关于java:在JMS中使用CCDT文件连接IBM MQ

Connecting to IBM MQ using CCDT file in JMS

我正在尝试使用 JMS 和客户端通道定义表 (CCDT) 连接到 IBM MQ。当我单独指定 MQ 属性时,我能够成功连接到 QueueManager。
但是当我尝试使用 CCDT 文件时,我得到了以下异常。

由于客户端通道定义表 (CCDT) 用于确定客户端应用程序用于连接到队列管理器的通道定义,因此我没有设置 QueueManager 名称。

1
2
3
4
5
6
7
8
ERROR> com.ssc.ach.mq.JMSMQReceiver[main]: errorMQJMS2005: failed to create MQQueueManager for ''
javax.jms.JMSException: MQJMS2005: failed to create MQQueueManager for ''
    at com.ibm.mq.jms.services.ConfigEnvironment.newException(ConfigEnvironment.java:586)
    at com.ibm.mq.jms.MQConnection.createQM(MQConnection.java:2110)
    at com.ibm.mq.jms.MQConnection.createQMNonXA(MQConnection.java:1532)
    at com.ibm.mq.jms.MQQueueConnection.<init>(MQQueueConnection.java:150)
    at com.ibm.mq.jms.MQQueueConnectionFactory.createQueueConnection(MQQueueConnectionFactory.java:174)
    at com.ibm.mq.jms.MQQueueConnectionFactory.createConnection(MQQueueConnectionFactory.java:1066)

我正在使用 .setCCDTURL(ccdt); 方法设置 CCDT URL。

1
2
3
private MQQueueConnectionFactory  mqQueueConnectionFactory = new MQQueueConnectionFactory();
         mqQueueConnectionFactory.setCCDTURL(ccdt);
         queueConnection = mqQueueConnectionFactory.createConnection(username, pwd);

当我尝试使用以下配置而不是 CCDT 文件进行连接时,它会连接到 MQ。

1
2
3
4
5
         mqQueueConnectionFactory.setHostName(host);
         mqQueueConnectionFactory.setChannel(channel);
         mqQueueConnectionFactory.setPort(port);
         mqQueueConnectionFactory.setQueueManager(qManager);
         mqQueueConnectionFactory.setTransportType(1);

我是否需要设置 setQueueManager 以及 CCDT 文件,因为例外情况是 failed to create MQQueueManager for ''


CCDT 不是用来在文本编辑器中读取的,它是一个二进制格式的文件。每个 CLNTCONN 通道的 CCDT 中的参数之一是 QMNAME。了解 QMNAME 设置为什么以及您在 CCDT 中定义了多少个 CLNTCONN 通道以及您想要完成什么将有助于确定应该为 setQueueManager 指定什么值。

如果只有一个 CLNTCONN 通道,那么您可以指定以下内容,无论 QMNAME 属性设置为什么,它都将使用单个通道进行连接:

1
setQueueManager("*");

如果文件中有多个 CLNTCONN 通道,每个通道都指定了不同的 QMNAME,假设名称与在主机和与通道关联的端口上侦听的实际队列管理器名称匹配,您将传递队列管理器名称:

1
setQueueManager("QMGRNAME");

如果文件中有多个 CLNTCONN 通道,每个通道都指定了相同的 QMNAME,其中此名称并不意味着反映在与每个通道关联的主机和端口上侦听的实际队列管理器名称,这是称为队列管理器组,这将用于您希望客户端连接到任意数量的不同主机和端口并且您不需要知道要连接到哪个队列管理器,在这种情况下您将传递队列管理器以 *:

为前缀的组名

1
setQueueManager("*QMGRGROUPNAME");

上述的另一种变体是,如果文件中有多个 CLNTCONN 通道,每个通道都指定了全空白(空格)或 NULL QMNAME,这称为队列管理器组,这是有意的您希望客户端连接到任意数量的不同主机和端口,并且您不需要知道要连接到哪个队列管理器,在这种情况下,您可以将队列管理器名称作为单个空格 或什么都不传递在所有``:

1
2
3
setQueueManager("");
//or
setQueueManager("");

如果您根本不使用 setQueueManager,上述最后一个用例可能会起作用。

如果您想查看 CCDT 的内容,您可以使用 MQ v8 和更高版本的客户端或服务器安装中附带的 runmqsc 命令。

对于 Unix ksh/bash shell,使用以下命令:

1
2
3
export MQCHLLIB=PATH/OF/CCDT
export MQCHLTAB=NAME_OF_CCDT
runmqsc -n

对于 Windows,请使用以下命令:

1
2
3
set MQCHLLIB=PATH/OF/CCDT
set MQCHLTAB=NAME_OF_CCDT
runmqsc -n

runmqsc 程序启动并显示 Starting local MQSC for 'NAME_OF_CCDT'. 后,您可以运行以下命令查看通道详细信息:

1
DIS CHL(*)

下面是一个更具体的命令来缩小返回的字段数量:

1
DIS CHL(*) QMNAME CONNAME


我有一段时间没看它了,但我认为正确的格式是:

1
2
3
4
MQQueueConnectionFactory qcf = new MQQueueConnectionFactory();
qcf.setQueueManager(qManager);
qcf.setCCDTURL(ccdt);
conn = qcf.createConnection(username, pwd);