[英]Camel exception handling behaviour when using interceptor
In a unit test I want to simulate that an Exception
occurs. 在单元测试中,我要模拟发生
Exception
情况。
I expect to receive one message at the "mock:count" endpoint, because of the doTry/doCatch
-block. 由于
doTry/doCatch
,我希望在“ mock:count”端点上收到一条消息。 Why is this not happening and why is the Exception
handled by the general onException
-block? 为什么没有发生这种情况,为什么一般的
onException
-block处理Exception
?
import org.apache.camel.LoggingLevel;
import org.apache.camel.builder.AdviceWithRouteBuilder;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.test.junit4.CamelTestSupport;
import org.apache.cxf.binding.soap.SoapFault;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;
public class TestClass extends CamelTestSupport {
@Override
protected RouteBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
@Override
public void configure() throws Exception {
onException(Exception.class)
.log(LoggingLevel.INFO, "outer catch")
.handled(true);
from("direct:start")
.doTry()
.to("mock:exception")
.doCatch(Exception.class)
.log(LoggingLevel.INFO, "inner catch")
.to("mock:count")
.end();
}
};
}
@Test
public void testBlaat() throws Exception {
final SoapFault soapFault = new SoapFault("Something clearly went wrong", SoapFault.FAULT_CODE_CLIENT);
Element detail = soapFault.getOrCreateDetail();
Document doc = detail.getOwnerDocument();
Text tn = doc.createTextNode("Fault details");
detail.appendChild(tn);
context.getRouteDefinitions().get(0).adviceWith(context, new AdviceWithRouteBuilder() {
@Override
public void configure() throws Exception {
interceptSendToEndpoint("mock:exception").throwException(new Exception("test"));
}
});
template.sendBody("direct:start", "start");
MockEndpoint endpoint = getMockEndpoint("mock:count");
endpoint.expectedMessageCount(1);
assertMockEndpointsSatisfied();
}
}
It turns out that exceptions thrown from an AdviceWithRouteBuilder
are not seen by the RouteDefinition
's doTry/doCatch
when the route is intercepted by the AdviceWithRouteBuilder
because they are on different channels. 事实证明,从抛出的异常
AdviceWithRouteBuilder
不被看到RouteDefinition
的doTry/doCatch
时的路线是由拦截AdviceWithRouteBuilder
,因为它们是在不同的频道。 The way to solve this is to use a mock for the endpoint and throw the exception from the mock: 解决此问题的方法是对端点使用模拟,并从模拟抛出异常:
getMockEndpoint("mock:exception").whenAnyExchangeReceived(new
Processor() {
@Override
public void process(Exchange exchange) throws Exception {
throw new Exception("fail me");
}
});
See: http://camel.465427.n5.nabble.com/question-about-exception-handling-behavior-td5743489.html 参见: http : //camel.465427.n5.nabble.com/question-about-exception-handling-behavior-td5743489.html
Also see this issue on JIRA: https://issues.apache.org/jira/browse/CAMEL-6300 It is fixed in Camel 2.10.5 and other newer versions. 另请参见JIRA上的此问题: https ://issues.apache.org/jira/browse/CAMEL-6300在Camel 2.10.5和其他更新版本中已修复。
I am not sure why this is happening to you, but I have an idea. 我不确定为什么会发生在您身上,但是我有个主意。 I am thinking that your context is starting before reaching your test case and maybe your interceptor is being set up too late.
我认为您的上下文在到达测试用例之前就已经开始,也许您的拦截器设置得太迟了。 Can you try the following?
您可以尝试以下吗?
Add this method: 添加此方法:
@Override
public boolean isUseRouteBuilder() {
return false;
}
Then use the regular way of defining the route with context.addRoutes(new RouteBuilder(){ .. })
instead of overriding createRouteBuilder
. 然后使用常规方法通过
context.addRoutes(new RouteBuilder(){ .. })
定义路由,而不是覆盖createRouteBuilder
。 Also, define your interceptor here. 另外,在此处定义您的拦截器。
And after configuring your route and interceptor run context.start()
in your test case. 在配置了路由和拦截器之后,在测试用例中运行
context.start()
。 Try and let me know if it worked. 尝试让我知道是否有效。
UPDATE : Overriding isUseRouteBuilder
is not required. 更新 :不需要覆盖
isUseRouteBuilder
。
UPDATE2: UPDATE2:
I have been running few tests and I am seeing the same behavior. 我已经运行了很少的测试,并且看到了相同的行为。 It seems that onException always triggers before doCatch.
似乎onException总是在doCatch之前触发。 Also, if you set
handled
to true
the exception does not get propagated and does not reach the doCatch block. 此外,如果你设置
handled
,以true
异常没有得到传播,并没有达到doCatch块。
Based on the documentation of doTry doCatch doFinally I would understand the error handler does not apply ( When using doTry .. doCatch .. doFinally then the regular Camel Error Handler does not apply ) but it seems the error handler and the onException are not the same. 根据doTry doCatch doFinally的文档,我会理解错误处理程序不适用( 使用doTry .. doCatch .. doFinally时,常规的Camel错误处理程序不适用 ),但似乎错误处理程序和onException不相同。
Also, I have found this: how to handle exception or fault in multiple routes which could be helpful for you. 另外,我发现了这一点: 如何处理多条路径中的异常或错误,这可能对您有所帮助。
One last thing: you can define your interceptor in the same RouteBuilder: 最后一件事:您可以在同一RouteBuilder中定义拦截器:
context.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
interceptSendToEndpoint("mock:exception").throwException(new Exception());
onException(Exception.class).process(new Processor() {
@Override
public void process(Exchange exchange) throws Exception {
System.out.println("from onException");
}
}).handled(false);
from("direct:start")
//.errorHandler(noErrorHandler())
.doTry()
.to("mock:exception")
.doCatch(Exception.class)
.process(new Processor() {
@Override
public void process(Exchange exchange) throws Exception {
System.out.println("from doCatch");
}
})
.to("mock:count")
.end();
}
});
Does this help? 这有帮助吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.