Bug 1373 - Fixed NullPointerException on incorrect input 15/9115/2
authorMichal Polkorab <michal.polkorab@pantheon.sk>
Thu, 17 Jul 2014 10:21:38 +0000 (12:21 +0200)
committerMichal Polkorab <michal.polkorab@pantheon.sk>
Thu, 17 Jul 2014 12:49:08 +0000 (14:49 +0200)
 - now throws IllegalArgumentException. This is just logged and pushed into Future, the Future delegates the information further to upper ODL layers

Change-Id: I64ac1e4904e8837ab5b26572235bdaf5fac984da
Signed-off-by: Michal Polkorab <michal.polkorab@pantheon.sk>
openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/connection/ChannelOutboundQueue.java
openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/connection/MessageListenerWrapper.java [new file with mode: 0644]
openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/core/OFEncoder.java
openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/deserialization/DeserializerRegistryImpl.java
openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/SerializerRegistryImpl.java
openflow-protocol-impl/src/test/java/org/opendaylight/openflowjava/protocol/impl/core/OFEncoderTest.java

index 765a979434d89c2f7e8d5b0f88512152a9e6152a..40af2791407451c89f8e7d75debc95055cf77733 100644 (file)
@@ -180,8 +180,8 @@ final class ChannelOutboundQueue extends ChannelInboundHandlerAdapter {
                 break;
             }
 
-            final ChannelFuture p = channel.write(h.takeMessage());
             final GenericFutureListener<Future<Void>> l = h.takeListener();
+            final ChannelFuture p = channel.write(new MessageListenerWrapper(h.takeMessage(), l));
             if (l != null) {
                 p.addListener(l);
             }
diff --git a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/connection/MessageListenerWrapper.java b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/connection/MessageListenerWrapper.java
new file mode 100644 (file)
index 0000000..68311d2
--- /dev/null
@@ -0,0 +1,50 @@
+/*\r
+ * Copyright (c) 2014 Pantheon Technologies s.r.o. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+\r
+package org.opendaylight.openflowjava.protocol.impl.connection;\r
+\r
+import io.netty.util.concurrent.Future;\r
+import io.netty.util.concurrent.GenericFutureListener;\r
+\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;\r
+\r
+/**\r
+ * Wraps outgoing message and includes listener attached to this message. This object\r
+ * is sent to OFEncoder. When OFEncoder fails to serialize the message,\r
+ * listener is filled with exception. The exception is then delegated to upper ODL layers. \r
+ * @author michal.polkorab\r
+ */\r
+public class MessageListenerWrapper {\r
+\r
+    private OfHeader msg;\r
+    private GenericFutureListener<Future<Void>> listener;\r
+\r
+    /**\r
+     * @param msg outgoing message\r
+     * @param listener listener attached to channel.write(msg) Future\r
+     */\r
+    public MessageListenerWrapper(Object msg, GenericFutureListener<Future<Void>> listener) {\r
+        this.msg = (OfHeader) msg;\r
+        this.listener = listener;\r
+    }\r
+\r
+    /**\r
+     * @return outgoing message (downstream)\r
+     */\r
+    public OfHeader getMsg() {\r
+        return msg;\r
+    }\r
+\r
+    \r
+    /**\r
+     * @return listener listening on message sending success / failure\r
+     */\r
+    public GenericFutureListener<Future<Void>> getListener() {\r
+        return listener;\r
+    }\r
+}
\ No newline at end of file
index c93f1fcf5c0b10a487ee6e4303b8078389f16b52..6080003f99297b53374b8a0e7980df9e69d7112f 100644 (file)
@@ -11,9 +11,10 @@ package org.opendaylight.openflowjava.protocol.impl.core;
 import io.netty.buffer.ByteBuf;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.handler.codec.MessageToByteEncoder;
+import io.netty.util.concurrent.Future;
 
+import org.opendaylight.openflowjava.protocol.impl.connection.MessageListenerWrapper;
 import org.opendaylight.openflowjava.protocol.impl.serialization.SerializationFactory;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -22,7 +23,7 @@ import org.slf4j.LoggerFactory;
  * @author michal.polkorab
  * @author timotej.kubas
  */
-public class OFEncoder extends MessageToByteEncoder<OfHeader> {
+public class OFEncoder extends MessageToByteEncoder<MessageListenerWrapper> {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(OFEncoder.class);
     private SerializationFactory serializationFactory;
@@ -33,14 +34,15 @@ public class OFEncoder extends MessageToByteEncoder<OfHeader> {
     }
 
     @Override
-    protected void encode(ChannelHandlerContext ctx, OfHeader msg, ByteBuf out)
+    protected void encode(ChannelHandlerContext ctx, MessageListenerWrapper wrapper, ByteBuf out)
             throws Exception {
         LOGGER.trace("Encoding");
         try {
-            serializationFactory.messageToBuffer(msg.getVersion(), out, msg);
+            serializationFactory.messageToBuffer(wrapper.getMsg().getVersion(), out, wrapper.getMsg());
         } catch(Exception e) {
-            LOGGER.error("Message serialization failed");
-            LOGGER.error(e.getMessage(), e);
+            LOGGER.warn("Message serialization failed: {}", e.getMessage());
+            Future<Void> newFailedFuture = ctx.newFailedFuture(e);
+            wrapper.getListener().operationComplete(newFailedFuture);
             out.clear();
             return;
         }
index f78dbb85f188193bc5b09a754414426e3de6a17f..a1efd1dc37a763154886e56b05dd4c96d1c3abbe 100644 (file)
@@ -59,7 +59,7 @@ public class DeserializerRegistryImpl implements DeserializerRegistry {
         OFGeneralDeserializer deserializer = registry.get(key);
         if (deserializer == null) {
             throw new NullPointerException("Deserializer for key: " + key.toString()
-                    + " was not found");
+                    + " was not found - please verify that all needed deserializers ale loaded correctly");
         }
         return (DESERIALIZER_TYPE) deserializer;
     }
@@ -68,7 +68,7 @@ public class DeserializerRegistryImpl implements DeserializerRegistry {
     public void registerDeserializer(MessageCodeKey key,
             OFGeneralDeserializer deserializer) {
         if ((key == null) || (deserializer == null)) {
-            throw new NullPointerException("MessageCodeKey or Deserializer is null");
+            throw new IllegalArgumentException("MessageCodeKey or Deserializer is null");
         }
         if (deserializer instanceof DeserializerRegistryInjector) {
             ((DeserializerRegistryInjector) deserializer).injectDeserializerRegistry(this);
@@ -79,7 +79,7 @@ public class DeserializerRegistryImpl implements DeserializerRegistry {
     @Override
     public boolean unregisterDeserializer(MessageCodeKey key) {
         if (key == null) {
-            throw new NullPointerException("MessageCodeKey is null");
+            throw new IllegalArgumentException("MessageCodeKey is null");
         }
         OFGeneralDeserializer deserializer = registry.remove(key);
         if (deserializer == null) {
index 47b2d4a5efc60dcf9309e9c2d56848c84315fe5c..e8a02bd78e4811743f2f74e7606d2277c5e24e4e 100644 (file)
@@ -61,8 +61,9 @@ public class SerializerRegistryImpl implements SerializerRegistry {
             MessageTypeKey<KEY_TYPE> msgTypeKey) {
         OFGeneralSerializer serializer = registry.get(msgTypeKey);
         if (serializer == null) {
-            throw new NullPointerException("Serializer for key: " + msgTypeKey.toString()
-                    + " was not found");
+            throw new IllegalArgumentException("Serializer for key: {}" + msgTypeKey.toString()
+                    + " was not found - please verify that you are using correct message"
+                    + " combination (e.g. OF v1.0 message to OF v1.0 device)");
         }
         return (SERIALIZER_TYPE) serializer;
     }
@@ -71,7 +72,7 @@ public class SerializerRegistryImpl implements SerializerRegistry {
     public <KEY_TYPE> void registerSerializer(
             MessageTypeKey<KEY_TYPE> msgTypeKey, OFGeneralSerializer serializer) {
         if ((msgTypeKey == null) || (serializer == null)) {
-            throw new NullPointerException("MessageTypeKey or Serializer is null");
+            throw new IllegalArgumentException("MessageTypeKey or Serializer is null");
         }
         if (serializer instanceof SerializerRegistryInjector) {
             ((SerializerRegistryInjector) serializer).injectSerializerRegistry(this);
@@ -82,7 +83,7 @@ public class SerializerRegistryImpl implements SerializerRegistry {
     @Override
     public <KEY_TYPE> boolean unregisterSerializer(MessageTypeKey<KEY_TYPE> msgTypeKey) {
         if (msgTypeKey == null) {
-            throw new NullPointerException("MessageTypeKey is null");
+            throw new IllegalArgumentException("MessageTypeKey is null");
         }
         OFGeneralSerializer serializer = registry.remove(msgTypeKey);
         if (serializer == null) {
index 11d2098a5abae214801cb92bf879d56c3b6834ab..9cb7dca044fdbbee9a843f3d92eecd653273b0fe 100644 (file)
@@ -16,12 +16,16 @@ import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 import io.netty.buffer.ByteBuf;
 import io.netty.channel.ChannelHandlerContext;
+import io.netty.util.concurrent.Future;
+import io.netty.util.concurrent.GenericFutureListener;
 
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.openflowjava.protocol.impl.connection.MessageListenerWrapper;
 import org.opendaylight.openflowjava.protocol.impl.serialization.SerializationFactory;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
 import org.opendaylight.yangtools.yang.binding.DataObject;
@@ -34,8 +38,11 @@ public class OFEncoderTest {
 
     @Mock ChannelHandlerContext mockChHndlrCtx ;
     @Mock SerializationFactory mockSerializationFactory ;
+    @Mock MessageListenerWrapper wrapper;
     @Mock OfHeader mockMsg ;
     @Mock ByteBuf mockOut ;
+    @Mock Future<Void> future;
+    @Mock GenericFutureListener<Future<Void>> listener;
 
     OFEncoder ofEncoder = new OFEncoder() ;
 
@@ -55,8 +62,10 @@ public class OFEncoderTest {
     @Test
     public void testEncodeSuccess() {
         when(mockOut.readableBytes()).thenReturn(1);
+        when(wrapper.getMsg()).thenReturn(mockMsg);
+        when(wrapper.getMsg().getVersion()).thenReturn((short) EncodeConstants.OF13_VERSION_ID);
         try {
-            ofEncoder.encode(mockChHndlrCtx, mockMsg, mockOut);
+            ofEncoder.encode(mockChHndlrCtx, wrapper, mockOut);
         } catch (Exception e) {
             Assert.fail();
         }
@@ -70,9 +79,12 @@ public class OFEncoderTest {
      */
     @Test
     public void testEncodeSerializationException() {
+        when(wrapper.getMsg()).thenReturn(mockMsg);
+        when(wrapper.getListener()).thenReturn(listener);
+        when(wrapper.getMsg().getVersion()).thenReturn((short) EncodeConstants.OF13_VERSION_ID);
         doThrow(new IllegalArgumentException()).when(mockSerializationFactory).messageToBuffer(anyShort(),any(ByteBuf.class), any(DataObject.class));
         try {
-            ofEncoder.encode(mockChHndlrCtx, mockMsg, mockOut);
+            ofEncoder.encode(mockChHndlrCtx, wrapper, mockOut);
         } catch (Exception e) {
             Assert.fail();
         }
@@ -87,8 +99,10 @@ public class OFEncoderTest {
     @Test
     public void testEncodeSerializesNoBytes() {
         when(mockOut.readableBytes()).thenReturn(0);
+        when(wrapper.getMsg()).thenReturn(mockMsg);
+        when(wrapper.getMsg().getVersion()).thenReturn((short) EncodeConstants.OF13_VERSION_ID);
         try {
-            ofEncoder.encode(mockChHndlrCtx, mockMsg, mockOut);
+            ofEncoder.encode(mockChHndlrCtx, wrapper, mockOut);
         } catch (Exception e) {
             Assert.fail();
         }