【问题标题】:MQRC_CLIENT_CONN_ERROR with IBM MQ in docker using CCDT + Spring BootMQRC_CLIENT_CONN_ERROR 与 IBM MQ 在 Docker 中使用 CCDT + Spring Boot
【发布时间】:2019-06-15 22:42:13
【问题描述】:

我正在使用这个 IBM 官方教程: MQ JMS application development with Spring Boot

并在 docker 中使用 IBM® MQ Advanced for Developers 从这个 docker hub 页面获得:ibmcom/mq

MQ 使用以下命令启动:

docker run --name mq --env LICENSE=accept --env MQ_QMGR_NAME=QM1 --publish 1414:1414 --publish 9443:9443 --detach ibmcom/mq 

它已启动并运行,我可以使用连接名称和频道信息连接到它:

ibm.mq.channel: DEV.ADMIN.SVRCONN
ibm.mq.connectionName: localhost(1414)

但是,当我尝试使用 CCDT 文件连接到它时出现错误。我用这个命令得到这个 CCDT 文件:

docker cp <container_id>:/mnt/mqm/data/qmgrs/QM1/@ipcc/AMQCLCHL.TAB <path_to_ccdt_path_on_my_computer>

我已经设置了正确的 application.yml 属性:

ibm:
  mq:
    ccdtUrl: file://<path_to_ccdt_path_on_my_computer>

但我收到此错误:

com.ibm.msg.client.jms.DetailedJMSException: JMSWMQ2020: Failed to connect to queue manager 'QM1' with connection mode 'Client' and supplied CCDT URL 'AMQCLCHL.TAB', see linked exception for more information.
    at com.ibm.msg.client.wmq.common.internal.Reason.reasonToException(Reason.java:595)
    at com.ibm.msg.client.wmq.common.internal.Reason.createException(Reason.java:215)
    at com.ibm.msg.client.wmq.internal.WMQConnection.<init>(WMQConnection.java:424)
    at com.ibm.msg.client.wmq.factories.WMQConnectionFactory.createV7ProviderConnection(WMQConnectionFactory.java:8475)
    at com.ibm.msg.client.wmq.factories.WMQConnectionFactory.createProviderConnection(WMQConnectionFactory.java:7815)
    at com.ibm.msg.client.jms.admin.JmsConnectionFactoryImpl._createConnection(JmsConnectionFactoryImpl.java:303)
    at com.ibm.msg.client.jms.admin.JmsConnectionFactoryImpl.createConnection(JmsConnectionFactoryImpl.java:236)
    at com.ibm.mq.jms.MQConnectionFactory.createCommonConnection(MQConnectionFactory.java:6016)
    at com.ibm.mq.jms.MQConnectionFactory.createConnection(MQConnectionFactory.java:6041)
    at org.springframework.jms.support.JmsAccessor.createConnection(JmsAccessor.java:196)
    at org.springframework.jms.listener.AbstractJmsListeningContainer.createSharedConnection(AbstractJmsListeningContainer.java:411)
    at org.springframework.jms.listener.AbstractJmsListeningContainer.establishSharedConnection(AbstractJmsListeningContainer.java:379)
    at org.springframework.jms.listener.DefaultMessageListenerContainer.establishSharedConnection(DefaultMessageListenerContainer.java:818)
    at org.springframework.jms.listener.AbstractJmsListeningContainer.doStart(AbstractJmsListeningContainer.java:291)
    at org.springframework.jms.listener.AbstractJmsListeningContainer.start(AbstractJmsListeningContainer.java:276)
    at org.springframework.jms.listener.DefaultMessageListenerContainer.start(DefaultMessageListenerContainer.java:612)
    at org.springframework.jms.config.JmsListenerEndpointRegistry.startIfNecessary(JmsListenerEndpointRegistry.java:242)
    at org.springframework.jms.config.JmsListenerEndpointRegistry.start(JmsListenerEndpointRegistry.java:205)
    at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:182)
    at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:53)
    at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:360)
    at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:158)
    at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:122)
    at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:879)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.finishRefresh(ServletWebServerApplicationContext.java:161)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:316)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248)
    at Application.main(Application.java:11)
Caused by: com.ibm.mq.MQException: JMSCMQ0001: IBM MQ call failed with compcode '2' ('MQCC_FAILED') reason '2278' ('MQRC_CLIENT_CONN_ERROR').
    at com.ibm.msg.client.wmq.common.internal.Reason.createException(Reason.java:203)
    ... 31 common frames omitted
Caused by: com.ibm.mq.jmqi.JmqiException: CC=2;RC=2278
    at com.ibm.mq.jmqi.remote.api.RemoteFAP.jmqiConnect(RemoteFAP.java:1688)
    at com.ibm.mq.jmqi.remote.api.RemoteFAP.jmqiConnect(RemoteFAP.java:1273)
    at com.ibm.mq.ese.jmqi.InterceptedJmqiImpl.jmqiConnect(InterceptedJmqiImpl.java:377)
    at com.ibm.mq.ese.jmqi.ESEJMQI.jmqiConnect(ESEJMQI.java:562)
    at com.ibm.msg.client.wmq.internal.WMQConnection.<init>(WMQConnection.java:357)
    ... 30 common frames omitted

官方故障排除在这里:2278 (08E6) (RC2278): MQRC_CLIENT_CONN_ERROR,但是说:

“当指定客户端通道定义表 (CCDT) 来确定通道的名称时,也会出现在 Java™ 应用程序中,但无法找到该表本身。”

无论找到表文件,如果我故意拼错文件名,我会收到 FileNotFoundException。

那么,我错过了什么?

【问题讨论】:

  • 更新,但仍然无法正常工作:名为 SYSTEM.DEF.CLNTCONN 的默认“客户端连接通道”并未指向名为 QM1 的队列管理器,尽管它似乎指向了那里。
  • 设置后收到新错误:JmqiException: CC=2;RC=2540;AMQ9204: Connection to host '' denied. [1=com.ibm.mq.jmqi.JmqiException[CC=2;RC=2540;AMQ9520:通道未远程定义。 [3=SYSTEM.DEF.CLNTCONN]],3=

标签: spring-boot docker jms ibm-mq spring-jms


【解决方案1】:

您找到的2278 MQRC_CLIENT_CONN_ERROR 是因为应用程序找不到与指定的队列管理器名称匹配的通道。

2540 MQRC_UNKNOWN_CHANNEL_NAME 错误是因为通过设置通道 SYSTEM.DEF.CLNTCONNQMNAME 字段,您现在正尝试连接到名为 SYSTEM.DEF.CLNTCONNSVRCONN 通道,但该通道不存在。


默认情况下,新队列管理器附带一个默认通道表,该表位于 MQDATA 路径下的以下位置:qmgrs/&lt;QMGR_NAME&gt;/@ipcc/AMQCLCHL.TAB

默认频道表仅包含一个名为 SYSTEM.DEF.CLNTCONNCLNTCONN 频道。这只是为了显示新定义的CLNTCONN 频道的默认值。

在队列管理器上,您的客户端应用程序连接到 SVRCONN 通道。在连接的客户端,如果您使用 CCDT,与队列管理器 SVRCONN 配对的通道类型是 CLNTCONN


由于您要连接到名为 DEV.ADMIN.SVRCONNSVRCONN 频道,因此您需要使用名为 DEV.ADMIN.SVRCONNCLNTCONN 频道定义 CCDT。

我建议不要修改默认 CCDT,而是创建一个新的。


您可以使用以下步骤来创建 CCDT:

echo "DEFINE CHL(DEV.ADMIN.SVRCONN) CHLTYPE(CLNTCONN) QMNAME(QM1) CONNAME(`localhost(1414)`)" | MQCHLLIB=/PATH/TO/CCDT MQCHLTAB=NAME_OF_CCDT runmqsc -n

只需将MQCHLLIBMQCHLTAB 的值替换为您要调用CCDT 的实际路径和名称,例如,要在/tmp 中创建一个名为AMQCLCHL.TAB 的CCDT,请使用以下命令:

echo "DEFINE CHL(DEV.ADMIN.SVRCONN) CHLTYPE(CLNTCONN) QMNAME(QM1) CONNAME(`localhost(1414)`)" | MQCHLLIB=/tmp MQCHLTAB=AMQCLCHL.TAB runmqsc -n

如需更多展示如何创建 CCDT 以及 MQ 如何在 CCDT 中选择特定通道的示例,您可以查看我对 Connecting to IBM MQ using CCDT file in JMS 的回答。

【讨论】:

  • 哇,大吃一惊,它有效!非常感谢你!
猜你喜欢
  • 2018-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多