3
votes

I am using this official IBM tutorial: MQ JMS application development with Spring Boot

and using IBM® MQ Advanced for Developers in docker got from this docker hub page: ibmcom/mq

MQ is started with this command:

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

It's up and running, and I'm able to connect to it using connection name and channel info:

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

However I get an error when I try to connect to it using the CCDT file. I get this CCDT file with this command:

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

I've set the proper application.yml property:

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

but I get this error:

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

The official troubleshoot is here: 2278 (08E6) (RC2278): MQRC_CLIENT_CONN_ERROR, but is says:

"It also occurs in Java™ applications when a client channel definition table (CCDT) is specified to determine the name of the channel, but the table itself cannot be found."

However the table file is found, if I mispell the filename on purpose, I get a FileNotFoundException.

So, what am I missing?

1
UPDATE, but still not works: The default "Client connection Channel" named SYSTEM.DEF.CLNTCONN did not pointed to queuemanager named QM1, even though it seemd like it pointed there.Kumite
After setting it, I receive a new error: JmqiException: CC=2;RC=2540;AMQ9204: Connection to host '' rejected. [1=com.ibm.mq.jmqi.JmqiException[CC=2;RC=2540;AMQ9520: Channel not defined remotely. [3=SYSTEM.DEF.CLNTCONN ]],3=Kumite

1 Answers

5
votes

The 2278 MQRC_CLIENT_CONN_ERROR as you found was because the application could not find a channel matching the queue manager name being specified.

The 2540 MQRC_UNKNOWN_CHANNEL_NAME error is because by setting the QMNAME field of the channel SYSTEM.DEF.CLNTCONN you are now attempting to connect to a SVRCONN channel called SYSTEM.DEF.CLNTCONN which does not exist.


By default a new queue manager comes with a default channel table found in the following location under the MQDATA path: qmgrs/<QMGR_NAME>/@ipcc/AMQCLCHL.TAB

The default channel table only contains a single CLNTCONN channel called SYSTEM.DEF.CLNTCONN. This is meant only to show the default values for newly defined CLNTCONN channels.

On the queue manager your client application connects to a SVRCONN channel. On the client side of the connection if you use a CCDT the channel type that pairs up with a queue managers SVRCONN is a CLNTCONN.


Since you are connecting to a SVRCONN channel called DEV.ADMIN.SVRCONN you need to define a CCDT with a CLNTCONN channel called DEV.ADMIN.SVRCONN.

I would recommend against modifying the default CCDT and instead just create a new one.


You can use the following steps to create a CCDT:

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

Just replace the values of MQCHLLIB and MQCHLTAB with the actual path and name you want to call the CCDT, for example, to create a CCDT called AMQCLCHL.TAB in /tmp use the following command:

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

For some more examples showing how to create CCDTs and how MQ selects a specific channel in the CCDT you can review this my answer to Connecting to IBM MQ using CCDT file in JMS.