Camel异常/错误处理事务处理路由而不会导致客户端异常

时间:2015-03-03 12:43:39

标签: java error-handling apache-camel transactional

我正在使用命令事件驱动的系统,使用JMS和Apache Camel进行路由。在以下情况中:

  • 我向系统发送请求 - 回复命令“X”。

  • 系统通过交易的驼峰路线接收“X”。

  • 在处理“X”时,系统会发出几个事件,“Y”和& “Z”, 但作为交易路线的一部分,这些不应该被刷新 直到交易完成。

  • 发生运行时异常 - 应该导致事务发生 回滚。

我希望能够拦截异常并使用真实的消息(而不是异常)回复客户端。因此我开始实现错误处理程序:

    onException(RuntimeException.class)
        .handled(true)
        .markRollbackOnly()
        .filter(header(Header.REPLY_TO.getName()).isNotNull())
        .to(DESTINATION_FOR_EXCEPTION_HANDLING)
        .to(DESTINATION_FOR_REPLIES);

其中:

  • DESTINATION_FOR_EXCEPTION_HANDLING是一个获取异常并返回消息对象的bean
  • DESTINATION_FOR_REPLIES是一个将out主体设置为消息对象的bean

我遇到的问题是如果我包含“markRollbackOnly()”它:

  • 防止“Y”&被冲洗的“Z” - 好的
  • 在发出requestReply - BAD
  • 的客户端上导致交换异常

如果我不包含它,那么:

  • “Y”& “Z”脸红了 - BAD
  • 我在客户端收到了正版消息对象 - GOOD

如何配置camel以防止在事务中刷新消息,并且能够将异常转换为处理过的错误消息?

2 个答案:

答案 0 :(得分:0)

如果发送到这两个目标的onException使用的是与from相同的Camel组件,那么您需要使用单独的组件,因此它们是独立的。因为回滚会导致它们全部回滚。

假设您使用ActiveMQ,您只需声明两个组件

   <bean id="activemq" ...>

   <bean id="activemq2" ...>

然后在onException中使用activemq2。然后可以配置为使用相同的brokerUrl和所有这些。对于第二个,您可能需要将其设置为transacted = false。

答案 1 :(得分:0)

我尝试过Claus方法,但由于某种原因无法使其工作,我必须误解或设置错误。

最终我通过在内部传播第二个事务来解决这个问题,一个错误处理程序,然后我可以“markRollbackOnlyLast”第二个事务,但在主事务上回复“好”消息:

    TransactionTemplate newTransactionTemplate = new TransactionTemplate(platformTransactionManager);
    newTransactionTemplate.setPropagationBehavior(PROPAGATION_REQUIRES_NEW);
    Policy requireNewTransaction = new SpringTransactionPolicy(newTransactionTemplate);

    onException(RuntimeException.class)
        .onWhen(header(Header.REPLY_TO.getName()).isNotNull())
            .log(LoggingLevel.ERROR, EXCEPTION_STACKTRACE)
            .to(PROCESSOR_FOR_EXCEPTION_HANDLING)
            .to(PROCESSOR_FOR_REPLY)
            .handled(true)
            .markRollbackOnlyLast();

    from(FROM)
        .policy(requireNewTransaction)...