Committed by
Gerrit Code Review
Workaround for NoClassDefFound issue in Netty.
SimpleChannelInboundHandler generates `message` instance check code on the fly, using JavaAssist. Which was not working, when a new Connection was created on the thread outside of NettyMessagingManager bundle, which did not have access to netty classes. - Implemented equivalent for SimpleChannelInboundHandler<InternaleMessage> without specifying type parameter, avoiding on the fly code generation. Other changes: - Add a method in IpAddress to return InetAddress instance. Change-Id: Ie97294a5650683457b9395e773269c5232d8e602
Showing
5 changed files
with
49 additions
and
26 deletions
| ... | @@ -23,5 +23,4 @@ osgi_jar_with_tests ( | ... | @@ -23,5 +23,4 @@ osgi_jar_with_tests ( |
| 23 | deps = COMPILE_DEPS, | 23 | deps = COMPILE_DEPS, |
| 24 | test_deps = TEST_DEPS, | 24 | test_deps = TEST_DEPS, |
| 25 | visibility = ['PUBLIC'], | 25 | visibility = ['PUBLIC'], |
| 26 | - dynamicimport_packages = 'io.netty.*', | ||
| 27 | ) | 26 | ) | ... | ... |
| ... | @@ -116,22 +116,4 @@ | ... | @@ -116,22 +116,4 @@ |
| 116 | </dependency> | 116 | </dependency> |
| 117 | </dependencies> | 117 | </dependencies> |
| 118 | 118 | ||
| 119 | - <build> | ||
| 120 | - <plugins> | ||
| 121 | - | ||
| 122 | - <plugin> | ||
| 123 | - <groupId>org.apache.felix</groupId> | ||
| 124 | - <artifactId>maven-bundle-plugin</artifactId> | ||
| 125 | - <extensions>true</extensions> | ||
| 126 | - <configuration> | ||
| 127 | - <instructions> | ||
| 128 | - <DynamicImport-Package> | ||
| 129 | - io.netty.* | ||
| 130 | - </DynamicImport-Package> | ||
| 131 | - </instructions> | ||
| 132 | - </configuration> | ||
| 133 | - </plugin> | ||
| 134 | - </plugins> | ||
| 135 | - </build> | ||
| 136 | - | ||
| 137 | </project> | 119 | </project> | ... | ... |
| ... | @@ -32,7 +32,11 @@ import java.io.IOException; | ... | @@ -32,7 +32,11 @@ import java.io.IOException; |
| 32 | * Encode InternalMessage out into a byte buffer. | 32 | * Encode InternalMessage out into a byte buffer. |
| 33 | */ | 33 | */ |
| 34 | @Sharable | 34 | @Sharable |
| 35 | -public class MessageEncoder extends MessageToByteEncoder<InternalMessage> { | 35 | +public class MessageEncoder extends MessageToByteEncoder<Object> { |
| 36 | +// Effectively MessageToByteEncoder<InternalMessage>, | ||
| 37 | +// had to specify <Object> to avoid Class Loader not being able to find some classes. | ||
| 38 | + | ||
| 39 | + private final Logger log = LoggerFactory.getLogger(getClass()); | ||
| 36 | 40 | ||
| 37 | private final int preamble; | 41 | private final int preamble; |
| 38 | 42 | ||
| ... | @@ -41,14 +45,15 @@ public class MessageEncoder extends MessageToByteEncoder<InternalMessage> { | ... | @@ -41,14 +45,15 @@ public class MessageEncoder extends MessageToByteEncoder<InternalMessage> { |
| 41 | this.preamble = preamble; | 45 | this.preamble = preamble; |
| 42 | } | 46 | } |
| 43 | 47 | ||
| 44 | - private final Logger log = LoggerFactory.getLogger(getClass()); | ||
| 45 | 48 | ||
| 46 | @Override | 49 | @Override |
| 47 | protected void encode( | 50 | protected void encode( |
| 48 | ChannelHandlerContext context, | 51 | ChannelHandlerContext context, |
| 49 | - InternalMessage message, | 52 | + Object rawMessage, |
| 50 | ByteBuf out) throws Exception { | 53 | ByteBuf out) throws Exception { |
| 51 | 54 | ||
| 55 | + InternalMessage message = (InternalMessage) rawMessage; | ||
| 56 | + | ||
| 52 | out.writeInt(this.preamble); | 57 | out.writeInt(this.preamble); |
| 53 | 58 | ||
| 54 | // write time | 59 | // write time |
| ... | @@ -100,4 +105,10 @@ public class MessageEncoder extends MessageToByteEncoder<InternalMessage> { | ... | @@ -100,4 +105,10 @@ public class MessageEncoder extends MessageToByteEncoder<InternalMessage> { |
| 100 | } | 105 | } |
| 101 | context.close(); | 106 | context.close(); |
| 102 | } | 107 | } |
| 108 | + | ||
| 109 | + // Effectively same result as one generated by MessageToByteEncoder<InternalMessage> | ||
| 110 | + @Override | ||
| 111 | + public final boolean acceptOutboundMessage(Object msg) throws Exception { | ||
| 112 | + return msg instanceof InternalMessage; | ||
| 113 | + } | ||
| 103 | } | 114 | } | ... | ... |
| ... | @@ -41,7 +41,6 @@ import io.netty.channel.nio.NioEventLoopGroup; | ... | @@ -41,7 +41,6 @@ import io.netty.channel.nio.NioEventLoopGroup; |
| 41 | import io.netty.channel.socket.SocketChannel; | 41 | import io.netty.channel.socket.SocketChannel; |
| 42 | import io.netty.channel.socket.nio.NioServerSocketChannel; | 42 | import io.netty.channel.socket.nio.NioServerSocketChannel; |
| 43 | import io.netty.channel.socket.nio.NioSocketChannel; | 43 | import io.netty.channel.socket.nio.NioSocketChannel; |
| 44 | - | ||
| 45 | import org.apache.commons.pool.KeyedPoolableObjectFactory; | 44 | import org.apache.commons.pool.KeyedPoolableObjectFactory; |
| 46 | import org.apache.commons.pool.impl.GenericKeyedObjectPool; | 45 | import org.apache.commons.pool.impl.GenericKeyedObjectPool; |
| 47 | import org.apache.felix.scr.annotations.Activate; | 46 | import org.apache.felix.scr.annotations.Activate; |
| ... | @@ -383,7 +382,7 @@ public class NettyMessagingManager implements MessagingService { | ... | @@ -383,7 +382,7 @@ public class NettyMessagingManager implements MessagingService { |
| 383 | } | 382 | } |
| 384 | // Start the client. | 383 | // Start the client. |
| 385 | CompletableFuture<Channel> retFuture = new CompletableFuture<>(); | 384 | CompletableFuture<Channel> retFuture = new CompletableFuture<>(); |
| 386 | - ChannelFuture f = bootstrap.connect(ep.host().toString(), ep.port()); | 385 | + ChannelFuture f = bootstrap.connect(ep.host().toInetAddress(), ep.port()); |
| 387 | 386 | ||
| 388 | f.addListener(future -> { | 387 | f.addListener(future -> { |
| 389 | if (future.isSuccess()) { | 388 | if (future.isSuccess()) { |
| ... | @@ -491,10 +490,13 @@ public class NettyMessagingManager implements MessagingService { | ... | @@ -491,10 +490,13 @@ public class NettyMessagingManager implements MessagingService { |
| 491 | } | 490 | } |
| 492 | 491 | ||
| 493 | @ChannelHandler.Sharable | 492 | @ChannelHandler.Sharable |
| 494 | - private class InboundMessageDispatcher extends SimpleChannelInboundHandler<InternalMessage> { | 493 | + private class InboundMessageDispatcher extends SimpleChannelInboundHandler<Object> { |
| 494 | + // Effectively SimpleChannelInboundHandler<InternalMessage>, | ||
| 495 | + // had to specify <Object> to avoid Class Loader not being able to find some classes. | ||
| 495 | 496 | ||
| 496 | @Override | 497 | @Override |
| 497 | - protected void channelRead0(ChannelHandlerContext ctx, InternalMessage message) throws Exception { | 498 | + protected void channelRead0(ChannelHandlerContext ctx, Object rawMessage) throws Exception { |
| 499 | + InternalMessage message = (InternalMessage) rawMessage; | ||
| 498 | try { | 500 | try { |
| 499 | dispatchLocally(message); | 501 | dispatchLocally(message); |
| 500 | } catch (RejectedExecutionException e) { | 502 | } catch (RejectedExecutionException e) { |
| ... | @@ -507,7 +509,21 @@ public class NettyMessagingManager implements MessagingService { | ... | @@ -507,7 +509,21 @@ public class NettyMessagingManager implements MessagingService { |
| 507 | log.error("Exception inside channel handling pipeline.", cause); | 509 | log.error("Exception inside channel handling pipeline.", cause); |
| 508 | context.close(); | 510 | context.close(); |
| 509 | } | 511 | } |
| 512 | + | ||
| 513 | + /** | ||
| 514 | + * Returns true if the given message should be handled. | ||
| 515 | + * | ||
| 516 | + * @param msg inbound message | ||
| 517 | + * @return true if {@code msg} is {@link InternalMessage} instance. | ||
| 518 | + * | ||
| 519 | + * @see SimpleChannelInboundHandler#acceptInboundMessage(Object) | ||
| 520 | + */ | ||
| 521 | + @Override | ||
| 522 | + public final boolean acceptInboundMessage(Object msg) { | ||
| 523 | + return msg instanceof InternalMessage; | ||
| 510 | } | 524 | } |
| 525 | + } | ||
| 526 | + | ||
| 511 | private void dispatchLocally(InternalMessage message) throws IOException { | 527 | private void dispatchLocally(InternalMessage message) throws IOException { |
| 512 | if (message.preamble() != preamble) { | 528 | if (message.preamble() != preamble) { |
| 513 | log.debug("Received {} with invalid preamble from {}", message.type(), message.sender()); | 529 | log.debug("Received {} with invalid preamble from {}", message.type(), message.sender()); | ... | ... |
| ... | @@ -16,6 +16,7 @@ | ... | @@ -16,6 +16,7 @@ |
| 16 | package org.onlab.packet; | 16 | package org.onlab.packet; |
| 17 | 17 | ||
| 18 | import java.net.InetAddress; | 18 | import java.net.InetAddress; |
| 19 | +import java.net.UnknownHostException; | ||
| 19 | import java.net.Inet4Address; | 20 | import java.net.Inet4Address; |
| 20 | import java.net.Inet6Address; | 21 | import java.net.Inet6Address; |
| 21 | import java.nio.ByteBuffer; | 22 | import java.nio.ByteBuffer; |
| ... | @@ -142,6 +143,20 @@ public class IpAddress implements Comparable<IpAddress> { | ... | @@ -142,6 +143,20 @@ public class IpAddress implements Comparable<IpAddress> { |
| 142 | } | 143 | } |
| 143 | 144 | ||
| 144 | /** | 145 | /** |
| 146 | + * Returns the IP address as InetAddress. | ||
| 147 | + * | ||
| 148 | + * @return InetAddress | ||
| 149 | + */ | ||
| 150 | + public InetAddress toInetAddress() { | ||
| 151 | + try { | ||
| 152 | + return InetAddress.getByAddress(octets); | ||
| 153 | + } catch (UnknownHostException e) { | ||
| 154 | + // Should never reach here | ||
| 155 | + return null; | ||
| 156 | + } | ||
| 157 | + } | ||
| 158 | + | ||
| 159 | + /** | ||
| 145 | * Computes the IP address byte length for a given IP version. | 160 | * Computes the IP address byte length for a given IP version. |
| 146 | * | 161 | * |
| 147 | * @param version the IP version | 162 | * @param version the IP version | ... | ... |
-
Please register or login to post a comment