【问题标题】:Redeliver message to MQ when using @JmsListener使用 @JmsListener 时向 MQ 重新传递消息
【发布时间】: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


【解决方案1】:

首先设置确认方式为Session.CLIENT_ACKNOWLEDGE 并且在收到消息时,如果处理正确,则只需调用message.acknowledge() 方法,否则不要调用。

它会自动留在队列中,您无需重新发送。

你需要使用

import javax.jms.Message

【讨论】:

    【解决方案2】:

    我创建了简单的 Spring Boot 应用程序和 IBM MQ 的 Docker 容器来测试您的案例。 我在本教程中找到了很好的说明:https://developer.ibm.com/tutorials/mq-jms-application-development-with-spring-boot/

    在你的情况下,这个环境的行为符合预期:接收消息的无限循环 -> NullPointerException -> 返回消息 -> ...

    我发现了 IBM MQ 的一个名为“Backout Queues & Thresholds”的特性,你会在这篇博文中找到解释:https://community.ibm.com/community/user/imwuc/browse/blogs/blogviewer?BlogKey=28814801-083d-4c80-be5f-90aaaf81cdfb

    简而言之,可以限制异常后消息返回队列的次数,并在此限制后将消息发送到另一个队列。

    在您的情况下,此功能可能会在您的目标队列中使用。

    【讨论】:

      猜你喜欢
      • 2015-01-09
      • 1970-01-01
      • 1970-01-01
      • 2018-12-12
      • 1970-01-01
      • 2013-03-20
      • 2010-10-05
      • 1970-01-01
      • 2017-11-30
      相关资源
      最近更新 更多