现在,我有一个程序可以监听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时如何停止消息提交?
感谢您的帮助!~~
答案 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重新交付(仅重复处理步骤)之间的区别。