使用拦截器时的Camel异常处理行为

时间:2013-11-18 16:09:49

标签: java apache-camel

在单元测试中,我想模拟发生Exception

由于doTry/doCatch - 阻止,我希望在“mock:count”端点收到一条消息。为什么这不会发生?为什么Exception由一般onException - 块处理?

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();

   }
}

2 个答案:

答案 0 :(得分:4)

事实证明,当AdviceWithRouteBuilder截获路由时,RouteDefinition的{​​{1}}无法看到doTry/doCatch引发的异常,因为它们位于不同的位置通道。解决这个问题的方法是使用模拟端点并从模拟中抛出异常:

AdviceWithRouteBuilder

请参阅:http://camel.465427.n5.nabble.com/question-about-exception-handling-behavior-td5743489.html

另请参阅JIRA上的此问题:https://issues.apache.org/jira/browse/CAMEL-6300 它已在Camel 2.10.5和其他更新版本中修复。

答案 1 :(得分:0)

我不确定为什么会发生这种情况,但我有一个想法。我认为你的上下文在到达你的测试用例之前就开始了,也许你的拦截器设置得太迟了。你能试试以下吗?

添加此方法:

@Override
public boolean isUseRouteBuilder() {
    return false;
}

然后使用常规方式使用context.addRoutes(new RouteBuilder(){ .. })定义路线,而不是覆盖createRouteBuilder。另外,在这里定义你的拦截器。

在配置路由和拦截器后,在测试用例中运行context.start()。试着告诉我它是否有效。

<强>更新

<强> UPDATE2:

我一直在运行一些测试,我看到了同样的行为。似乎onException总是在doCatch之前触发。此外,如果将isUseRouteBuilder设置为handled,则异常不会传播,也不会到达doCatch块。

根据doTry doCatch doFinally的文档,我会理解错误处理程序不适用(当使用doTry ... doCatch .. doFinally然后常规的Camel错误处理程序不适用)但是似乎错误处理程序和onException是不一样的。

另外,我发现了这个:how to handle exception or fault in multiple routes对你有所帮助。

最后一件事:您可以在同一个RouteBuilder中定义拦截器:

true

这有帮助吗?