【问题标题】:Two queue manager with different channel not allowed不允许使用不同通道的两个队列管理器
【发布时间】:2020-11-22 03:57:10
【问题描述】:

我使用带有 ibm mq 的 spring boot 2.3.2。 我使用属性文件设置 mq。

ibm.mq.queueManager=
ibm.mq.channel=
ibm.mq.connName
ibm.mq.user
ibm.mq.password
ibm.mq.useIBMCipherMappings=false
ibm.mq.userAuthenticationMQCSP=false
ibm.mq.sslCipherSuite=TLS_RSA_WITH_AES_128_CBC_SHA256

效果很好。

我需要创建另一个工厂才能连接到另一个通道。所以我想创建一个类似的,默认创建,但频道名称不同。

所以我创建了一个配置类

@EnableJms
@Configuration
public class JmsConfig {
@Bean
    public MQQueueConnectionFactory jmsMQConnectionFactoryPayment() throws JMSException {
        MQQueueConnectionFactory connectionFactory = new MQQueueConnectionFactory();
        connectionFactory.setQueueManager("AD_TEST");
        connectionFactory.setChannel("FROM.PAYMENTMNG");
        connectionFactory.setConnectionNameList("wmqd1.int.test.com(1818),wmqd2.int.test.com(1818)");


        connectionFactory.setBooleanProperty(WMQConstants.USER_AUTHENTICATION_MQCSP, false);

        connectionFactory.setStringProperty(WMQConstants.WMQ_SSL_CIPHER_SUITE, "TLS_RSA_WITH_AES_128_CBC_SHA256");
        connectionFactory.setIntProperty(CommonConstants.WMQ_CONNECTION_MODE, CommonConstants.WMQ_CM_CLIENT);


        System.setProperty("com.ibm.mq.cfg.useIBMCipherMappings", String.valueOf(Boolean.FALSE));

        connectionFactory.createConnection("123", "123");
        return connectionFactory;
    }

    @Bean
    JmsListenerContainerFactory<?> jmsContainerFactoryPayment() throws JMSException {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        factory.setConnectionFactory(jmsMQConnectionFactoryPayment());
        return factory;
    }

    @Bean("payment")
    JmsTemplate jmsTemplatePayment() throws JMSException {
        JmsTemplate template = new JmsTemplate();
        template.setConnectionFactory(jmsMQConnectionFactoryPayment());
        return template;
    }


}

在我的课上

@JmsListener(destination="xxx", containerFactory="jmsContainerFactoryPayment"){
    ....
}

当我开始申请时,我得到

com.ibm.msg.client.jms.DetailedIllegalStateException: JMSWMQ0018: E Failed to connect to queue manager 'AD_TEST' with connection mode 'Client' and host name 'wmqd1.int.test.com(1818),wmqd2.int.test.com(1818)'.

                at com.ibm.msg.client.wmq.common.internal.Reason.reasonToException(Reason.java:489) ~[com.ibm.mq.allclient-9.2.0.0.jar:9.2.0.0 - p920-L200710.DE]

                at com.ibm.msg.client.wmq.common.internal.Reason.createException(Reason.java:215) ~[com.ibm.mq.allclient-9.2.0.0.jar:9.2.0.0 - p920-L200710.DE]

                at com.ibm.msg.client.wmq.internal.WMQConnection.<init>(WMQConnection.java:450) ~[com.ibm.mq.allclient-9.2.0.0.jar:9.2.0.0 - p920-L200710.DE]

                at com.ibm.msg.client.wmq.factories.WMQConnectionFactory.createV7ProviderConnection(WMQConnectionFactory.java:8475) ~[com.ibm.mq.allclient-9.2.0.0.jar:9.2.0.0

Caused by: com.ibm.mq.MQException: JMSCMQ0001: IBM MQ  call failed with compcode '2' ('MQCC_FAILED') ; reason '2538' ('MQRC_HOST_NOT_AVAILABLE').

                at com.ibm.msg.client.wmq.common.internal.Reason.createException(Reason.java:203) ~[com.ibm.mq.allclient-9.2.0.0.jar:9.2.0.0 - p920-L200710.DE]

                ... 51 common frames omitted

似乎我们不能有两个具有相同主机但不同通道的队列管理器

【问题讨论】:

  • MQRC_HOST_NOT_AVAILABLE 表示无法成功建立与您提供的连接列表的 TCP/IP 连接。您是否检查过您可以 ping 主机名并且侦听器正在运行?
  • 是我在属性文件中使用的那个
  • 是不是和报错信息中的连接一样?
  • 是的,也尝试使用默认连接(属性文件)并创建一个新连接,得到相同的结果。我在网上找不到任何示例来获得两个具有不同配置的队列管理器。
  • 对不起 - 我有点困惑。您是否可以更新显示原始和新详细信息的问题,即第一个连接(有效?)和您显示失败的第二个连接。这可能有助于弄清楚出了什么问题。

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


【解决方案1】:

我已经用 IBM MQ 配置了 Spring Boot 来测试这个。从IBM Messaging GitHub Repo 中提供的示例开始,我添加了两个额外的侦听器,如下所示。

首先我在application.properties 文件中添加了一些附加属性

my.mq.queueManager=QM2
my.mq.channel=DEV.APP.SVRCONN
my.mq.connName=localhost(1415)
my.mq.user=<your_user_name>
my.mq.password=<your_password>

我保持Application.java 不变,复制Listener.java 以创建ListenerTwo.javaListenerThree.java。然后我在示例中添加了一个新的ListenerBeanConfig.java 类。

ListenerTwo.java 已更改为绑定到稍后创建的新 ConnectionFactory 配置 listenerTwoFactory

@JmsListener(destination = Application.qName, containerFactory = "listenerTwoFactory")

ListenerThree.java 已更改为绑定到新的 listenerThreeFactory 配置和 Queue

@JmsListener(destination = "DEV.QUEUE.2", containerFactory = "listenerThreeFactory")

ListenerBeanConfig.java 类声明被注释,以便我可以通过为每个属性添加字符串来访问我的属性,例如queueManagerchannelconnName 等,并为每个属性提供设置方法,例如,

@Configuration
@EnableJms
@ConfigurationProperties(prefix="my.mq")
public class ListenerBeanConfig {

    String connName;
public void setConnName(String value) {
    System.out.println("connName is set to: "+value);
    connName = value;
  }

我注册了两个新的Listener bean

@Bean
  public ListenerTwo myListenerTwo() {
    return new ListenerTwo();
  }

@Bean
  public ListenerThree myListenerThree() {
    return new ListenerThree();
  }

然后我创建了新的连接工厂配置listenerTwoFactorylistenerThreeFactory

对于 listenerTwoFactory,我在 Spring Boot 配置中使用了 com.ibm.mq.jms 提供的 JMS 类

JmsConnectionFactory cf;

@Bean
  public DefaultJmsListenerContainerFactory listenerTwoFactory() {
  DefaultJmsListenerContainerFactory containerFactory = new DefaultJmsListenerContainerFactory();
  try {
    JmsFactoryFactory ff = JmsFactoryFactory.getInstance(WMQConstants.WMQ_PROVIDER);
    cf = ff.createConnectionFactory();
    cf.setStringProperty(WMQConstants.WMQ_CONNECTION_NAME_LIST, connName);
    cf.setStringProperty(WMQConstants.WMQ_CHANNEL, channel);
    cf.setIntProperty(WMQConstants.WMQ_CONNECTION_MODE, WMQConstants.WMQ_CM_CLIENT);
    cf.setStringProperty(WMQConstants.WMQ_QUEUE_MANAGER, queueManager);
    cf.setStringProperty(WMQConstants.WMQ_APPLICATIONNAME, "Spring Boot ListenerTwo");
    cf.setBooleanProperty(WMQConstants.USER_AUTHENTICATION_MQCSP, true);
    cf.setStringProperty(WMQConstants.USERID, user);
    cf.setStringProperty(WMQConstants.PASSWORD, password);
  } catch (JMSException jmsex) {
    System.out.println(jmsex);
  }
  containerFactory.setConnectionFactory(cf);
  return containerFactory;
}

对于 listenerThreeFactory,我使用了来自 com.ibm.mq.spring.boot 的 MQ JMS 助手类。

@Bean
public DefaultJmsListenerContainerFactory listenerThreeFactory() {
    MQConfigurationProperties myProps = new MQConfigurationProperties();
    myProps.setUser(user);
    myProps.setChannel(channel);
    myProps.setConnName(connName);
    myProps.setPassword(password);
    myProps.setQueueManager(queueManager);
    //No customizer
    MQConnectionFactoryFactory mqcff = new MQConnectionFactoryFactory(myProps,null);
    MQConnectionFactory mqcf = mqcff.createConnectionFactory(MQConnectionFactory.class);
    DefaultJmsListenerContainerFactory containerFactory = new DefaultJmsListenerContainerFactory();
    containerFactory.setConnectionFactory(mqcf);
    return containerFactory;
}

最后,我编译并运行了新的示例配置。将 IBM MQ 控制台用于两个 IBM MQ 队列管理器 docker 实例,我将消息发送到 QM1: DEV.QUEUE.1QM2: DEV.QUEUE.1, DEV.QUEUE.2。在终端上看到以下输出。

========================================
Received message is: message 1
========================================

========================================
ListenerTwo received message is: message 2
========================================

========================================
ListenerThree received message is: message 3
========================================

还测试了通过两个不同通道连接到 QM2 的所有三个侦听器:DEV.APP.SVRCONNDEV.APP.SVRCONN.TWO

我相信还有更优雅的方式来管理其他属性。

【讨论】:

    猜你喜欢
    • 2019-04-07
    • 2017-03-29
    • 1970-01-01
    • 2013-03-10
    • 1970-01-01
    • 2013-11-08
    • 1970-01-01
    • 2020-01-26
    • 2015-08-03
    相关资源
    最近更新 更多