【问题标题】:Spring `jms:listener-container` and IBM MQ backout queuesSpring `jms:listener-container` 和 IBM MQ 回退队列
【发布时间】:2014-10-03 06:07:20
【问题描述】:

我正在使用 Spring 的 JMS (v. 3.1.2) listener-container 和来自 WebSphere 7 的 JNDI 设置的 JMS connectionFactory。应用程序正确处理消息 (put/get),但在 MQ 队列管理器中设置的 backout 设置似乎不起作用。

为了使消息消费失败,我使用带有 setRollbackOnly() 的 spring 事务,它确实增加了属性“Backout count”,因为我可以看到该数字随着“WebSphere MQ Explorer”指向远程队列而增加。

通过阅读一些 IBM 文档,它描述了 IBM MQ JMS 客户端 需要将错误消息移动到回退队列。 Spring 的listener-container 似乎并没有以启用该行为的方式使用 MQ 客户端。退出计数不断增加,好像重新排队命令不起作用。

Spring JMS 是否能够使用该功能?是否需要在 listener-container 中设置任何内容才能处理向 IBM MQ 回退队列的移动?

我的配置如下:

<tx:jta-transaction-manager/>
<jee:jndi-lookup id="connectionFactory" 
        jndi-name="java:comp/env/jms/myapp_queuefactory"/>
<jms:listener-container 
        connection-factory="connectionFactory"
        transaction-manager="transactionManager">
    <jms:listener destination="ONEQUEUE" ref="oneQueueListener" />
    <jms:listener destination="ANOTHERQUEUE" ref="anotherQueueListener" />
    <!-- many more -->
<jms:listener-container/>

IBM MQ 队列设置为“Backout Requeue Queue”设置为 ONEQUEUE.BOQ,“Backout Threshold”设置为 5

我的Spring消息驱动POJO java代码如下:

@Transactional
public class MyQueueMDBean implements javax.jms.MessageListener {
    public void onMessage(javax.jms.Message msg) {
        try {
            // some code that throws some exception ...
        } catch (Exception e) {
            TransactionInterceptor.currentTransactionStatus().setRollbackOnly();    
        }
    }
}

堆栈跟踪错误

消息回滚 5 次后,监听器开始连接失败,作为日志的输出:

[org.springframework.jms.listener.DefaultMessageListenerContainer#3-14870] 警告 org.springframework.jms.listener.DefaultMessageListenerContainer - 目标“ONEQUEUE”的 JMS 消息侦听器调用程序设置失败 - 试图恢复。原因:MQJMS1079:无法将消息写入死信队列。嵌套异常是 com.ibm.mq.MQException: MQJE001: Completion Code '2', Reason '2035'

似乎正在执行撤销消息的权限,或者未正确检索实际的撤销队列,这是出乎意料的,因为 get/puts 工作正常。不过,这是否是一种有效的方法仍在寻找答案。

【问题讨论】:

  • 这应该只是因为队列被定义了一个回退队列和计数而发生的。您能否将您的队列定义添加到您问题中的信息中?
  • 会对您已经看到 MQ 退出工作的 Spring JMS 配置指针非常感兴趣。如果您可以将其发布为答案,将不胜感激。非常感谢!
  • 请将错误消息输出添加到队列管理器 AMQERR01.LOG,这将显示 2035 MQRC_NOT_AUTHORIZED 错误背后的原因。
  • 我在日志中找不到任何内容,但添加更多访问权限使其工作。感谢您的帮助。

标签: jakarta-ee ibm-mq websphere-7 spring-jms


【解决方案1】:

当回滚次数超过 BackoutThreshold (BOTHRESH) 中定义的数量后,JMS 客户端会将有害消息放入队列的 BackoutRequeueQueue (BOQNAME) 中定义的回退队列。这意味着运行 JMS 应用程序的用户不仅需要访问应用程序队列,还需要访问命名的回退队列。

如果无法访问或未定义回退队列,则将尝试使用队列管理器的死信队列(DEADQ 属性)。

当有害消息满足重新排队到回退队列的条件时,未能授予用户 ID +put 访问回退队列和/或 DLQ 的权限将导致 MQRC_NOT_AUTHORIZED (2035) 原因代码。

JMS 异常将报告 2035,队列管理器错误日志中将报告准确用户 ID 的准确队列名称的准确缺失权限。

相关阅读

  1. Handling poison messages in WebSphere MQ classes for JMS

【讨论】: