Apache Camel - 具有死信通道功能的事务错误处理程序

时间:2015-08-06 02:26:20

标签: apache-camel

我正在开发一个消息路由器,我已经到了处理意外的地步并实施了一些错误处理。

在我的代码中,我能够区分由于错误消息而发生异常的时间,这是我希望将消息发送到死信终点的唯一一种情况。 在所有其他情况下,我认为由基础结构问题引起的异常(例如,数据库/ JMS端点变得不可用),在这种情况下,我希望将消息回滚到路由开始。

查看Camel文档时,唯一一个支持死信的错误处理程序是DeadLetterChannel,但问题是此错误处理程序未处理。

那么有没有办法实现我想要的东西以及简单或困难呢?我可以看到您可以配置camel上下文以使用自定义错误处理程序构建器,并且正在考虑尝试在我自己的构建器中的TransactionErrorHandlerDeadLetterChannel之间进行合成,但我不确定这是否是要走的路。开箱即用的构建器似乎有相当复杂的逻辑。

另一种选择是扩展TransactionErrorHandlerBuilder并从DeadLetterChannelBuilder获取验证结束点的代码并创建失败处理器但又不确定。如果这很容易,骆驼家伙会把它包含在框架中。我的用例必须是任何处理企业关键应用程序的用例。

提前感谢您的建议。任何提示都会非常感激。

更新 我试图扩展TransactionErrorHandlerBuilder,如上所述,它不起作用,因为它创建的故障处理器从未使用过。

因为我真的需要这个功能,所以我试着通过让我的代码添加一个**" dead.letter = true"在邮件标题中,将原始邮件放回交换中,如下所示:

@Override
public void process(Exchange exchange) {
    Message incomingMessage = exchange.getIn();
    try {
        // Do some work here
    } catch (MyCustomException e) {    
        incomingMessage.setHeader("dead.letter", "true");
        exchange.setIn(incomingMessage);
    } catch (Exception e) {
        exchange.setException(e);
    }
}

然后在我的路线定义中我添加了:

from(ep).routeId(createRouteId(system))
        .autoStartup(false).transacted()
        .threads(route.getThreads())
        .filter(body().isNotNull())
        .process((Processor) routeBean)
        .choice()
        .when(header("dead.letter").isNotNull())
        .to(mq1:ERROR.QUEUE);

我预计这将解决我的问题。但是我的ERROR.QUEUE没有得到任何东西(日志中也没有)和提交的事务,我的消息丢失了。

请尽快帮助我。

1 个答案:

答案 0 :(得分:0)

我遇到了同样的问题。我不知道为什么 TransactionErrorHandlerBuilder 不能配置为向死信通道发送消息。 我对它的方法 setDeadLetterUri() 没有按我预期的那样工作感到困惑。经过长时间的研究,我找到了相当简单的解决方案。

它处理事务中的消息,如果有异常抛出,事务将回滚,原始消息将发送到死信通道。 请注意,您应该明确允许使用原始消息。

@Override
public void configure() {
    
    getContext().setAllowUseOriginalMessage(true); 

    from("jms:queue:{{foo.bar}}")
            .doTry()
                .to("direct:processMsgInTransaction")
            .doCatch(Exception.class)
                .process(exchange -> exchange.setMessage(exchange.getUnitOfWork().getOriginalInMessage()))
                .to("jms:queue:{{foo.bar.dead.letter}}")
            .endDoTry();

    from("direct:processMsgInTransaction")
            .errorHandler(new TransactionErrorHandlerBuilder() 
                .onExceptionOccurred(exchange -> log.error("Something went wrong")))
            //.transacted() //uncomment for using default TransactionErrorHandler
            .process(someProcessor)
            .process(someOtherProcessor);
            
}