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