You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@camel.apache.org by Stanislaw Kulczycki <gr...@kce.one.pl> on 2015/03/13 12:51:23 UTC

Camel-SJMS: Null pointer exception when sending a message (+ proposed patch)

Hi All,

sorry for spamming around SJMS component but I'm having issues with it :-(
Now I'm getting NPE when I'm trying to send a message with content created
using POJO created with JAXB.

I think that it is a bug in the JmsMessageHelper with results in Null
Pointer exceptions.

It looks like the function:
JmsMessageHelper.discoverMessageTypeFromPayload(payload) can return type of
JmsMessageType.Message but this type is not supported by the caller
createMessage method.
JmsMessageType.Message is returned in two cases when body payload is either
"null" or unknown type.

Extract from the function:
(...)
private static Message createMessage(Session session, Object payload,
Map<String, Object> messageHeaders, KeyFormatStrategy keyFormatStrategy,
TypeConverter typeConverter) throws Exception {
        Message answer = null;
        JmsMessageType messageType =
JmsMessageHelper.discoverMessageTypeFromPayload(payload);
        try {

            switch (messageType) {
            case Bytes:
				(...)
            case Map:
                (...)
            case Object:
                (...)
            case Text:
                (...)
            case Stream:
                (...)
			////////////////////////////////////////
			/////////////// SK: WHERE IS case Message: ?
			////////////////////////////////////////
            default:
                break; // ? Unknown type is silently ignored. Wouldn't it be
better to default to Object type?
            }
        } catch (Exception e) {
            LOGGER.error("Error creating a message of type: {}",
messageType, e);
            throw e;
        }
        if (messageHeaders != null && !messageHeaders.isEmpty()) {
            answer = JmsMessageHelper.setJmsMessageHeaders(answer,
messageHeaders, keyFormatStrategy);
        }
        return answer;
    }
	(...)
	


This problem can be reproduced with this unit test (tested on 2.14.0):

    @Test
    public void testCreationOfUnknownPayloadType() throws Exception {
        Connection conn = connectionFactory.createConnection();
        Session session = conn.createSession(false,
Session.AUTO_ACKNOWLEDGE);
        
        Map<String, Object> sampleMap = new HashMap<String, Object>();
        sampleMap.put("test", 5L);
        
        Message msg = JmsMessageHelper.createMessage(session, null,
sampleMap, null);
        session.close();
        
        conn.close();
    }

I guess it would be enough to do this in order to fix the problem (Patch
works with 2.14.x and 2.15.0):

$ diff -c JmsMessageHelper.java.org JmsMessageHelper.java
*** JmsMessageHelper.java.org   2015-03-07 04:20:32.000000000 +0100
--- JmsMessageHelper.java       2015-03-13 12:00:17.791081500 +0100
***************
*** 195,200 ****
--- 195,210 ----
                  }
                  answer = streamMessage;
                  break;
+             case Message:
+                 if (payload == null) {
+                     // Create empty message       
+                     answer = session.createMessage();
+                 } else {
+                     // Throw exception as there is a playload but it is
not supported by JMS
+                     throw new JMSException("Unsupported message payload
type");
+                 }
+                 break;
              default:
                  break;
              }

Unit test for Camel 2.14.x (Unfortunately in Camel 2.15.0 it got more
complex to test createMessage function) because of need of SjmsEndpoint as
parameter:
WARNING!: This test will fail on 2.15.0 !!! as API has changed. I guess I
could port it to newer version but first please confirm that fix is "valid".

package org.apache.camel.component.sjms.bugfixes;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import org.apache.camel.component.sjms.jms.*;
import javax.jms.Connection;
import javax.jms.Message;
import javax.jms.Session;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.camel.test.junit4.TestSupport;
import org.junit.After;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import org.junit.Before;
import org.junit.Test;

public class JmsMessageHelperNpe {
    private ActiveMQConnectionFactory connectionFactory;

    @Before
    public void setup() {
        connectionFactory = new
ActiveMQConnectionFactory("vm://broker?broker.persistent=false&broker.useJmx=false");
    }

    @After
    public void teardown() {
        connectionFactory = null;
    }

    @Test
    public void testCreationOfNullpayloadMessage() throws Exception {
        Connection connection = connectionFactory.createConnection();
        assertNotNull(connection);
        Session session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
        assertNotNull(session);
        
        Map<String, Object> sampleMap = new HashMap<String, Object>();
        sampleMap.put("test", 5L);
        
        Object nullObject = null;
        
        Message msg = JmsMessageHelper.createMessage(session, nullObject,
sampleMap, null);
        assertNotNull(msg);
        session.close();
        
        connection.close();
    }
    
        
    @Test
    public void testCreationOfUnknownPayloadMessage() throws Exception {
        Connection connection = connectionFactory.createConnection();
        assertNotNull(connection);
        Session session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
        assertNotNull(session);
        
        Map<String, Object> sampleMap = new HashMap<String, Object>();
        sampleMap.put("test", 5L);
        
        Object helloWorld = new Object() {
            private Integer someValue = 5;
        };
        
        try {
            Message msg = JmsMessageHelper.createMessage(session,
helloWorld, sampleMap, null);
            fail("Exception is expected");
        } catch (Exception e) {            
            TestSupport.assertStringContains(e.getMessage(), "Unsupported
message payload type");
        }
       
        
        session.close();
        
        connection.close();
    }
}


Thanks & Kind regards,
Stan




--
View this message in context: http://camel.465427.n5.nabble.com/Camel-SJMS-Null-pointer-exception-when-sending-a-message-proposed-patch-tp5764093.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: Camel-SJMS: Null pointer exception when sending a message (+ proposed patch)

Posted by Claus Ibsen <cl...@gmail.com>.
Hi

Thanks for the suggestion, it has been changed.

On Sun, Mar 15, 2015 at 12:22 PM, Stanislaw Kulczycki <gr...@kce.one.pl> wrote:
> Hi
>
> Many thanks for this! I have just one more bit to add, I think that in code
> of JmsMessageHelper there should be something like this:
>
>         case Message:
>             if (allowNullBody && payload == null) {
>                 answer = session.createMessage();
>             } else if(payload != null) {
>                 throw new JMSException("Unsupported message body");
>             }
>             else {
>                 throw new JMSException("Null body is not allowed");
>             }
>
> You can get to this situation:
>           else if(payload != null) {
>                 throw new JMSException("Unsupported message body");
>             }
>
> if you add test from below to JMSMessageHelperTypeConversionTest:
> @Test
>     public void testJMSMessageHelperUnknownType() throws
> InterruptedException, FileNotFoundException {
>         class TestAnonymousClass {
>             private String testValue = "Hello Camel";
>
>             public String getTestValue() {
>                 return testValue;
>             }
>         };
>         try {
>             template.sendBody(SJMS_QUEUE_URI, new TestAnonymousClass());
>         } catch (Exception e) {
>             StringWriter sw = new StringWriter();
>             PrintWriter pw = new PrintWriter(sw);
>             e.printStackTrace(pw);
>             assertFalse(sw.toString().contains("Null body is not allowed"));
> //            assertStringContains(sw.toString(), "Unsupported message body"
> );
>         }
>     }
>
> And it looks strange when you send non empty message body and get stacktrace
> like this:
>         at
> org.apache.camel.impl.DefaultProducerTemplate.sendBody(DefaultProducerTemplate.java:137)
>         ... 30 more
> Caused by: javax.jms.JMSException: Null body is not allowed
>         at
> org.apache.camel.component.sjms.jms.JmsMessageHelper.createMessage(JmsMessageHelper.java:202)
>         at
> org.apache.camel.component.sjms.jms.JmsMessageHelper.createMessage(JmsMessageHelper.java:156)
>
> Kind regards,
> Stan
>
>
>
> --
> View this message in context: http://camel.465427.n5.nabble.com/Camel-SJMS-Null-pointer-exception-when-sending-a-message-proposed-patch-tp5764093p5764186.html
> Sent from the Camel - Users mailing list archive at Nabble.com.



-- 
Claus Ibsen
-----------------
Red Hat, Inc.
Email: cibsen@redhat.com
Twitter: davsclaus
Blog: http://davsclaus.com
Author of Camel in Action: http://www.manning.com/ibsen
hawtio: http://hawt.io/
fabric8: http://fabric8.io/

Re: Camel-SJMS: Null pointer exception when sending a message (+ proposed patch)

Posted by Stanislaw Kulczycki <gr...@kce.one.pl>.
Hi

Many thanks for this! I have just one more bit to add, I think that in code
of JmsMessageHelper there should be something like this:

        case Message:
            if (allowNullBody && payload == null) {
                answer = session.createMessage();
            } else if(payload != null) {
                throw new JMSException("Unsupported message body");
            }
            else {
                throw new JMSException("Null body is not allowed");
            }

You can get to this situation:
          else if(payload != null) {
                throw new JMSException("Unsupported message body");
            }

if you add test from below to JMSMessageHelperTypeConversionTest: 
@Test
    public void testJMSMessageHelperUnknownType() throws
InterruptedException, FileNotFoundException {
        class TestAnonymousClass {
            private String testValue = "Hello Camel";
            
            public String getTestValue() {
                return testValue;
            }            
        };        
        try {
            template.sendBody(SJMS_QUEUE_URI, new TestAnonymousClass());
        } catch (Exception e) {
            StringWriter sw = new StringWriter();
            PrintWriter pw = new PrintWriter(sw);
            e.printStackTrace(pw);
            assertFalse(sw.toString().contains("Null body is not allowed"));
//            assertStringContains(sw.toString(), "Unsupported message body"
);
        }        
    }

And it looks strange when you send non empty message body and get stacktrace
like this:
	at
org.apache.camel.impl.DefaultProducerTemplate.sendBody(DefaultProducerTemplate.java:137)
	... 30 more
Caused by: javax.jms.JMSException: Null body is not allowed
	at
org.apache.camel.component.sjms.jms.JmsMessageHelper.createMessage(JmsMessageHelper.java:202)
	at
org.apache.camel.component.sjms.jms.JmsMessageHelper.createMessage(JmsMessageHelper.java:156)

Kind regards,
Stan



--
View this message in context: http://camel.465427.n5.nabble.com/Camel-SJMS-Null-pointer-exception-when-sending-a-message-proposed-patch-tp5764093p5764186.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: Camel-SJMS: Null pointer exception when sending a message (+ proposed patch)

Posted by Claus Ibsen <cl...@gmail.com>.
Hi

Thanks for reporting. I have logged a ticket to allow null body like
camel-jms can do
https://issues.apache.org/jira/browse/CAMEL-8489

On Fri, Mar 13, 2015 at 12:51 PM, Stanislaw Kulczycki <gr...@kce.one.pl> wrote:
> Hi All,
>
> sorry for spamming around SJMS component but I'm having issues with it :-(
> Now I'm getting NPE when I'm trying to send a message with content created
> using POJO created with JAXB.
>
> I think that it is a bug in the JmsMessageHelper with results in Null
> Pointer exceptions.
>
> It looks like the function:
> JmsMessageHelper.discoverMessageTypeFromPayload(payload) can return type of
> JmsMessageType.Message but this type is not supported by the caller
> createMessage method.
> JmsMessageType.Message is returned in two cases when body payload is either
> "null" or unknown type.
>
> Extract from the function:
> (...)
> private static Message createMessage(Session session, Object payload,
> Map<String, Object> messageHeaders, KeyFormatStrategy keyFormatStrategy,
> TypeConverter typeConverter) throws Exception {
>         Message answer = null;
>         JmsMessageType messageType =
> JmsMessageHelper.discoverMessageTypeFromPayload(payload);
>         try {
>
>             switch (messageType) {
>             case Bytes:
>                                 (...)
>             case Map:
>                 (...)
>             case Object:
>                 (...)
>             case Text:
>                 (...)
>             case Stream:
>                 (...)
>                         ////////////////////////////////////////
>                         /////////////// SK: WHERE IS case Message: ?
>                         ////////////////////////////////////////
>             default:
>                 break; // ? Unknown type is silently ignored. Wouldn't it be
> better to default to Object type?
>             }
>         } catch (Exception e) {
>             LOGGER.error("Error creating a message of type: {}",
> messageType, e);
>             throw e;
>         }
>         if (messageHeaders != null && !messageHeaders.isEmpty()) {
>             answer = JmsMessageHelper.setJmsMessageHeaders(answer,
> messageHeaders, keyFormatStrategy);
>         }
>         return answer;
>     }
>         (...)
>
>
>
> This problem can be reproduced with this unit test (tested on 2.14.0):
>
>     @Test
>     public void testCreationOfUnknownPayloadType() throws Exception {
>         Connection conn = connectionFactory.createConnection();
>         Session session = conn.createSession(false,
> Session.AUTO_ACKNOWLEDGE);
>
>         Map<String, Object> sampleMap = new HashMap<String, Object>();
>         sampleMap.put("test", 5L);
>
>         Message msg = JmsMessageHelper.createMessage(session, null,
> sampleMap, null);
>         session.close();
>
>         conn.close();
>     }
>
> I guess it would be enough to do this in order to fix the problem (Patch
> works with 2.14.x and 2.15.0):
>
> $ diff -c JmsMessageHelper.java.org JmsMessageHelper.java
> *** JmsMessageHelper.java.org   2015-03-07 04:20:32.000000000 +0100
> --- JmsMessageHelper.java       2015-03-13 12:00:17.791081500 +0100
> ***************
> *** 195,200 ****
> --- 195,210 ----
>                   }
>                   answer = streamMessage;
>                   break;
> +             case Message:
> +                 if (payload == null) {
> +                     // Create empty message
> +                     answer = session.createMessage();
> +                 } else {
> +                     // Throw exception as there is a playload but it is
> not supported by JMS
> +                     throw new JMSException("Unsupported message payload
> type");
> +                 }
> +                 break;
>               default:
>                   break;
>               }
>
> Unit test for Camel 2.14.x (Unfortunately in Camel 2.15.0 it got more
> complex to test createMessage function) because of need of SjmsEndpoint as
> parameter:
> WARNING!: This test will fail on 2.15.0 !!! as API has changed. I guess I
> could port it to newer version but first please confirm that fix is "valid".
>
> package org.apache.camel.component.sjms.bugfixes;
>
> import java.io.Serializable;
> import java.util.HashMap;
> import java.util.Map;
> import org.apache.camel.component.sjms.jms.*;
> import javax.jms.Connection;
> import javax.jms.Message;
> import javax.jms.Session;
>
> import org.apache.activemq.ActiveMQConnectionFactory;
> import org.apache.camel.test.junit4.TestSupport;
> import org.junit.After;
> import static org.junit.Assert.assertNotNull;
> import static org.junit.Assert.fail;
> import org.junit.Before;
> import org.junit.Test;
>
> public class JmsMessageHelperNpe {
>     private ActiveMQConnectionFactory connectionFactory;
>
>     @Before
>     public void setup() {
>         connectionFactory = new
> ActiveMQConnectionFactory("vm://broker?broker.persistent=false&broker.useJmx=false");
>     }
>
>     @After
>     public void teardown() {
>         connectionFactory = null;
>     }
>
>     @Test
>     public void testCreationOfNullpayloadMessage() throws Exception {
>         Connection connection = connectionFactory.createConnection();
>         assertNotNull(connection);
>         Session session = connection.createSession(false,
> Session.AUTO_ACKNOWLEDGE);
>         assertNotNull(session);
>
>         Map<String, Object> sampleMap = new HashMap<String, Object>();
>         sampleMap.put("test", 5L);
>
>         Object nullObject = null;
>
>         Message msg = JmsMessageHelper.createMessage(session, nullObject,
> sampleMap, null);
>         assertNotNull(msg);
>         session.close();
>
>         connection.close();
>     }
>
>
>     @Test
>     public void testCreationOfUnknownPayloadMessage() throws Exception {
>         Connection connection = connectionFactory.createConnection();
>         assertNotNull(connection);
>         Session session = connection.createSession(false,
> Session.AUTO_ACKNOWLEDGE);
>         assertNotNull(session);
>
>         Map<String, Object> sampleMap = new HashMap<String, Object>();
>         sampleMap.put("test", 5L);
>
>         Object helloWorld = new Object() {
>             private Integer someValue = 5;
>         };
>
>         try {
>             Message msg = JmsMessageHelper.createMessage(session,
> helloWorld, sampleMap, null);
>             fail("Exception is expected");
>         } catch (Exception e) {
>             TestSupport.assertStringContains(e.getMessage(), "Unsupported
> message payload type");
>         }
>
>
>         session.close();
>
>         connection.close();
>     }
> }
>
>
> Thanks & Kind regards,
> Stan
>
>
>
>
> --
> View this message in context: http://camel.465427.n5.nabble.com/Camel-SJMS-Null-pointer-exception-when-sending-a-message-proposed-patch-tp5764093.html
> Sent from the Camel - Users mailing list archive at Nabble.com.



-- 
Claus Ibsen
-----------------
Red Hat, Inc.
Email: cibsen@redhat.com
Twitter: davsclaus
Blog: http://davsclaus.com
Author of Camel in Action: http://www.manning.com/ibsen
hawtio: http://hawt.io/
fabric8: http://fabric8.io/