成功处理骆驼内部重新传递(交易的骆驼路由)之后,如何防止从MQ Broker重新传递消息

时间:2019-04-10 12:20:49

标签: java apache-camel spring-transactions camel-jms

我尝试使用JPATransactionManager运行骆驼transacted()路由(独立的Java进程)是spring PlatformTransactionManager(因为我希望骆驼路由在单个DB事务中运行),但是我无法禁止从MQ重新交付即使我在onException子句中使用了handle(true)以及我的自定义重新交付策略(成功执行),如果交易方法失败,也将代理。我只希望在服务崩溃时重新交付MQ。

在下面尝试过,但不起作用:

  • 在JMSComponent配置中设置setTransacted(false)以防止骆驼jms运行是transacted_session jms模式,但不起作用
  • doTry和doCatch事务块中的异常
  • 重新运输骆驼,然后处理(true)。

    onException(Exception.class)
        .log("ERROR OCCURRED")
        .redeliveryPolicyRef("myRedeliveryPolicy")
        .handled(true)
        .to(getPostExceptionRoute());
    
    @Bean
    @Autowired
    public RedeliveryPolicy myRedeliveryPolicy() {
        RedeliveryPolicy myRedeliveryPolicy= new RedeliveryPolicy();
        myRedeliveryPolicy.setMaximumRedeliveries(2);
        myRedeliveryPolicy.setMaximumRedeliveryDelay(2000);
        return myRedeliveryPolicy;
    }
    
    @Bean
    @Autowired
    public JmsComponent jms(IJMSConnectionFactory cf) throws JMSException {
        JmsComponent jmsComponent = new JmsComponent();
        jmsComponent.setConfiguration(jmsConfig(cf));
        jmsComponent.setTransacted(false);
        return jmsComponent;
    }
    
    from("jms:queue:TestQueue?acknowledgementModeName=CLIENT_ACKNOWLEDGE")
        .unmarshal().json(JsonLibrary.Jackson, TestObject.class)
        .transacted()
        .processRef("myPersistInDBProcessor")
    
  • 我希望骆驼按照重新交付策略(有效)尝试重新交付,但是MQ不应该重新交付。

  • 我希望我的骆驼路线可以在单个数据库事务中运行。
  • 我希望仅当我的Java服务在处理过程中崩溃时,MQ代理才能重新交付,以免丢失消息。

2 个答案:

答案 0 :(得分:0)

  

我希望骆驼按照重新交付政策(有效)尝试重新交付,但MQ不应该重新交付

当MQ 绝不能进行重新交付时(因为您处理了Camel中的错误),应删除acknowledgementModeName=CLIENT_ACKNOWLEDGE或显式设置AUTO_ACKNOWLEDGE(默认值)。

只要未确认消息,就不会从代理角度传递消息。 AUTO_ACKNOWLEDGE在消费后立即确认该消息,这对于您从不不希望再次交付您是有意义的。

另一方面,

CLIENT_ACKNOWLEDGE仅在特定条件下确认消息,请参见this post for some more info about this

由于评论有新信息而进行编辑

如果您希望MQ重新交付,但在大多数情况下用Camel“覆盖”它们,则必须使用已处理的消息

通过这样配置您的JMS组件

使用本地JMS代理交易

jmsComponent.setLazyCreateTransactionManager(false);
jmsComponent.setTransacted(true);

对于这种类型的事务,您根本不需要Spring TransactionManager。因此,我猜想JPATransactionManager被JMS忽略了,并且您的JMS使用量应该是事务性的。

现在,当您的骆驼错误处理程序通过使用handled(true)“吞下”一个异常时,必须没有MQ重新交付。但是,当将异常传播回代理时,MQ会重新交付。

  

我希望我的骆驼路线可以在单个数据库事务中运行

在您的问题中,我没有找到有关无法正常工作的数据库事务的任何信息。似乎只有一个处理数据库的处理器。如果这不能正常工作,请在您的问题或单独的问题中描述问题。

答案 1 :(得分:0)

根据Apache Karaf Transaction Guide,doTry和doCatch应该按预期工作。在您的情况下,可能是异常触发了错误情况。只有checked exceptions(没有RuntimeException或其后代)不会将正在进行的事务标记为回滚。