问题描述
我正在将 Spring JMS 与 TIBCO EMS 队列/主题用于我的 Spring Boot 应用程序。 TIBCO EMS 队列是使用 EXPLICIT_CLIENT_DUPS_OK_ACKNowLEDGE 设置的。在我的代码中,我没有设置确认模式,所以我假设 spring 将采用它的默认 AUTO_ACKNowLEDGE。我在监听器 onMessage 方法中注意到的行为是,如果应用程序成功处理了消息,则不会重新传递相同的消息 如果应用程序抛出 RuntimeException,则会重新传递相同的消息。该代码还使用 DefaultJmsListenerContainerFactory 将 setSessionTransacted 设置为 true。在这种情况下,是 spring 实际代表我确认消息还是代码需要设置 message.ackNowledge()。
解决方法
请参阅 Session
的 javadoc。 Auto
表示提供程序库在 consumer.receive()
返回消息或 consumer.messsageListener()
退出时自动确认消息。
使用 SimpleMessageListenerContainer
,您的侦听器由提供者的使用者直接调用,因此在您的侦听器正常退出之前不会自动确认消息。
DirectMessageListenerContainer
调用 receive()
并在其自己的线程上调用您的侦听器。因此,我们需要事务在抛出异常后回滚 ack。