使用spring JmsTemplate发送消息时的MQRC_UNKNOWN_ALIAS_BASE_Q

时间:2016-12-28 13:41:18

标签: ibm-mq spring-jms

当我尝试将JMS消息发送到外部队列时 失败时出现以下错误

error occured while sending the message :JMSWMQ2008: Failed to open MQ queue 'TESTQUEUE'.; nested exception is com.ibm.mq.MQException: JMSCMQ0001: WebSphere MQ call failed with compcode '2' ('MQCC_FAILED') reason '2082' ('MQRC_UNKNOWN_ALIAS_BASE_Q').

Jms模板声明

<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <property name="connectionFactory" ref="cachedJmsQueueConnectionFactory" />
        <property name="pubSubDomain" value="false" />
        <property name="receiveTimeout" value="2000" />
    </bean>

<bean id="testQueue" class="com.ibm.mq.jms.MQQueue">
        <property name="baseQueueManagerName" value="${test.qmgrName}" />
        <property name="baseQueueName" value="${test.queue}" />
    </bean>

this.jmsTemplate.convertAndSend(getDestinationBean("testQueue"),
                        message.getJson());

但如果我使用动态目标解析器和jmsTemplate,我可以发送消息

this.jmsTemplate.convertAndSend(&#34; TESTQUEUE&#34 ;,                             message.getJson());

2 个答案:

答案 0 :(得分:3)

在这种情况下,当一个程序工作而一个程序不起作用时,不同之处在于两个程序已解析为不同的队列名称。要弄清楚什么是错的,需要了解如何解析名称。 2082: MQRC_UNKNOWN_ALIAS_BASE_Q结果有两种可能性:

  1. 别名队列的TARGQ属性指向不存在的队列。
  2. 别名队列是指非本地群集队列。
  3. 在第一种情况下,在本地队列上定义了别名队列,但定义在某种程度上是有缺陷的。通常是因为本地队列名称拼写错误。结果是TARGQ没有任何本地可以解决的问题。这很容易通过简单检查或使用amqsput或任何其他将消息放入队列的样本进行诊断。

    这可以在一个实例中工作的唯一方式而不是所描述的另一个实例是一个应用程序解析为别名队列而另一个不解析。例如,两个应用程序中的一个指定了非本地QMgr名称,并且消息直接放入传输队列,而另一个则通过解析损坏的别名来达到死胡同。

    第二种情况是别名解析为非本地群集队列,但调用程序已将本地QMgr名称指定为目标的一部分。理解这种情况的关键在于,与可以重新映射QMgr名称的QRemote不同,QAlias不会更改调用应用程序指定的QMgr名称。由于不应提供QMgr名称来恢复群集队列,因此在此处提供非空字符串会破坏解决方案。

    这就是为什么......打开群集队列时,app指定没有QMgr名称,MQ决定要发送到哪个实例。名称解析机制首先在本地查找,如果找到聚簇队列,则使用CLWLUSEQ属性来决定是否优先选择本地实例而不是聚簇实例。但如果它发现的是群集队列上的别名,它会使用TARGQ名称重新驱动解析。如果已将本地QMgr名称指定为完全限定目标地址的一部分,并且没有与TARGQ匹配的本地队列实例,则无法在该点解析它并且解决方案失败。因此,要在群集队列上成功使用别名,需要调用程序 not 指定QMgr名称。

    因此两个程序都解析为不同的队列名称。当行为表明他们不可能需要处理以进一步诊断时,您认为他们正在解析相同的名称。

    最好的办法是使用已知良好的代码片段,其分辨率是明确的。 amqsput示例很好,但您真正需要测试的是一个程序,它允许您指定要连接的QMgr名称和目标地址的QMgr名称,例如来自{{3的Q程序}}。通过在目标中以不同方式指定本地QMgr名称或将其留空来重新创建错误,您将能够辨别失败的情况,然后相应地修改代码。

答案 1 :(得分:0)

正如Rob所说,如果它是一个集群队列,那么就不要指定队列管理器。

<bean id="testInQueue" class="com.ibm.mq.jms.MQQueue">
   <property name="baseQueueName" value="${test.queue}" />
</bean>

此配置对我有用。