【问题标题】:issues Connecting to IBM MQ on cloud连接到云上的 IBM MQ 的问题
【发布时间】:2019-07-16 05:21:57
【问题描述】:

在 IBM Cloud 上创建了一个 IBM MQ 并尝试连接 IBM 提供的 JMS 客户端。授权失败。

相同的程序在我的本地队列管理器上运行。任何见解都会帮助我探索云上的 IBM MQ。

  • 环境 = JDK 1.8
  • MQ 客户端 Jar = 9

我给了应用程序用户名/API 密钥,不知道为什么它没有连接

遵循 IBM 文档 https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_9.1.0/com.ibm.mq.sec.doc/q118680_.htm https://developer.ibm.com/messaging/learn-mq/mq-tutorials/develop-mq-jms/

异常跟踪

Exception in thread "main" 

com.ibm.msg.client.jms.DetailedJMSSecurityRuntimeException: JMSWMQ2007: Failed to send a message to destination 'RequestQ'.
JMS attempted to perform an MQPUT or MQPUT1; however IBM MQ reported an error.
Use the linked exception to determine the cause of this error.
    at com.ibm.msg.client.jms.DetailedJMSSecurityException.getUnchecked(DetailedJMSSecurityException.java:270)
    at com.ibm.msg.client.jms.internal.JmsErrorUtils.convertJMSException(JmsErrorUtils.java:173)
    at com.ibm.msg.client.jms.internal.JmsProducerImpl.send(JmsProducerImpl.java:633)
    at com.ibm.mq.samples.jms.JmsPutGet.main(JmsPutGet.java:122)
Caused by: com.ibm.mq.MQException: JMSCMQ0001: IBM MQ call failed with compcode '2' ('MQCC_FAILED') reason '2035' ('MQRC_NOT_AUTHORIZED').

/*
* (c) Copyright IBM Corporation 2018
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.ibm.mq.samples.jms;


import javax.jms.Destination;
import javax.jms.JMSConsumer;
import javax.jms.JMSContext;
import javax.jms.JMSException;
import javax.jms.JMSProducer;
import javax.jms.TextMessage;

import com.ibm.mq.constants.MQConstants;
import com.ibm.msg.client.jms.JmsConnectionFactory;
import com.ibm.msg.client.jms.JmsConstants;
import com.ibm.msg.client.jms.JmsFactoryFactory;
import com.ibm.msg.client.wmq.WMQConstants;

/**
 * A minimal and simple application for Point-to-point messaging.
 *
 * Application makes use of fixed literals, any customisations will require
 * re-compilation of this source file. Application assumes that the named queue
 * is empty prior to a run.
 *
 * Notes:
 *
 * API type: JMS API (v2.0, simplified domain)
 *
 * Messaging domain: Point-to-point
 *
 * Provider type: IBM MQ
 *
 * Connection mode: Client connection
 *
 * JNDI in use: No
 *  ReadMe -CompatibleMode
 *  
 */

public class JmsPutGet {

	// System exit status value (assume unset value to be 1)
	private static int status = 1;
	private static final String HOST = "ibm hostname"; // Host name or IP address
	private static final int PORT = 32442; // Listener port for your queue manager
	private static final String CHANNEL = "xxx.APP.SVRCONN"; //.APP.SVRCONN"; // Channel name
	private static final String QMGR = "QMxxx"; // Queue manager name
	private static final String APP_USER = "appusername"; // User name that application uses to connect to MQ
	private static final String APP_PASSWORD = "IBM API Key"; // Password that the application uses to connect to MQ
	private static final String QUEUE_NAME = "TestRequestQ"; // Queue that the application uses to put and get messages to and from
	
	/**
	 * Main method
	 *
	 * @param args
	 */
	public static void main(String[] args) {

		// Variables
		JMSContext context = null;
		Destination destination = null;
		JMSProducer producer = null;
		JMSConsumer consumer = null;



		try {
			// Create a connection factory
			JmsFactoryFactory ff = JmsFactoryFactory.getInstance(WMQConstants.WMQ_PROVIDER);
			JmsConnectionFactory cf = ff.createConnectionFactory();

			// Set the properties
			cf.setStringProperty(WMQConstants.WMQ_HOST_NAME, HOST);
			cf.setIntProperty(WMQConstants.WMQ_PORT, PORT);
			cf.setStringProperty(WMQConstants.WMQ_CHANNEL, CHANNEL);
			cf.setIntProperty(WMQConstants.WMQ_CONNECTION_MODE, WMQConstants.WMQ_CM_CLIENT);
			cf.setStringProperty(WMQConstants.WMQ_QUEUE_MANAGER, QMGR);
			cf.setStringProperty(WMQConstants.WMQ_APPLICATIONNAME, "JmsPutGet (JMS)");
			cf.setBooleanProperty(WMQConstants.USER_AUTHENTICATION_MQCSP, true);
			cf.setStringProperty(WMQConstants.USERID, APP_USER);
			cf.setStringProperty(WMQConstants.PASSWORD, APP_PASSWORD);
			/*cf.setBooleanProperty(JmsConstants.USER_AUTHENTICATION_MQCSP, false);*/
			/*cf.setBooleanProperty(MQConstants.USE_MQCSP_AUTHENTICATION_PROPERTY, false);*/
			/*cf.setBooleanProperty("WMQConstants.USER_AUTHENTICATION_MQCSP",false);*/
			

			// Create JMS objects
			context = cf.createContext();
			destination = context.createQueue("queue:///" + QUEUE_NAME);

			long uniqueNumber = System.currentTimeMillis() % 1000;
			TextMessage message = context.createTextMessage("Your lucky number today is " + uniqueNumber);

			producer = context.createProducer();
			producer.send(destination, message);
			System.out.println("Sent message:\n" + message);

			consumer = context.createConsumer(destination); // autoclosable
			String receivedMessage = consumer.receiveBody(String.class, 15000); // in ms or 15 seconds

			System.out.println("\nReceived message:\n" + receivedMessage);

			recordSuccess();
		} catch (JMSException jmsex) {
			recordFailure(jmsex);
		}

		System.exit(status);

	} // end main()

	/**
	 * Record this run as successful.
	 */
	private static void recordSuccess() {
		System.out.println("SUCCESS");
		status = 0;
		return;
	}

	/**
	 * Record this run as failure.
	 *
	 * @param ex
	 */
	private static void recordFailure(Exception ex) {
		if (ex != null) {
			if (ex instanceof JMSException) {
				processJMSException((JMSException) ex);
			} else {
				System.out.println(ex);
			}
		}
		System.out.println("FAILURE");
		status = -1;
		return;
	}

	/**
	 * Process a JMSException and any associated inner exceptions.
	 *
	 * @param jmsex
	 */
	private static void processJMSException(JMSException jmsex) {
		System.out.println(jmsex);
		Throwable innerException = jmsex.getLinkedException();
		if (innerException != null) {
			System.out.println("Inner exception(s):");
		}
		while (innerException != null) {
			System.out.println(innerException);
			innerException = innerException.getCause();
		}
		return;
	}

}

【问题讨论】:

  • 在安全例外情况下,客户端无法获得有关阻止连接的太多信息。您是否检查过队列管理器日志以了解队列管理器阻止连接的原因?请您将其添加到问题中。
  • 检查了它显示的 QManager 日志 确保客户端应用程序指定了密码并且密码对于用户 ID 是正确的。队列管理器连接的认证配置决定了用户 ID 存储库。例如,本地操作系统用户数据库或 LDAP 服务器。

标签: ibm-mq


【解决方案1】:

最可能的原因可能是尝试通过“CLOUD.APP.SVRCONN”通道获取/放入队列中的消息的用户没有正确的访问权限。默认情况下,通道身份验证记录可能会阻止此用户获取/放置消息。

解决方案

  1. 尝试使用“CLOUD.ADMIN.SVRCONN”,您的应用程序现在应该能够获取/放置消息。

  2. 在 CLOUD.APP.SVRCONN 的通道身份验证记录中为您的用户提供适当的访问权限。

【讨论】:

  • 它不能指向管理员频道,根据日志它说密码错误
【解决方案2】:

为了扩展上述 Rob 和 Paras 的响应,尝试连接到 MQ on Cloud 时出现 2035 响应的两个最常见原因通常如下;

  1. 需要启用 MQCSP 以便将完整(长)密码传递给队列管理器 details available here
  2. 设置适当的授权权限以访问名称不以“DEV.”开头的队列,details of which are here。 (默认情况下允许访问 DEV.队列,但其他队列必须为您的应用程序明确授权

正如 Rob 所建议的,队列管理器错误日志应显示详细信息以指示您可能处于哪种情况,并且可以从 IBM Cloud 用户界面中队列管理器详细信息选项卡内的“日志和诊断”选项卡下载.

问候,马特。

【讨论】:

  • 禁用了兼容模式,还是一样的问题 cf.setBooleanProperty(JmsConstants.USER_AUTHENTICATION_MQCSP, false); cf.setBooleanProperty(MQConstants.USE_MQCSP_AUTHENTICATION_PROPERTY, false); cf.setBooleanProperty("WMQConstants.USER_AUTHENTICATION_MQCSP",false);
  • 嗨@sivaganti - 实际上与上面的相反 - MQCSP 的使用是“不兼容”选择,因此您必须设置 USER_AUTHENTICATION_MQCSP = true 以禁用兼容性模式。同时,要确认的另一件事是您拥有 v8.0.0.0 或更高版本的 IBM MQ 客户端库,以便它将根据该指令执行操作。
猜你喜欢
  • 2020-09-18
  • 1970-01-01
  • 2012-08-19
  • 2015-01-24
  • 2016-01-21
  • 2022-11-08
  • 1970-01-01
  • 2023-04-05
  • 1970-01-01
相关资源
最近更新 更多