【发布时间】:2019-06-21 23:31:15
【问题描述】:
我正在使用@EnableJms 和@JmsListener 注释在我的应用程序中注册一个队列监听器,基于this 教程。我正在连接到 IBM MQ,使用 jndi 获取连接工厂。我已经阅读了有关确认模式等的信息,但对我来说仍然是新事物。我的问题是消息没有被返回到队列中(监听器不再被调用)。
@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
DefaultJmsListenerContainerFactory factory
= new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory());
factory.setSessionTransacted(true);
factory.setSessionAcknowledgeMode(Session.AUTO_ACKNOWLEDGE); //I have tried also CLIENT_ACKNOWLEDGE
return factory;
}
@JmsListener(containerFactory = "jmsListenerContainerFactory", destination = "myQueue")
@SendTo("secondQueue")
public String testListener(String message){
if(true) throw new NullPointerException();
else return message;
}
任何帮助将不胜感激。 我还有第二个问题。据我了解,如果我想在数据库上实现任何操作,回滚提交的唯一方法(如果在此之后出现问题)将是创建一个事务管理器?如果没有,我需要检测重复的消息。
【问题讨论】:
-
我不确定我是否理解您要完成的工作。 @artild 提供的答案会让我明白您正试图导致失败,以便您可以看到返回队列的消息,这是正确的吗?
-
如果会话已被处理,那么在您读取/处理消息后,您必须调用 commit 将其从队列中删除。 SessionAcknowledgeMode 仅用于非 Transacted 会话,对于 Transacted 会话将被忽略。您可以使用一个特殊值来更好地指示它被忽略,它是
Session.TRANSACTED,但此字段中的值对于 Transacted 会话无关紧要。Session.CLIENT_ACKNOWLEDGE仅适用于非事务会话。 -
从 IBM MQ 的角度来看,
Session.CLIENT_ACKNOWLEDGE的 Transacted 和 non-Transacted 是相似的,最大的区别在于 Transacted 会话可以在事务中包含写入。对于 IBM MQ,这意味着您可以让侦听器使用一条消息,然后例如将其放入第二个队列,如果它们都在同一个队列管理器上,那么提交将使消息的 GET 和 PUT 作为一个单元发生的工作,这不能与非交易Session.CLIENT_ACKNOWLEDGE完成。 -
如果在我的示例中队列位于两个不同的队列管理器上,或者像您的第二个问题一样,如果您使用消息然后想要更新数据库,那么这些将需要事务管理器。事务管理器的工作是将队列中的 GET 和 PUT 提交到第二个队列或将 UPDATE 提交到数据库作为单个工作单元。
-
请注意,如果您有权查看队列中的消息,则可以检查消息的回退计数以查看它已回滚到队列的次数。
标签: spring jms listener ibm-mq