在骆驼的客户端确认模式下捕获异常后如何防止消息提交

时间:2019-04-15 02:45:03

标签: exception apache-camel

现在,我有一个程序可以监听jms队列,并且在程序无例外地使用了消息之后,它使用客户端确认模式提交事务。

public void process(Exchange exch) throws Exception {
        JmsMessage message = (JmsMessage) exch.getIn();
        try {
            ...
            javax.jms.Message msg = message.getJmsMessage();
            log.info("commit ems level transaction");
            msg.acknowledge();
        } catch (Exception e) {
            ...
        }
    }
<camelContext id="JMS_MCI" xmlns="http://camel.apache.org/schema/spring">
        <endpoint id="commonJmsMciInQue" uri="QUEUE">
            <property key="testConnectionOnStartup" value="true" />
            <property key="disableReplyTo" value="true" />
            <property key="concurrentConsumers" value="10" />
            <property key="acknowledgementModeName" value="CLIENT_ACKNOWLEDGE" />
        </endpoint>
</camelContext>

我尝试在程序上设置断点,当它捕获到异常时,如果异常处理代码尚未完成执行,则消息仍然存在于队列中,一旦异常处理代码完成执行,则消息为删除。

那么当捕获到ecxeption时如何停止消息提交?

感谢您的帮助!~~

1 个答案:

答案 0 :(得分:0)

您正在使用骆驼,为什么通过针对JMS API进行编程来“弄脏手”?骆驼JMS component免费为您做这一切。

仅使用local JMS transactions(不使用外部事务管理器)来消耗消息,Camel会自动提交成功处理的消息并回滚具有处理错误的消息(然后,消息代理进行重新交付或将消息移至{{3} }。

此设置的关键是正确配置Camel JMS组件。对于DLQ,您可以这样做

@Bean("activemq")
public ActiveMQComponent createActiveMQComponent(final ConnectionFactory connectionFactory) {
    final ActiveMQComponent activeMQComponent = new ActiveMQComponent();
    final JmsConfiguration jmsConfiguration = new JmsConfiguration();
    jmsConfiguration.setConnectionFactory(connectionFactory);
    jmsConfiguration.setLazyCreateTransactionManager(false);
    jmsConfiguration.setTransacted(true);
    jmsConfiguration.setConcurrentConsumers([number of concurrent consumers]);
    jmsConfiguration.setCacheLevelName("CACHE_CONSUMER");
    activeMQComponent.setConfiguration(jmsConfiguration);
    return activeMQComponent;
}

这的重要部分是这两种配置。

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

此组件配置与配置的 Spring交易管理器相结合,为您提供了与经纪人的本地交易。

完成此设置后,您只需编写路由即可使用队列中的消息:

from("activemq:queue:myQueue")
...

一定不能在路由中使用骆驼transacted()语句,因为它与已配置的事务管理器有关,不适用于本地JMS事务。但是不用担心,如果上面的设置正确,那么无需transacted(),您的JMS使用者路由就可以完美处理。

您也不需要像示例中那样配置队列。您可以像我的示例一样在Camel中将队列端点配置为简单的字符串

from("activemq:queue:myQueue")
activemq = component name
queue = consume from a queue (not a topic)
myQueue = queue name

如果需要,您还可以使用ActiveMQ处理处理错误。但是一定要了解Broker重新交付(再次发送消息)和Camel重新交付(仅重复处理步骤)之间的区别。