useOriginalMessage with direct-vm

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

useOriginalMessage with direct-vm

Karsten Vileid
I use the deadLetterChannel errorHandler with useOriginalMessage. However
if using direct-vm for a sub-route then the original message is not sent to
the deadLetterChannel, if an exception occurs in the sub-route.
I see that the problem is that direct-vm creates a new UOW, hence the
sub-route will consider whatever message enters the direct-vm as the
original message (in contrast to direct which resuses existing UOW)
This different behaviour between direct and direct-vm, do anyone know if
this is a feature?

Below is a TestCase reproducing my observation. (Tested with Camel version
2.12.3 and latest from github)

import org.apache.camel.EndpointInject;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.test.junit4.CamelTestSupport;
import org.junit.Test;

public class DirectVMTest extends CamelTestSupport {
    public RouteBuilder createRouteBuilder() {
        return new DirectVmRoute();
    }

    @EndpointInject(uri = "mock:deadLetterChannel")
    private MockEndpoint mockDeadLetterChannel;

    @Test
    public void directVmShallNotChangeUnitOfWork() throws Exception {
        final String originalBody = "original body";
        mockDeadLetterChannel.expectedMessageCount(1);
        mockDeadLetterChannel.expectedBodiesReceived(originalBody);
        template.sendBody("direct:start", originalBody);
        assertMockEndpointsSatisfied();
    }

    private static class DirectVmRoute extends RouteBuilder {
        public void configure() throws Exception {

errorHandler(deadLetterChannel("mock:deadLetterChannel").useOriginalMessage());
            from("direct:start").setBody(constant("modified
body")).to("direct-vm:next");
            from("direct-vm:next").throwException(new RuntimeException());
        }
    }
}


-------

If updating DirectVmProcessor.java in camel-core as shown below the
testcase passes.

    protected Exchange prepareExchange(Exchange exchange) {
        // send a new copied exchange with new camel context (do not
handover completions)
        Exchange newExchange =
ExchangeHelper.copyExchangeAndSetCamelContext(exchange,
endpoint.getCamelContext(), false);
        // set the from endpoint
        newExchange.setFromEndpoint(endpoint);
        newExchange.setUnitOfWork(exchange.getUnitOfWork());  // <---
Update. Copy UOW from original exchange

        return newExchange;
    }


Thanks,
Karsten
Reply | Threaded
Open this post in threaded view
|

Re: useOriginalMessage with direct-vm

ceposta
Can you please open a JIRA and attach these (test/patch) and approve
us to use this code? I can review it and get it in for you.

On Thu, Feb 27, 2014 at 3:52 PM, Karsten Vileid <[hidden email]> wrote:

> I use the deadLetterChannel errorHandler with useOriginalMessage. However
> if using direct-vm for a sub-route then the original message is not sent to
> the deadLetterChannel, if an exception occurs in the sub-route.
> I see that the problem is that direct-vm creates a new UOW, hence the
> sub-route will consider whatever message enters the direct-vm as the
> original message (in contrast to direct which resuses existing UOW)
> This different behaviour between direct and direct-vm, do anyone know if
> this is a feature?
>
> Below is a TestCase reproducing my observation. (Tested with Camel version
> 2.12.3 and latest from github)
>
> import org.apache.camel.EndpointInject;
> import org.apache.camel.builder.RouteBuilder;
> import org.apache.camel.component.mock.MockEndpoint;
> import org.apache.camel.test.junit4.CamelTestSupport;
> import org.junit.Test;
>
> public class DirectVMTest extends CamelTestSupport {
>     public RouteBuilder createRouteBuilder() {
>         return new DirectVmRoute();
>     }
>
>     @EndpointInject(uri = "mock:deadLetterChannel")
>     private MockEndpoint mockDeadLetterChannel;
>
>     @Test
>     public void directVmShallNotChangeUnitOfWork() throws Exception {
>         final String originalBody = "original body";
>         mockDeadLetterChannel.expectedMessageCount(1);
>         mockDeadLetterChannel.expectedBodiesReceived(originalBody);
>         template.sendBody("direct:start", originalBody);
>         assertMockEndpointsSatisfied();
>     }
>
>     private static class DirectVmRoute extends RouteBuilder {
>         public void configure() throws Exception {
>
> errorHandler(deadLetterChannel("mock:deadLetterChannel").useOriginalMessage());
>             from("direct:start").setBody(constant("modified
> body")).to("direct-vm:next");
>             from("direct-vm:next").throwException(new RuntimeException());
>         }
>     }
> }
>
>
> -------
>
> If updating DirectVmProcessor.java in camel-core as shown below the
> testcase passes.
>
>     protected Exchange prepareExchange(Exchange exchange) {
>         // send a new copied exchange with new camel context (do not
> handover completions)
>         Exchange newExchange =
> ExchangeHelper.copyExchangeAndSetCamelContext(exchange,
> endpoint.getCamelContext(), false);
>         // set the from endpoint
>         newExchange.setFromEndpoint(endpoint);
>         newExchange.setUnitOfWork(exchange.getUnitOfWork());  // <---
> Update. Copy UOW from original exchange
>
>         return newExchange;
>     }
>
>
> Thanks,
> Karsten



--
Christian Posta
http://www.christianposta.com/blog
twitter: @christianposta
Reply | Threaded
Open this post in threaded view
|

Re: useOriginalMessage with direct-vm

Claus Ibsen-2
No this is working as designed.



On Fri, Feb 28, 2014 at 1:01 AM, Christian Posta
<[hidden email]> wrote:

> Can you please open a JIRA and attach these (test/patch) and approve
> us to use this code? I can review it and get it in for you.
>
> On Thu, Feb 27, 2014 at 3:52 PM, Karsten Vileid <[hidden email]> wrote:
>> I use the deadLetterChannel errorHandler with useOriginalMessage. However
>> if using direct-vm for a sub-route then the original message is not sent to
>> the deadLetterChannel, if an exception occurs in the sub-route.
>> I see that the problem is that direct-vm creates a new UOW, hence the
>> sub-route will consider whatever message enters the direct-vm as the
>> original message (in contrast to direct which resuses existing UOW)
>> This different behaviour between direct and direct-vm, do anyone know if
>> this is a feature?
>>
>> Below is a TestCase reproducing my observation. (Tested with Camel version
>> 2.12.3 and latest from github)
>>
>> import org.apache.camel.EndpointInject;
>> import org.apache.camel.builder.RouteBuilder;
>> import org.apache.camel.component.mock.MockEndpoint;
>> import org.apache.camel.test.junit4.CamelTestSupport;
>> import org.junit.Test;
>>
>> public class DirectVMTest extends CamelTestSupport {
>>     public RouteBuilder createRouteBuilder() {
>>         return new DirectVmRoute();
>>     }
>>
>>     @EndpointInject(uri = "mock:deadLetterChannel")
>>     private MockEndpoint mockDeadLetterChannel;
>>
>>     @Test
>>     public void directVmShallNotChangeUnitOfWork() throws Exception {
>>         final String originalBody = "original body";
>>         mockDeadLetterChannel.expectedMessageCount(1);
>>         mockDeadLetterChannel.expectedBodiesReceived(originalBody);
>>         template.sendBody("direct:start", originalBody);
>>         assertMockEndpointsSatisfied();
>>     }
>>
>>     private static class DirectVmRoute extends RouteBuilder {
>>         public void configure() throws Exception {
>>
>> errorHandler(deadLetterChannel("mock:deadLetterChannel").useOriginalMessage());
>>             from("direct:start").setBody(constant("modified
>> body")).to("direct-vm:next");
>>             from("direct-vm:next").throwException(new RuntimeException());
>>         }
>>     }
>> }
>>
>>
>> -------
>>
>> If updating DirectVmProcessor.java in camel-core as shown below the
>> testcase passes.
>>
>>     protected Exchange prepareExchange(Exchange exchange) {
>>         // send a new copied exchange with new camel context (do not
>> handover completions)
>>         Exchange newExchange =
>> ExchangeHelper.copyExchangeAndSetCamelContext(exchange,
>> endpoint.getCamelContext(), false);
>>         // set the from endpoint
>>         newExchange.setFromEndpoint(endpoint);
>>         newExchange.setUnitOfWork(exchange.getUnitOfWork());  // <---
>> Update. Copy UOW from original exchange
>>
>>         return newExchange;
>>     }
>>
>>
>> Thanks,
>> Karsten
>
>
>
> --
> Christian Posta
> http://www.christianposta.com/blog
> twitter: @christianposta



--
Claus Ibsen
-----------------
Red Hat, Inc.
Email: [hidden email]
Twitter: davsclaus
Blog: http://davsclaus.com
Author of Camel in Action: http://www.manning.com/ibsen
Make your Camel applications look hawt, try: http://hawt.io
Reply | Threaded
Open this post in threaded view
|

Re: useOriginalMessage with direct-vm

Karsten Vileid
Ok, any best practises for handling this.

We are using jboss-fuse with its osgi container and bundles. And working in
a bundle with direct between the sub-routes. However some sub-routes
handled common reusable functionality, so we moved these reusable
sub-routes to a common bundle and used direct-vm to talk to them.
However here we were surprised when understanding that if error handling in
sub-route the original message can not be restored.

What I can think of.
1. Store original message as a property on the exchange before calling
direct-vm, and let error handling route fetch this property.
2. In some way use a wiretap before calling direct-vm.

Any input on best practises/patterns for this use case is appreciated




On Fri, Feb 28, 2014 at 8:09 AM, Claus Ibsen <[hidden email]> wrote:

> No this is working as designed.
>
>
>
> On Fri, Feb 28, 2014 at 1:01 AM, Christian Posta
> <[hidden email]> wrote:
> > Can you please open a JIRA and attach these (test/patch) and approve
> > us to use this code? I can review it and get it in for you.
> >
> > On Thu, Feb 27, 2014 at 3:52 PM, Karsten Vileid <[hidden email]>
> wrote:
> >> I use the deadLetterChannel errorHandler with useOriginalMessage.
> However
> >> if using direct-vm for a sub-route then the original message is not
> sent to
> >> the deadLetterChannel, if an exception occurs in the sub-route.
> >> I see that the problem is that direct-vm creates a new UOW, hence the
> >> sub-route will consider whatever message enters the direct-vm as the
> >> original message (in contrast to direct which resuses existing UOW)
> >> This different behaviour between direct and direct-vm, do anyone know if
> >> this is a feature?
> >>
> >> Below is a TestCase reproducing my observation. (Tested with Camel
> version
> >> 2.12.3 and latest from github)
> >>
> >> import org.apache.camel.EndpointInject;
> >> import org.apache.camel.builder.RouteBuilder;
> >> import org.apache.camel.component.mock.MockEndpoint;
> >> import org.apache.camel.test.junit4.CamelTestSupport;
> >> import org.junit.Test;
> >>
> >> public class DirectVMTest extends CamelTestSupport {
> >>     public RouteBuilder createRouteBuilder() {
> >>         return new DirectVmRoute();
> >>     }
> >>
> >>     @EndpointInject(uri = "mock:deadLetterChannel")
> >>     private MockEndpoint mockDeadLetterChannel;
> >>
> >>     @Test
> >>     public void directVmShallNotChangeUnitOfWork() throws Exception {
> >>         final String originalBody = "original body";
> >>         mockDeadLetterChannel.expectedMessageCount(1);
> >>         mockDeadLetterChannel.expectedBodiesReceived(originalBody);
> >>         template.sendBody("direct:start", originalBody);
> >>         assertMockEndpointsSatisfied();
> >>     }
> >>
> >>     private static class DirectVmRoute extends RouteBuilder {
> >>         public void configure() throws Exception {
> >>
> >>
> errorHandler(deadLetterChannel("mock:deadLetterChannel").useOriginalMessage());
> >>             from("direct:start").setBody(constant("modified
> >> body")).to("direct-vm:next");
> >>             from("direct-vm:next").throwException(new
> RuntimeException());
> >>         }
> >>     }
> >> }
> >>
> >>
> >> -------
> >>
> >> If updating DirectVmProcessor.java in camel-core as shown below the
> >> testcase passes.
> >>
> >>     protected Exchange prepareExchange(Exchange exchange) {
> >>         // send a new copied exchange with new camel context (do not
> >> handover completions)
> >>         Exchange newExchange =
> >> ExchangeHelper.copyExchangeAndSetCamelContext(exchange,
> >> endpoint.getCamelContext(), false);
> >>         // set the from endpoint
> >>         newExchange.setFromEndpoint(endpoint);
> >>         newExchange.setUnitOfWork(exchange.getUnitOfWork());  // <---
> >> Update. Copy UOW from original exchange
> >>
> >>         return newExchange;
> >>     }
> >>
> >>
> >> Thanks,
> >> Karsten
> >
> >
> >
> > --
> > Christian Posta
> > http://www.christianposta.com/blog
> > twitter: @christianposta
>
>
>
> --
> Claus Ibsen
> -----------------
> Red Hat, Inc.
> Email: [hidden email]
> Twitter: davsclaus
> Blog: http://davsclaus.com
> Author of Camel in Action: http://www.manning.com/ibsen
> Make your Camel applications look hawt, try: http://hawt.io
>