You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@camel.apache.org by Tim <ch...@gmail.com> on 2010/11/17 01:25:21 UTC

Error in MessageSupport when using JMSMessage

This is essentially a different incantation of CAMEL-2436
(https://issues.apache.org/activemq/browse/CAMEL-2436)
A test case that reproduces the issue is below.
If you have a bean that returns null when processing the body of a
JMSMessage you will not get the null in the next endpoint but rather
the original message itself.
One really hacky way around this bug is to replace the JMSMessage with
a DefaultMessage by adding a processor

                    .process(
                        new Processor() {
                            @Override
                            public void process(@NotNull Exchange
anExchange) throws Exception {
                                final DefaultMessage myIn = new
DefaultMessage();
                                myIn.setBody(anExchange.getIn().getBody());
                                anExchange.setIn(myIn);
                            }
                        }
                    )

Into the below code after the from()


import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.command.ActiveMQObjectMessage;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.jms.JmsComponent;
import org.apache.camel.component.jms.JmsMessage;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.test.junit4.CamelTestSupport;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.junit.Test;

import javax.jms.JMSException;

public class C2436Test extends CamelTestSupport {
    private static final String ENDPOINT1 = "jms:mock";
    private static final String ENDPOINT2 = "mock:results";
    private static final String TEST_CONTENT = "My Test Content";

    @NotNull
    @Override
    protected RouteBuilder createRouteBuilder() throws Exception {
        context.addComponent("jms", JmsComponent.jmsComponent(new
ActiveMQConnectionFactory("vm://localhost")));

        return new RouteBuilder() {
            @Override
            public void configure() throws Exception {
                from(ENDPOINT1)
                    .bean(new ReturnsNull())
                    .filter(body().isNull())
                        .log("stopping:${body}")
                            .stop()
                        .end()
                    .log("not-stopping:${body}")
                    .to(ENDPOINT2);
            }
        };
    }

    @Test
    public void testRoutePassing() throws InterruptedException, JMSException {
        final MockEndpoint myMockEndpoint = getMockEndpoint(ENDPOINT2);

        myMockEndpoint.expectedMessageCount(1);
        myMockEndpoint.allMessages().body().isNull();

        final ActiveMQObjectMessage myMessage = new ActiveMQObjectMessage();
        myMessage.setObject(TEST_CONTENT);

        template.send(ENDPOINT1, new Processor() {
            @Override
            public void process(@NotNull Exchange anExchange) throws Exception {
                anExchange.setIn(new JmsMessage(myMessage, null));
            }
        });

        myMockEndpoint.assertIsSatisfied();
    }

    public class ReturnsNull {
        @Nullable
        public String processMessage(@NotNull String aMessage) {
            return null;
        }
    }
}

Re: Error in MessageSupport when using JMSMessage

Posted by Claus Ibsen <cl...@gmail.com>.
On Mon, Nov 22, 2010 at 4:14 PM, Tim <ch...@gmail.com> wrote:
> Yea I thought about that but isn't that a hack solution as it now ties
> you to Camel in what was just a pojo?
>

Yeah that would tie it to the Camel API.

I have created a ticket
https://issues.apache.org/activemq/browse/CAMEL-3354

To see if we can allow the null behavior your need.


> On Mon, Nov 22, 2010 at 8:57 AM, Claus Ibsen <cl...@gmail.com> wrote:
>> Then return an empty Message object instead of null.
>>
>>
>>
>> On Mon, Nov 22, 2010 at 3:55 PM, Tim <ch...@gmail.com> wrote:
>>> Sorry Claus, Maybe I didn't represent the problem correctly.
>>> I DO want to alter the body. In this case the result of processing the
>>> body should be null.
>>>
>>> Think of this example (not exactly my case but definitely something
>>> that may be helpful).
>>>
>>> I have a route that says:
>>>
>>> from("jms:queue:processKey") #1
>>>   .bean("cacheValueExtractor") #2
>>>     .filter(body().isNull().log("not processing because value was not
>>> in cache").stop().end() #3
>>>     .bean("beanWillProcessFromValueLookedUpFromCache")..... #4
>>>
>>> In this case I'm sending a key (or maybe the name of a command) to be
>>> processed. (#1)
>>> The key maps some value in a cache (or is the key to a command that
>>> should be executed) which should be processed. (#2)
>>> If the value is not in the cache when looked up in
>>> "cacheValueExtractor" you would return null as the object looked up.
>>> Just so that beanWillProcessFromValueLookedUpFromCache will not have
>>> to worry about invalid keys, we can add a filter (or choose) that the
>>> value extracted was not null. (#3&4)
>>> In this case it won't work though since JMSMessage will replace the
>>> null returned from #2 and replace it with the original message (the
>>> key in this case).
>>>
>>> On Mon, Nov 22, 2010 at 7:42 AM, Claus Ibsen <cl...@gmail.com> wrote:
>>>> On Wed, Nov 17, 2010 at 9:59 PM, Tim <ch...@gmail.com> wrote:
>>>>> BTW, this is an error in logic in MessageSupport when interoperating
>>>>> with JMSMessage it seems. I'm not quite sure what the intention was
>>>>> when having it copy the old body over on null.
>>>>>
>>>>> Can a committer please either confirm this as a bug (and I can try to
>>>>> patch that would fix this without breaking other intended
>>>>> functionality) or explain to me why this is not a bug if it was
>>>>> designed this way?
>>>>>
>>>>
>>>> Its designed that way. If you dont want to alter the body using beans,
>>>> then use a void method.
>>>>
>>>>
>>>>> Thanks
>>>>> -Tim
>>>>>
>>>>> On Tue, Nov 16, 2010 at 6:25 PM, Tim <ch...@gmail.com> wrote:
>>>>>> This is essentially a different incantation of CAMEL-2436
>>>>>> (https://issues.apache.org/activemq/browse/CAMEL-2436)
>>>>>> A test case that reproduces the issue is below.
>>>>>> If you have a bean that returns null when processing the body of a
>>>>>> JMSMessage you will not get the null in the next endpoint but rather
>>>>>> the original message itself.
>>>>>> One really hacky way around this bug is to replace the JMSMessage with
>>>>>> a DefaultMessage by adding a processor
>>>>>>
>>>>>>                    .process(
>>>>>>                        new Processor() {
>>>>>>                            @Override
>>>>>>                            public void process(@NotNull Exchange
>>>>>> anExchange) throws Exception {
>>>>>>                                final DefaultMessage myIn = new
>>>>>> DefaultMessage();
>>>>>>                                myIn.setBody(anExchange.getIn().getBody());
>>>>>>                                anExchange.setIn(myIn);
>>>>>>                            }
>>>>>>                        }
>>>>>>                    )
>>>>>>
>>>>>> Into the below code after the from()
>>>>>>
>>>>>>
>>>>>> import org.apache.activemq.ActiveMQConnectionFactory;
>>>>>> import org.apache.activemq.command.ActiveMQObjectMessage;
>>>>>> import org.apache.camel.Exchange;
>>>>>> import org.apache.camel.Processor;
>>>>>> import org.apache.camel.builder.RouteBuilder;
>>>>>> import org.apache.camel.component.jms.JmsComponent;
>>>>>> import org.apache.camel.component.jms.JmsMessage;
>>>>>> import org.apache.camel.component.mock.MockEndpoint;
>>>>>> import org.apache.camel.test.junit4.CamelTestSupport;
>>>>>> import org.jetbrains.annotations.NotNull;
>>>>>> import org.jetbrains.annotations.Nullable;
>>>>>> import org.junit.Test;
>>>>>>
>>>>>> import javax.jms.JMSException;
>>>>>>
>>>>>> public class C2436Test extends CamelTestSupport {
>>>>>>    private static final String ENDPOINT1 = "jms:mock";
>>>>>>    private static final String ENDPOINT2 = "mock:results";
>>>>>>    private static final String TEST_CONTENT = "My Test Content";
>>>>>>
>>>>>>    @NotNull
>>>>>>    @Override
>>>>>>    protected RouteBuilder createRouteBuilder() throws Exception {
>>>>>>        context.addComponent("jms", JmsComponent.jmsComponent(new
>>>>>> ActiveMQConnectionFactory("vm://localhost")));
>>>>>>
>>>>>>        return new RouteBuilder() {
>>>>>>            @Override
>>>>>>            public void configure() throws Exception {
>>>>>>                from(ENDPOINT1)
>>>>>>                    .bean(new ReturnsNull())
>>>>>>                    .filter(body().isNull())
>>>>>>                        .log("stopping:${body}")
>>>>>>                            .stop()
>>>>>>                        .end()
>>>>>>                    .log("not-stopping:${body}")
>>>>>>                    .to(ENDPOINT2);
>>>>>>            }
>>>>>>        };
>>>>>>    }
>>>>>>
>>>>>>    @Test
>>>>>>    public void testRoutePassing() throws InterruptedException, JMSException {
>>>>>>        final MockEndpoint myMockEndpoint = getMockEndpoint(ENDPOINT2);
>>>>>>
>>>>>>        myMockEndpoint.expectedMessageCount(1);
>>>>>>        myMockEndpoint.allMessages().body().isNull();
>>>>>>
>>>>>>        final ActiveMQObjectMessage myMessage = new ActiveMQObjectMessage();
>>>>>>        myMessage.setObject(TEST_CONTENT);
>>>>>>
>>>>>>        template.send(ENDPOINT1, new Processor() {
>>>>>>            @Override
>>>>>>            public void process(@NotNull Exchange anExchange) throws Exception {
>>>>>>                anExchange.setIn(new JmsMessage(myMessage, null));
>>>>>>            }
>>>>>>        });
>>>>>>
>>>>>>        myMockEndpoint.assertIsSatisfied();
>>>>>>    }
>>>>>>
>>>>>>    public class ReturnsNull {
>>>>>>        @Nullable
>>>>>>        public String processMessage(@NotNull String aMessage) {
>>>>>>            return null;
>>>>>>        }
>>>>>>    }
>>>>>> }
>>>>>>
>>>>>
>>>>
>>>>
>>>>
>>>> --
>>>> Claus Ibsen
>>>> -----------------
>>>> FuseSource
>>>> Email: cibsen@fusesource.com
>>>> Web: http://fusesource.com
>>>> Twitter: davsclaus
>>>> Blog: http://davsclaus.blogspot.com/
>>>> Author of Camel in Action: http://www.manning.com/ibsen/
>>>>
>>>
>>
>>
>>
>> --
>> Claus Ibsen
>> -----------------
>> FuseSource
>> Email: cibsen@fusesource.com
>> Web: http://fusesource.com
>> Twitter: davsclaus
>> Blog: http://davsclaus.blogspot.com/
>> Author of Camel in Action: http://www.manning.com/ibsen/
>>
>



-- 
Claus Ibsen
-----------------
FuseSource
Email: cibsen@fusesource.com
Web: http://fusesource.com
Twitter: davsclaus
Blog: http://davsclaus.blogspot.com/
Author of Camel in Action: http://www.manning.com/ibsen/

Re: Error in MessageSupport when using JMSMessage

Posted by Tim <ch...@gmail.com>.
Yea I thought about that but isn't that a hack solution as it now ties
you to Camel in what was just a pojo?

On Mon, Nov 22, 2010 at 8:57 AM, Claus Ibsen <cl...@gmail.com> wrote:
> Then return an empty Message object instead of null.
>
>
>
> On Mon, Nov 22, 2010 at 3:55 PM, Tim <ch...@gmail.com> wrote:
>> Sorry Claus, Maybe I didn't represent the problem correctly.
>> I DO want to alter the body. In this case the result of processing the
>> body should be null.
>>
>> Think of this example (not exactly my case but definitely something
>> that may be helpful).
>>
>> I have a route that says:
>>
>> from("jms:queue:processKey") #1
>>   .bean("cacheValueExtractor") #2
>>     .filter(body().isNull().log("not processing because value was not
>> in cache").stop().end() #3
>>     .bean("beanWillProcessFromValueLookedUpFromCache")..... #4
>>
>> In this case I'm sending a key (or maybe the name of a command) to be
>> processed. (#1)
>> The key maps some value in a cache (or is the key to a command that
>> should be executed) which should be processed. (#2)
>> If the value is not in the cache when looked up in
>> "cacheValueExtractor" you would return null as the object looked up.
>> Just so that beanWillProcessFromValueLookedUpFromCache will not have
>> to worry about invalid keys, we can add a filter (or choose) that the
>> value extracted was not null. (#3&4)
>> In this case it won't work though since JMSMessage will replace the
>> null returned from #2 and replace it with the original message (the
>> key in this case).
>>
>> On Mon, Nov 22, 2010 at 7:42 AM, Claus Ibsen <cl...@gmail.com> wrote:
>>> On Wed, Nov 17, 2010 at 9:59 PM, Tim <ch...@gmail.com> wrote:
>>>> BTW, this is an error in logic in MessageSupport when interoperating
>>>> with JMSMessage it seems. I'm not quite sure what the intention was
>>>> when having it copy the old body over on null.
>>>>
>>>> Can a committer please either confirm this as a bug (and I can try to
>>>> patch that would fix this without breaking other intended
>>>> functionality) or explain to me why this is not a bug if it was
>>>> designed this way?
>>>>
>>>
>>> Its designed that way. If you dont want to alter the body using beans,
>>> then use a void method.
>>>
>>>
>>>> Thanks
>>>> -Tim
>>>>
>>>> On Tue, Nov 16, 2010 at 6:25 PM, Tim <ch...@gmail.com> wrote:
>>>>> This is essentially a different incantation of CAMEL-2436
>>>>> (https://issues.apache.org/activemq/browse/CAMEL-2436)
>>>>> A test case that reproduces the issue is below.
>>>>> If you have a bean that returns null when processing the body of a
>>>>> JMSMessage you will not get the null in the next endpoint but rather
>>>>> the original message itself.
>>>>> One really hacky way around this bug is to replace the JMSMessage with
>>>>> a DefaultMessage by adding a processor
>>>>>
>>>>>                    .process(
>>>>>                        new Processor() {
>>>>>                            @Override
>>>>>                            public void process(@NotNull Exchange
>>>>> anExchange) throws Exception {
>>>>>                                final DefaultMessage myIn = new
>>>>> DefaultMessage();
>>>>>                                myIn.setBody(anExchange.getIn().getBody());
>>>>>                                anExchange.setIn(myIn);
>>>>>                            }
>>>>>                        }
>>>>>                    )
>>>>>
>>>>> Into the below code after the from()
>>>>>
>>>>>
>>>>> import org.apache.activemq.ActiveMQConnectionFactory;
>>>>> import org.apache.activemq.command.ActiveMQObjectMessage;
>>>>> import org.apache.camel.Exchange;
>>>>> import org.apache.camel.Processor;
>>>>> import org.apache.camel.builder.RouteBuilder;
>>>>> import org.apache.camel.component.jms.JmsComponent;
>>>>> import org.apache.camel.component.jms.JmsMessage;
>>>>> import org.apache.camel.component.mock.MockEndpoint;
>>>>> import org.apache.camel.test.junit4.CamelTestSupport;
>>>>> import org.jetbrains.annotations.NotNull;
>>>>> import org.jetbrains.annotations.Nullable;
>>>>> import org.junit.Test;
>>>>>
>>>>> import javax.jms.JMSException;
>>>>>
>>>>> public class C2436Test extends CamelTestSupport {
>>>>>    private static final String ENDPOINT1 = "jms:mock";
>>>>>    private static final String ENDPOINT2 = "mock:results";
>>>>>    private static final String TEST_CONTENT = "My Test Content";
>>>>>
>>>>>    @NotNull
>>>>>    @Override
>>>>>    protected RouteBuilder createRouteBuilder() throws Exception {
>>>>>        context.addComponent("jms", JmsComponent.jmsComponent(new
>>>>> ActiveMQConnectionFactory("vm://localhost")));
>>>>>
>>>>>        return new RouteBuilder() {
>>>>>            @Override
>>>>>            public void configure() throws Exception {
>>>>>                from(ENDPOINT1)
>>>>>                    .bean(new ReturnsNull())
>>>>>                    .filter(body().isNull())
>>>>>                        .log("stopping:${body}")
>>>>>                            .stop()
>>>>>                        .end()
>>>>>                    .log("not-stopping:${body}")
>>>>>                    .to(ENDPOINT2);
>>>>>            }
>>>>>        };
>>>>>    }
>>>>>
>>>>>    @Test
>>>>>    public void testRoutePassing() throws InterruptedException, JMSException {
>>>>>        final MockEndpoint myMockEndpoint = getMockEndpoint(ENDPOINT2);
>>>>>
>>>>>        myMockEndpoint.expectedMessageCount(1);
>>>>>        myMockEndpoint.allMessages().body().isNull();
>>>>>
>>>>>        final ActiveMQObjectMessage myMessage = new ActiveMQObjectMessage();
>>>>>        myMessage.setObject(TEST_CONTENT);
>>>>>
>>>>>        template.send(ENDPOINT1, new Processor() {
>>>>>            @Override
>>>>>            public void process(@NotNull Exchange anExchange) throws Exception {
>>>>>                anExchange.setIn(new JmsMessage(myMessage, null));
>>>>>            }
>>>>>        });
>>>>>
>>>>>        myMockEndpoint.assertIsSatisfied();
>>>>>    }
>>>>>
>>>>>    public class ReturnsNull {
>>>>>        @Nullable
>>>>>        public String processMessage(@NotNull String aMessage) {
>>>>>            return null;
>>>>>        }
>>>>>    }
>>>>> }
>>>>>
>>>>
>>>
>>>
>>>
>>> --
>>> Claus Ibsen
>>> -----------------
>>> FuseSource
>>> Email: cibsen@fusesource.com
>>> Web: http://fusesource.com
>>> Twitter: davsclaus
>>> Blog: http://davsclaus.blogspot.com/
>>> Author of Camel in Action: http://www.manning.com/ibsen/
>>>
>>
>
>
>
> --
> Claus Ibsen
> -----------------
> FuseSource
> Email: cibsen@fusesource.com
> Web: http://fusesource.com
> Twitter: davsclaus
> Blog: http://davsclaus.blogspot.com/
> Author of Camel in Action: http://www.manning.com/ibsen/
>

Re: Error in MessageSupport when using JMSMessage

Posted by Claus Ibsen <cl...@gmail.com>.
Then return an empty Message object instead of null.



On Mon, Nov 22, 2010 at 3:55 PM, Tim <ch...@gmail.com> wrote:
> Sorry Claus, Maybe I didn't represent the problem correctly.
> I DO want to alter the body. In this case the result of processing the
> body should be null.
>
> Think of this example (not exactly my case but definitely something
> that may be helpful).
>
> I have a route that says:
>
> from("jms:queue:processKey") #1
>   .bean("cacheValueExtractor") #2
>     .filter(body().isNull().log("not processing because value was not
> in cache").stop().end() #3
>     .bean("beanWillProcessFromValueLookedUpFromCache")..... #4
>
> In this case I'm sending a key (or maybe the name of a command) to be
> processed. (#1)
> The key maps some value in a cache (or is the key to a command that
> should be executed) which should be processed. (#2)
> If the value is not in the cache when looked up in
> "cacheValueExtractor" you would return null as the object looked up.
> Just so that beanWillProcessFromValueLookedUpFromCache will not have
> to worry about invalid keys, we can add a filter (or choose) that the
> value extracted was not null. (#3&4)
> In this case it won't work though since JMSMessage will replace the
> null returned from #2 and replace it with the original message (the
> key in this case).
>
> On Mon, Nov 22, 2010 at 7:42 AM, Claus Ibsen <cl...@gmail.com> wrote:
>> On Wed, Nov 17, 2010 at 9:59 PM, Tim <ch...@gmail.com> wrote:
>>> BTW, this is an error in logic in MessageSupport when interoperating
>>> with JMSMessage it seems. I'm not quite sure what the intention was
>>> when having it copy the old body over on null.
>>>
>>> Can a committer please either confirm this as a bug (and I can try to
>>> patch that would fix this without breaking other intended
>>> functionality) or explain to me why this is not a bug if it was
>>> designed this way?
>>>
>>
>> Its designed that way. If you dont want to alter the body using beans,
>> then use a void method.
>>
>>
>>> Thanks
>>> -Tim
>>>
>>> On Tue, Nov 16, 2010 at 6:25 PM, Tim <ch...@gmail.com> wrote:
>>>> This is essentially a different incantation of CAMEL-2436
>>>> (https://issues.apache.org/activemq/browse/CAMEL-2436)
>>>> A test case that reproduces the issue is below.
>>>> If you have a bean that returns null when processing the body of a
>>>> JMSMessage you will not get the null in the next endpoint but rather
>>>> the original message itself.
>>>> One really hacky way around this bug is to replace the JMSMessage with
>>>> a DefaultMessage by adding a processor
>>>>
>>>>                    .process(
>>>>                        new Processor() {
>>>>                            @Override
>>>>                            public void process(@NotNull Exchange
>>>> anExchange) throws Exception {
>>>>                                final DefaultMessage myIn = new
>>>> DefaultMessage();
>>>>                                myIn.setBody(anExchange.getIn().getBody());
>>>>                                anExchange.setIn(myIn);
>>>>                            }
>>>>                        }
>>>>                    )
>>>>
>>>> Into the below code after the from()
>>>>
>>>>
>>>> import org.apache.activemq.ActiveMQConnectionFactory;
>>>> import org.apache.activemq.command.ActiveMQObjectMessage;
>>>> import org.apache.camel.Exchange;
>>>> import org.apache.camel.Processor;
>>>> import org.apache.camel.builder.RouteBuilder;
>>>> import org.apache.camel.component.jms.JmsComponent;
>>>> import org.apache.camel.component.jms.JmsMessage;
>>>> import org.apache.camel.component.mock.MockEndpoint;
>>>> import org.apache.camel.test.junit4.CamelTestSupport;
>>>> import org.jetbrains.annotations.NotNull;
>>>> import org.jetbrains.annotations.Nullable;
>>>> import org.junit.Test;
>>>>
>>>> import javax.jms.JMSException;
>>>>
>>>> public class C2436Test extends CamelTestSupport {
>>>>    private static final String ENDPOINT1 = "jms:mock";
>>>>    private static final String ENDPOINT2 = "mock:results";
>>>>    private static final String TEST_CONTENT = "My Test Content";
>>>>
>>>>    @NotNull
>>>>    @Override
>>>>    protected RouteBuilder createRouteBuilder() throws Exception {
>>>>        context.addComponent("jms", JmsComponent.jmsComponent(new
>>>> ActiveMQConnectionFactory("vm://localhost")));
>>>>
>>>>        return new RouteBuilder() {
>>>>            @Override
>>>>            public void configure() throws Exception {
>>>>                from(ENDPOINT1)
>>>>                    .bean(new ReturnsNull())
>>>>                    .filter(body().isNull())
>>>>                        .log("stopping:${body}")
>>>>                            .stop()
>>>>                        .end()
>>>>                    .log("not-stopping:${body}")
>>>>                    .to(ENDPOINT2);
>>>>            }
>>>>        };
>>>>    }
>>>>
>>>>    @Test
>>>>    public void testRoutePassing() throws InterruptedException, JMSException {
>>>>        final MockEndpoint myMockEndpoint = getMockEndpoint(ENDPOINT2);
>>>>
>>>>        myMockEndpoint.expectedMessageCount(1);
>>>>        myMockEndpoint.allMessages().body().isNull();
>>>>
>>>>        final ActiveMQObjectMessage myMessage = new ActiveMQObjectMessage();
>>>>        myMessage.setObject(TEST_CONTENT);
>>>>
>>>>        template.send(ENDPOINT1, new Processor() {
>>>>            @Override
>>>>            public void process(@NotNull Exchange anExchange) throws Exception {
>>>>                anExchange.setIn(new JmsMessage(myMessage, null));
>>>>            }
>>>>        });
>>>>
>>>>        myMockEndpoint.assertIsSatisfied();
>>>>    }
>>>>
>>>>    public class ReturnsNull {
>>>>        @Nullable
>>>>        public String processMessage(@NotNull String aMessage) {
>>>>            return null;
>>>>        }
>>>>    }
>>>> }
>>>>
>>>
>>
>>
>>
>> --
>> Claus Ibsen
>> -----------------
>> FuseSource
>> Email: cibsen@fusesource.com
>> Web: http://fusesource.com
>> Twitter: davsclaus
>> Blog: http://davsclaus.blogspot.com/
>> Author of Camel in Action: http://www.manning.com/ibsen/
>>
>



-- 
Claus Ibsen
-----------------
FuseSource
Email: cibsen@fusesource.com
Web: http://fusesource.com
Twitter: davsclaus
Blog: http://davsclaus.blogspot.com/
Author of Camel in Action: http://www.manning.com/ibsen/

Re: Error in MessageSupport when using JMSMessage

Posted by Tim <ch...@gmail.com>.
Sorry Claus, Maybe I didn't represent the problem correctly.
I DO want to alter the body. In this case the result of processing the
body should be null.

Think of this example (not exactly my case but definitely something
that may be helpful).

I have a route that says:

from("jms:queue:processKey") #1
   .bean("cacheValueExtractor") #2
     .filter(body().isNull().log("not processing because value was not
in cache").stop().end() #3
     .bean("beanWillProcessFromValueLookedUpFromCache")..... #4

In this case I'm sending a key (or maybe the name of a command) to be
processed. (#1)
The key maps some value in a cache (or is the key to a command that
should be executed) which should be processed. (#2)
If the value is not in the cache when looked up in
"cacheValueExtractor" you would return null as the object looked up.
Just so that beanWillProcessFromValueLookedUpFromCache will not have
to worry about invalid keys, we can add a filter (or choose) that the
value extracted was not null. (#3&4)
In this case it won't work though since JMSMessage will replace the
null returned from #2 and replace it with the original message (the
key in this case).

On Mon, Nov 22, 2010 at 7:42 AM, Claus Ibsen <cl...@gmail.com> wrote:
> On Wed, Nov 17, 2010 at 9:59 PM, Tim <ch...@gmail.com> wrote:
>> BTW, this is an error in logic in MessageSupport when interoperating
>> with JMSMessage it seems. I'm not quite sure what the intention was
>> when having it copy the old body over on null.
>>
>> Can a committer please either confirm this as a bug (and I can try to
>> patch that would fix this without breaking other intended
>> functionality) or explain to me why this is not a bug if it was
>> designed this way?
>>
>
> Its designed that way. If you dont want to alter the body using beans,
> then use a void method.
>
>
>> Thanks
>> -Tim
>>
>> On Tue, Nov 16, 2010 at 6:25 PM, Tim <ch...@gmail.com> wrote:
>>> This is essentially a different incantation of CAMEL-2436
>>> (https://issues.apache.org/activemq/browse/CAMEL-2436)
>>> A test case that reproduces the issue is below.
>>> If you have a bean that returns null when processing the body of a
>>> JMSMessage you will not get the null in the next endpoint but rather
>>> the original message itself.
>>> One really hacky way around this bug is to replace the JMSMessage with
>>> a DefaultMessage by adding a processor
>>>
>>>                    .process(
>>>                        new Processor() {
>>>                            @Override
>>>                            public void process(@NotNull Exchange
>>> anExchange) throws Exception {
>>>                                final DefaultMessage myIn = new
>>> DefaultMessage();
>>>                                myIn.setBody(anExchange.getIn().getBody());
>>>                                anExchange.setIn(myIn);
>>>                            }
>>>                        }
>>>                    )
>>>
>>> Into the below code after the from()
>>>
>>>
>>> import org.apache.activemq.ActiveMQConnectionFactory;
>>> import org.apache.activemq.command.ActiveMQObjectMessage;
>>> import org.apache.camel.Exchange;
>>> import org.apache.camel.Processor;
>>> import org.apache.camel.builder.RouteBuilder;
>>> import org.apache.camel.component.jms.JmsComponent;
>>> import org.apache.camel.component.jms.JmsMessage;
>>> import org.apache.camel.component.mock.MockEndpoint;
>>> import org.apache.camel.test.junit4.CamelTestSupport;
>>> import org.jetbrains.annotations.NotNull;
>>> import org.jetbrains.annotations.Nullable;
>>> import org.junit.Test;
>>>
>>> import javax.jms.JMSException;
>>>
>>> public class C2436Test extends CamelTestSupport {
>>>    private static final String ENDPOINT1 = "jms:mock";
>>>    private static final String ENDPOINT2 = "mock:results";
>>>    private static final String TEST_CONTENT = "My Test Content";
>>>
>>>    @NotNull
>>>    @Override
>>>    protected RouteBuilder createRouteBuilder() throws Exception {
>>>        context.addComponent("jms", JmsComponent.jmsComponent(new
>>> ActiveMQConnectionFactory("vm://localhost")));
>>>
>>>        return new RouteBuilder() {
>>>            @Override
>>>            public void configure() throws Exception {
>>>                from(ENDPOINT1)
>>>                    .bean(new ReturnsNull())
>>>                    .filter(body().isNull())
>>>                        .log("stopping:${body}")
>>>                            .stop()
>>>                        .end()
>>>                    .log("not-stopping:${body}")
>>>                    .to(ENDPOINT2);
>>>            }
>>>        };
>>>    }
>>>
>>>    @Test
>>>    public void testRoutePassing() throws InterruptedException, JMSException {
>>>        final MockEndpoint myMockEndpoint = getMockEndpoint(ENDPOINT2);
>>>
>>>        myMockEndpoint.expectedMessageCount(1);
>>>        myMockEndpoint.allMessages().body().isNull();
>>>
>>>        final ActiveMQObjectMessage myMessage = new ActiveMQObjectMessage();
>>>        myMessage.setObject(TEST_CONTENT);
>>>
>>>        template.send(ENDPOINT1, new Processor() {
>>>            @Override
>>>            public void process(@NotNull Exchange anExchange) throws Exception {
>>>                anExchange.setIn(new JmsMessage(myMessage, null));
>>>            }
>>>        });
>>>
>>>        myMockEndpoint.assertIsSatisfied();
>>>    }
>>>
>>>    public class ReturnsNull {
>>>        @Nullable
>>>        public String processMessage(@NotNull String aMessage) {
>>>            return null;
>>>        }
>>>    }
>>> }
>>>
>>
>
>
>
> --
> Claus Ibsen
> -----------------
> FuseSource
> Email: cibsen@fusesource.com
> Web: http://fusesource.com
> Twitter: davsclaus
> Blog: http://davsclaus.blogspot.com/
> Author of Camel in Action: http://www.manning.com/ibsen/
>

Re: Error in MessageSupport when using JMSMessage

Posted by Claus Ibsen <cl...@gmail.com>.
On Wed, Nov 17, 2010 at 9:59 PM, Tim <ch...@gmail.com> wrote:
> BTW, this is an error in logic in MessageSupport when interoperating
> with JMSMessage it seems. I'm not quite sure what the intention was
> when having it copy the old body over on null.
>
> Can a committer please either confirm this as a bug (and I can try to
> patch that would fix this without breaking other intended
> functionality) or explain to me why this is not a bug if it was
> designed this way?
>

Its designed that way. If you dont want to alter the body using beans,
then use a void method.


> Thanks
> -Tim
>
> On Tue, Nov 16, 2010 at 6:25 PM, Tim <ch...@gmail.com> wrote:
>> This is essentially a different incantation of CAMEL-2436
>> (https://issues.apache.org/activemq/browse/CAMEL-2436)
>> A test case that reproduces the issue is below.
>> If you have a bean that returns null when processing the body of a
>> JMSMessage you will not get the null in the next endpoint but rather
>> the original message itself.
>> One really hacky way around this bug is to replace the JMSMessage with
>> a DefaultMessage by adding a processor
>>
>>                    .process(
>>                        new Processor() {
>>                            @Override
>>                            public void process(@NotNull Exchange
>> anExchange) throws Exception {
>>                                final DefaultMessage myIn = new
>> DefaultMessage();
>>                                myIn.setBody(anExchange.getIn().getBody());
>>                                anExchange.setIn(myIn);
>>                            }
>>                        }
>>                    )
>>
>> Into the below code after the from()
>>
>>
>> import org.apache.activemq.ActiveMQConnectionFactory;
>> import org.apache.activemq.command.ActiveMQObjectMessage;
>> import org.apache.camel.Exchange;
>> import org.apache.camel.Processor;
>> import org.apache.camel.builder.RouteBuilder;
>> import org.apache.camel.component.jms.JmsComponent;
>> import org.apache.camel.component.jms.JmsMessage;
>> import org.apache.camel.component.mock.MockEndpoint;
>> import org.apache.camel.test.junit4.CamelTestSupport;
>> import org.jetbrains.annotations.NotNull;
>> import org.jetbrains.annotations.Nullable;
>> import org.junit.Test;
>>
>> import javax.jms.JMSException;
>>
>> public class C2436Test extends CamelTestSupport {
>>    private static final String ENDPOINT1 = "jms:mock";
>>    private static final String ENDPOINT2 = "mock:results";
>>    private static final String TEST_CONTENT = "My Test Content";
>>
>>    @NotNull
>>    @Override
>>    protected RouteBuilder createRouteBuilder() throws Exception {
>>        context.addComponent("jms", JmsComponent.jmsComponent(new
>> ActiveMQConnectionFactory("vm://localhost")));
>>
>>        return new RouteBuilder() {
>>            @Override
>>            public void configure() throws Exception {
>>                from(ENDPOINT1)
>>                    .bean(new ReturnsNull())
>>                    .filter(body().isNull())
>>                        .log("stopping:${body}")
>>                            .stop()
>>                        .end()
>>                    .log("not-stopping:${body}")
>>                    .to(ENDPOINT2);
>>            }
>>        };
>>    }
>>
>>    @Test
>>    public void testRoutePassing() throws InterruptedException, JMSException {
>>        final MockEndpoint myMockEndpoint = getMockEndpoint(ENDPOINT2);
>>
>>        myMockEndpoint.expectedMessageCount(1);
>>        myMockEndpoint.allMessages().body().isNull();
>>
>>        final ActiveMQObjectMessage myMessage = new ActiveMQObjectMessage();
>>        myMessage.setObject(TEST_CONTENT);
>>
>>        template.send(ENDPOINT1, new Processor() {
>>            @Override
>>            public void process(@NotNull Exchange anExchange) throws Exception {
>>                anExchange.setIn(new JmsMessage(myMessage, null));
>>            }
>>        });
>>
>>        myMockEndpoint.assertIsSatisfied();
>>    }
>>
>>    public class ReturnsNull {
>>        @Nullable
>>        public String processMessage(@NotNull String aMessage) {
>>            return null;
>>        }
>>    }
>> }
>>
>



-- 
Claus Ibsen
-----------------
FuseSource
Email: cibsen@fusesource.com
Web: http://fusesource.com
Twitter: davsclaus
Blog: http://davsclaus.blogspot.com/
Author of Camel in Action: http://www.manning.com/ibsen/

Re: Error in MessageSupport when using JMSMessage

Posted by Tim <ch...@gmail.com>.
BTW, this is an error in logic in MessageSupport when interoperating
with JMSMessage it seems. I'm not quite sure what the intention was
when having it copy the old body over on null.

Can a committer please either confirm this as a bug (and I can try to
patch that would fix this without breaking other intended
functionality) or explain to me why this is not a bug if it was
designed this way?

Thanks
-Tim

On Tue, Nov 16, 2010 at 6:25 PM, Tim <ch...@gmail.com> wrote:
> This is essentially a different incantation of CAMEL-2436
> (https://issues.apache.org/activemq/browse/CAMEL-2436)
> A test case that reproduces the issue is below.
> If you have a bean that returns null when processing the body of a
> JMSMessage you will not get the null in the next endpoint but rather
> the original message itself.
> One really hacky way around this bug is to replace the JMSMessage with
> a DefaultMessage by adding a processor
>
>                    .process(
>                        new Processor() {
>                            @Override
>                            public void process(@NotNull Exchange
> anExchange) throws Exception {
>                                final DefaultMessage myIn = new
> DefaultMessage();
>                                myIn.setBody(anExchange.getIn().getBody());
>                                anExchange.setIn(myIn);
>                            }
>                        }
>                    )
>
> Into the below code after the from()
>
>
> import org.apache.activemq.ActiveMQConnectionFactory;
> import org.apache.activemq.command.ActiveMQObjectMessage;
> import org.apache.camel.Exchange;
> import org.apache.camel.Processor;
> import org.apache.camel.builder.RouteBuilder;
> import org.apache.camel.component.jms.JmsComponent;
> import org.apache.camel.component.jms.JmsMessage;
> import org.apache.camel.component.mock.MockEndpoint;
> import org.apache.camel.test.junit4.CamelTestSupport;
> import org.jetbrains.annotations.NotNull;
> import org.jetbrains.annotations.Nullable;
> import org.junit.Test;
>
> import javax.jms.JMSException;
>
> public class C2436Test extends CamelTestSupport {
>    private static final String ENDPOINT1 = "jms:mock";
>    private static final String ENDPOINT2 = "mock:results";
>    private static final String TEST_CONTENT = "My Test Content";
>
>    @NotNull
>    @Override
>    protected RouteBuilder createRouteBuilder() throws Exception {
>        context.addComponent("jms", JmsComponent.jmsComponent(new
> ActiveMQConnectionFactory("vm://localhost")));
>
>        return new RouteBuilder() {
>            @Override
>            public void configure() throws Exception {
>                from(ENDPOINT1)
>                    .bean(new ReturnsNull())
>                    .filter(body().isNull())
>                        .log("stopping:${body}")
>                            .stop()
>                        .end()
>                    .log("not-stopping:${body}")
>                    .to(ENDPOINT2);
>            }
>        };
>    }
>
>    @Test
>    public void testRoutePassing() throws InterruptedException, JMSException {
>        final MockEndpoint myMockEndpoint = getMockEndpoint(ENDPOINT2);
>
>        myMockEndpoint.expectedMessageCount(1);
>        myMockEndpoint.allMessages().body().isNull();
>
>        final ActiveMQObjectMessage myMessage = new ActiveMQObjectMessage();
>        myMessage.setObject(TEST_CONTENT);
>
>        template.send(ENDPOINT1, new Processor() {
>            @Override
>            public void process(@NotNull Exchange anExchange) throws Exception {
>                anExchange.setIn(new JmsMessage(myMessage, null));
>            }
>        });
>
>        myMockEndpoint.assertIsSatisfied();
>    }
>
>    public class ReturnsNull {
>        @Nullable
>        public String processMessage(@NotNull String aMessage) {
>            return null;
>        }
>    }
> }
>