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 via email to