一些遗留代码在使用 JMS 类连接到 MQ 的大型机上运行。
旧版本使用 Java 8、带有 Spring 5 的 Java EE 和 IBM 提供的 JAR:com.ibm.mq.jar、com.ibm.mq.jmqi.jar、com.ibm.mqjms.jar。
在我们切换到 Java 17、Jakarta EE 和 Spring 6 后,代码开始失败并出现以下错误:
Caused by: com.ibm.msg.client.jakarta.jms.DetailedJMSSecurityException: JMSWMQ2008: Failed to open MQ queue 'XXXXXXXX.YYYYYYYY'.
at com.ibm.msg.client.jakarta.wmq.common.internal.Reason.reasonToException(Reason.java:531)
at com.ibm.msg.client.jakarta.wmq.common.internal.Reason.createException(Reason.java:215)
at com.ibm.msg.client.jakarta.wmq.internal.WMQMessageConsumer.checkJmqiCallSuccess(WMQMessageConsumer.java:222)
at com.ibm.msg.client.jakarta.wmq.internal.WMQMessageConsumer.checkJmqiCallSuccess(WMQMessageConsumer.java:156)
at com.ibm.msg.client.jakarta.wmq.internal.WMQConsumerShadow.initialize(WMQConsumerShadow.java:1172)
at com.ibm.msg.client.jakarta.wmq.internal.WMQSyncConsumerShadow.initialize(WMQSyncConsumerShadow.java:128)
at com.ibm.msg.client.jakarta.wmq.internal.WMQMessageConsumer.<init>(WMQMessageConsumer.java:486)
at com.ibm.msg.client.jakarta.wmq.internal.WMQSession.createConsumer(WMQSession.java:934)
at com.ibm.msg.client.jakarta.jms.internal.JmsSessionImpl.createConsumer(JmsSessionImpl.java:1012)
at com.ibm.msg.client.jakarta.jms.internal.JmsSessionImpl.createConsumer(JmsSessionImpl.java:1097)
at com.ibm.msg.client.jakarta.jms.internal.JmsQueueSessionImpl.createReceiver(JmsQueueSessionImpl.java:103)
at com.ibm.mq.jakarta.jms.MQQueueSession.createReceiver(MQQueueSession.java:87)
at xxxx.api.messaging.JMSMessagingManager.open(JMSMessagingManager.java:279)
... 4 common frames omitted
Caused by: com.ibm.mq.MQException: JMSCMQ0001: IBM MQ call failed with compcode '2' ('MQCC_FAILED') reason '2035' ('MQRC_NOT_AUTHORIZED').
at com.ibm.msg.client.jakarta.wmq.common.internal.Reason.createException(Reason.java:203)
新代码使用依赖:
implementation group: 'com.ibm.mq', name: 'com.ibm.mq.jakarta.client', version: '9.4.1.0'
如上所述,我们需要使用 Jakarta EE 而不是 Java EE,因为 Spring 6 支持 Jakarta EE 9。
失败的设置,我们用来在 Windows 计算机上本地运行应用程序,同时以 client 模式连接到远程队列。
生产中的应用程序与 MQ 位于同一主机上,并使用绑定模式(无密码,只有用户 ID,即 MVS 用户 ID)
我们使用 SecExit 以 client 模式连接,并使用登录名和密码(同样,这仅适用于本地计算机上的开发环境):
mq.security.exit = biz.capitalware.mqausx.MQAUSXJ2EE
如果我故意使用错误的用户 ID 或密码,我会收到不同的错误:
Caused by: com.ibm.mq.jmqi.JmqiException: CC=2;RC=2009;AMQ9204: Connection to host 'xxxxxxx(1415)' rejected. [1=com.ibm.mq.jmqi.JmqiException[CC=2;RC=2009],3=xxxxxxxxx(1415),4=,5=RemoteConnection.asyncConnectionBroken]
at com.ibm.mq.jmqi.remote.api.RemoteFAP$Connector.jmqiConnect(RemoteFAP.java:13703)
at com.ibm.mq.jmqi.remote.api.RemoteFAP$Connector.access$100(RemoteFAP.java:13206)
at com.ibm.mq.jmqi.remote.api.RemoteFAP.jmqiConnect(RemoteFAP.java:1456)
at com.ibm.mq.jmqi.remote.api.RemoteFAP.jmqiConnect(RemoteFAP.java:1397)
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.jakarta.wmq.internal.WMQConnection.<init>(WMQConnection.java:417)
因此,我假设身份验证通过正常,但是当队列侦听器创建时出现问题。
我已经搜索过这个问题并阅读了这些讨论:
使用 com.ibm.mq.jakarta.client.jar 9.3 迁移到 Spring Boot 3 后,IBM MQ JMS 无法工作
还有这个
IBM MQ 调用失败,代码为“2”(“MQCC_FAILED”),原因为“2035”(“MQRC_NOT_AUTHORIZED”)
我尝试过不同的组合
-Dcom.ibm.mq.cfg.jmqi.useMQCSPauthentication=true -Duser.name=xxxxx
-Dcom.ibm.mq.cfg.jmqi.useMQCSPauthentication=false -Duser.name=xxxxx
-Dcom.ibm.mq.cfg.jmqi.useMQCSPauthentication=false
没有任何帮助。事实上没有区别,唯一的区别是当我尝试错误的密码时。
由于代码适用于 Java EE 的 Java 8 和 MQ JMS 库,我不想修改 QMGR 端的任何设置,主要是因为这个新设置仅需要开发环境。
任何帮助/提示表示赞赏。
我强烈建议您联系 Capitalware 支持。
您似乎已配置并正在使用客户端安全出口进行MQ 身份验证用户安全出口 (MQAUSX),并且我认为 z/OS MQAUSX 服务器端安全出口已完全配置。
生产中的应用程序与 MQ 位于同一主机上并使用绑定模式(无密码,只有用户 ID,即 MVS 用户 ID)
这个评论没有任何意义。那么,您正在 z/OS 上与 z/OS 队列管理器位于同一 LPAR 中运行 Java 应用程序吗?此外,在绑定模式下,MQ 客户端库不使用通道,因此不会调用通道安全出口。
如果我故意使用错误的用户 ID 或密码,我会收到不同的错误: 引起原因:com.ibm.mq.jmqi.JmqiException:CC=2;RC=2009;AMQ9204
原因码2009表示MQAUSX服务器端安全出口关闭通道。即身份验证失败。
您说您从使用 MQ v8.0 切换到最新的 MQ CSD 9.4.1.0,但 IBM 已对客户端到服务器端队列管理器之间发送的 UserId 的下划线处理进行了更改。我敢打赌你会被这个烧伤。
原因为:com.ibm.mq.MQException:JMSCMQ0001:IBM MQ 调用失败,代码为“2”(“MQCC_FAILED”),原因为“2035”(“MQRC_NOT_AUTHORIZED”)。
您的应用程序的 UserId 和密码似乎已成功通过 MQAUSX 服务器端安全出口进行身份验证,但在“连接到队列管理器”或“打开队列”的 RACF/ACF2 授权上失败,因为用于授权的 UserId 不匹配.
要求您的 z/OS MQAdmin 检查 MQAUSX 日志文件以查看 MQAUSX 输出的内容。它将包含经过身份验证的 UserId 和用于访问 z/OS 队列管理器的 UserId 的详细输出。另外,询问 z/OS MQAdmin 队列管理器的日志文件是否记录了 2035 的 RC 以及错误消息中的内容。
最后,您是否切换了通道名称以连接到 z/OS 队列管理器?如果是,旧频道和新频道的 MCAUSER 字段的值是什么?