【问题标题】:Unexpected behaviour after calling sub-route调用子路由后的意外行为
【发布时间】:2014-11-21 16:41:18
【问题描述】:

我有一个封装路由(WrapperRoute),它可以调用不同的子路由。 我的问题是,根据子路由中的异常处理,包装器路由在调用后会以不同的方式进行。

当子路由没有错误(NoErrorRoute)、没有异常处理(ErrorRouteUnhandled)或在try-catch块中处理异常(ErrorRouteTryCatch)时WrapperRoute正常工作。这意味着 WrapperRoute 一直工作到结束并写入最后一个日志。

当子路由有 onException-definition (ErrorRouteHandled) 时,只会执行 WrapperRoute 中的 finally-block。不会显示该路线的最后一条日志。

为什么在 try-catch 块之后停止 WrapperRoute?

这是我测试此行为的完整代码。在每个测试用例中我都写了日志。

在测试用例中,handledTest 是 WrapperRoute 中缺少的最后一条日志。

package test;

import org.apache.camel.CamelContext;
import org.apache.camel.builder.RouteBuilder;
import org.junit.Test;

import at.mic.edis.test.TemplateCamelTest;

public class ExcepionHandlingTest extends TemplateCamelTest{

    @Test
    public void noErrorTest() throws Exception {
        template.sendBodyAndHeader("direct:WRAPPER", "BODY", "SUBROUTE", "direct:NO-ERROR");
//      2014-11-20 10:35:23,335 [main] INFO  route1 - WRAPPER-Start
//      2014-11-20 10:35:23,350 [main] INFO  route2 - NO-ERROR-ROUTE: run without exception
//      2014-11-20 10:35:23,353 [main] INFO  route1 - WRAPPER: Finally
//      2014-11-20 10:35:23,353 [main] INFO  route1 - WRAPPER: End of wrapper route
    }

    @Test
    public void unhandledTest() throws Exception {
        template.sendBodyAndHeader("direct:WRAPPER", "BODY", "SUBROUTE", "direct:UNHANDLED");
//      2014-11-20 10:36:34,932 [main] INFO  route1 - WRAPPER-Start
//      2014-11-20 10:36:34,948 [main] INFO  route3 - UNHANDLED: throw exception
//      2014-11-20 10:36:34,952 [main] INFO  route1 - WRAPPER: Catch exception
//      2014-11-20 10:36:34,953 [main] INFO  route1 - WRAPPER: Finally
//      2014-11-20 10:36:34,953 [main] INFO  route1 - WRAPPER: End of wrapper route
    }

    @Test
    public void handledTest() throws Exception {
        template.sendBodyAndHeader("direct:WRAPPER", "BODY", "SUBROUTE", "direct:HANDLED");
//      2014-11-20 10:37:47,898 [main] INFO  route1 - WRAPPER-Start
//      2014-11-20 10:37:47,913 [main] INFO  route4 - HANDLED: throw exception
//      2014-11-20 10:37:47,916 [main] INFO  route4 - HANDLED: Exception handled
//      2014-11-20 10:37:47,919 [main] INFO  route1 - WRAPPER: Finally
    }

    @Test
    public void tryCatchTest() throws Exception {
        template.sendBodyAndHeader("direct:WRAPPER", "BODY", "SUBROUTE", "direct:TRY-CATCH");
//      2014-11-20 10:38:55,871 [main] INFO  route1 - WRAPPER-Start
//      2014-11-20 10:38:55,887 [main] INFO  route5 - TRY-CATCH: throw exception
//      2014-11-20 10:38:55,889 [main] INFO  route5 - TRY-CATCH: exception caught
//      2014-11-20 10:38:55,890 [main] INFO  route5 - TRY-CATCH: finish
//      2014-11-20 10:38:55,891 [main] INFO  route1 - WRAPPER: Finally
//      2014-11-20 10:38:55,892 [main] INFO  route1 - WRAPPER: End of wrapper route
    }

    @Override
    public RouteBuilder createRouteBuilder() throws Exception {
        return new RouteBuilder() {
            @Override
            public void configure() throws Exception {
                WrapperRoute wrapper = new WrapperRoute();
                NoErrorRoute noError = new NoErrorRoute();
                ErrorRouteUnhandled unhandled = new ErrorRouteUnhandled();
                ErrorRouteHandled handled = new ErrorRouteHandled();
                ErrorRouteTryCatch tryCatch = new ErrorRouteTryCatch();

                CamelContext context = getContext();
                context.addRoutes(wrapper);
                context.addRoutes(noError);
                context.addRoutes(unhandled);
                context.addRoutes(handled);
                context.addRoutes(tryCatch);
            }
        };
    }
}

包装路由:

package test;

import org.apache.camel.builder.RouteBuilder;

import at.mic.edis.all.scheduler.processor.WrappedRoutingSlipBean;

public class WrapperRoute extends RouteBuilder{

    @Override
    public void configure() throws Exception {
        onException(Exception.class)
            .handled(true)
            .log("WRAPPER: exception handler");

        from("direct:WRAPPER")
            .log("WRAPPER-Start")
            .doTry()
                .recipientList().method(WrappedEndpoint.class.getName())                
                .end()
            .doCatch(Exception.class)
                .log("WRAPPER: Catch exception")
            .doFinally()
                .log("WRAPPER: Finally")
            .end()
            .log("WRAPPER: End of wrapper route");
    }
}

包装端点:

package test;

import org.apache.camel.Exchange;
import org.apache.camel.Handler;

public class WrappedEndpoint {

    @Handler
    public Object process(Exchange exchange) throws Exception {
        //Reads the direct endpoint for the subroute from the header
        String endpoint = (String) exchange.getIn().getHeader("SUBROUTE");
        return endpoint;
    }
}

无错误路由:

package test;

import org.apache.camel.builder.RouteBuilder;

public class NoErrorRoute extends RouteBuilder {

    @Override
    public void configure() throws Exception {
        from("direct:NO-ERROR")
            .log("NO-ERROR-ROUTE: run without exception");
    }
}

错误路由未处理:

package test;

import org.apache.camel.builder.RouteBuilder;

public class ErrorRouteUnhandled extends RouteBuilder{

    @Override
    public void configure() throws Exception {
        from("direct:UNHANDLED")
            .log("UNHANDLED: throw exception")
            .throwException(new Exception("Exception"));
    }
}

错误路由处理:

package test;

import org.apache.camel.builder.RouteBuilder;

public class ErrorRouteHandled extends RouteBuilder{

    @Override
    public void configure() throws Exception {
        onException(Exception.class)
            .handled(true)
            .log("HANDLED: Exception handled");

        from("direct:HANDLED")
            .log("HANDLED: throw exception")
            .throwException(new Exception("Exception"));
    }
}

ErrorRouteTryCatch:

package test;

import org.apache.camel.builder.RouteBuilder;

public class ErrorRouteTryCatch extends RouteBuilder{

    @Override
    public void configure() throws Exception {
        from("direct:TRY-CATCH")
            .log("TRY-CATCH: throw exception")
            .doTry()
                .throwException(new Exception("Exception"))
            .doCatch(Exception.class)
                .log("TRY-CATCH: exception caught")
            .end()
            .log("TRY-CATCH: finish");
    }
}

编辑:

可以将属性 Exchange.ERRORHANDLER_HANDLED (=CamelErrorHandlerHandled) 设置为 false。这与未定义错误处理或在 onException 块中设置 .handled(false) 时属性的外观相同。

我从 WrapperRoute 修改了 doFinally() 块,现在一切正常:

...
.doFinally()
    .process(new Processor() {
        @Override
        public void process(Exchange exchange) throws Exception {
            // Print all properties
            for (Entry<String, Object>  entry: exchange.getProperties().entrySet()){
                System.out.println(entry.getKey() + " | " + entry.getValue());
            }
            if (exchange.getProperty(Exchange.ERRORHANDLER_HANDLED)!=null){
                System.out.println("Set error handler property to false");
                exchange.setProperty(Exchange.ERRORHANDLER_HANDLED, false);
            }
        }
    })
    .log("WRAPPER: Finally")
.end()
...

【问题讨论】:

    标签: java apache-camel


    【解决方案1】:

    ErrorRouteHandled 中将handledtrue(= 没有向客户端返回失败)设置为false,最后的日志条目再次显示:

    onException(Exception.class)
        .handled(false) // changed from true to false
        .log("HANDLED: Exception handled");
    

    如果设置为true,则仅处理doFinally() 部分中的一个步骤。

    实际上,我不知道这是一个错误还是它按设计工作。

    【讨论】:

    • 感谢您的提示,但我不建议更改我所有路线中的所有 onException-blocks,因为它们超过 200 个。可以在 doFinally-Block 中设置属性WrapperRoute(见我的编辑)。这也导致了可以处理多个步骤的行为。
    • @lahu89 如果不以这种方式使用,则不应将 handled 设置为 true。设置Exchange.ERRORHANDLER_HANDLED 可能是一个解决方案。但这看起来很神奇,应该避免。
    • handled(true) 对于我的所有其他路线都是正确的。 WrapperRoute 只是我的程序中的一个新功能,用于从外部动态调用其他路由并监视结果。我知道这看起来很神奇,应该避免,但我目前没有看到其他意见,这是我找到的第一个解决方案。
    猜你喜欢
    • 2018-08-22
    • 2020-01-23
    • 1970-01-01
    • 2011-03-31
    • 2019-03-06
    • 1970-01-01
    • 1970-01-01
    • 2020-02-23
    • 1970-01-01
    相关资源
    最近更新 更多