1

我正在尝试使用 JPATransactionManager 运行 camel transacted() 路由(独立的 java 进程)是 spring PlatformTransactionManager (因为我希望骆驼路由在单个 DB 事务中运行)但我无法禁止从 MQ Broker 重新传递以防万一即使我在 onException 子句中使用了handled(true) 以及我的自定义重新交付策略(成功执行),事务方法也会失败。我只希望 MQ 在服务崩溃时重新交付。

在下面尝试但它不起作用:

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

    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 不应该重新交付。

  • 我希望我的骆驼路线在单个数据库事务中运行。
  • 我希望 MQ 代理仅在我的 java 服务在处理过程中崩溃时重新传递,这样我就不会丢失消息。
4

2 回答 2

0

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

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

只要消息未被确认,从代理的角度来看,它就没有被传递。消费后立即确认消息,如果您不想再次交付,AUTO_ACKNOWLEDGE是有道理的。

CLIENT_ACKNOWLEDGE另一方面,仅在某些条件下确认消息,有关此内容的更多信息,请参阅此帖子

编辑由于对新信息的评论

如果您想要 MQ 重新传递,但在大多数情况下用 Camel“覆盖”它们,则必须使用消息 transacted

通过像这样配置 JMS 组件来使用本地 JMS 代理事务

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

对于这种类型的事务,您根本不需要 Spring TransactionManager。所以我猜JMSJPATransactionManager忽略它,你的 JMS 消耗应该是事务性的。

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

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

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

于 2019-04-12T13:25:45.053 回答
0

根据Apache Karaf 事务指南, doTry 和 doCatch 应该按预期工作。您的问题可能是触发错误场景的异常。只有已检查的异常(没有 RuntimeException 或其后代)不会将正在进行的事务标记为回滚。

于 2019-06-12T12:27:00.323 回答