编程语言
首页 > 编程语言> > java-如何将消息发送到托管在IBM MQ集群中不同队列管理器和主机名中的不同队列

java-如何将消息发送到托管在IBM MQ集群中不同队列管理器和主机名中的不同队列

作者:互联网

我基于Apache骆驼的应用正在消耗来自IBM队列之一的消息,例如以下是连接工厂的详细信息

hostname=host1000
QManager=QM1000
Port="some port"
Channel="common channel"

消耗和处理并将响应发送到来自消息头的ReplyQueue的骆驼流.

 from(wmq:queue:<INPUT_QUEUE>)
.bean("processBean")
.bean("beanToSendMsgToReplyQueue")

在骆驼标头中,我在JMSReplyQueue下面.您可以看到它是不同的队列管理器,并且该队列管理器来自不同的主机,但是在集群环境中.

JMSReplyTo = queue://QM1012/TEST.REPLY?targetClient=1

队列管理器也在两者之间.喜欢

queue://<queue-manager>//<queue-name>?<other parameters>

以下是我在发送消息时遇到的异常.

ERROR o.apache.camel.processor.DefaultErrorHandler:215 - Failed delivery for (MessageId: ID-xxxxxxxxx-0-4 on ExchangeId: ID-xxxxxx-42443-1492594420697-0-1). Exhausted after delivery attempt: 1 caught: org.apache.camel.ResolveEndpointFailedException: Failed to resolve endpoint: wmq://queue://QM1012/TEST.REPLY?targetClient=1 due to: Failed to resolve endpoint: wmq://queue://TAP2001R5/TEST?targetClient=1 due to: There are 1 parameters that couldn't be set on the endpoint. Check the uri if the parameters are spelt correctly and that they are properties of the endpoint. Unknown parameters=[{targetClient=1}]. Processed by failure processor: FatalFallbackErrorHandler[Pipeline[[Channel[sendTo(Endpoint[wmq://queue:BACKOUT_Q])], Channel[DelegateSync[com.xxx.yyy.listener.XXXOnExceptionProcessor@21c66ee4]], Channel[Stop]]]]

任何人都可以帮我发送消息到不同的队列管理器队列,该队列位于不同的主机中,但都在同一群集中.另外,队列管理器名称位于字符串的中间,因此如何解决该问题.
如果您需要更多详细信息,请告诉我.

更新-1:
尝试使用相同的队列管理器并且没有参数

JMSReplyTo =队列:// QM1000 / QUEUE_V1
低于异常我得到

org.springframework.jms.InvalidDestinationException: JMSWMQ2008: Failed to open MQ queue 'QM1000/QUEUE_V1'.; nested exception is com.ibm.msg.client.jms.DetailedInvalidDestinationException: JMSWMQ2008: Failed to open MQ queue 'QM1000/QUEUE_V1'. JMS attempted to perform an MQOPEN, but WebSphere MQ reported an error. Use the linked exception to determine the cause of this error. Check that the specified queue and queue manager are defined correctly.; nested exception is com.ibm.mq.MQException: JMSCMQ0001: WebSphere MQ call failed with compcode '2' ('MQCC_FAILED') reason '2189' ('MQRC_CLUSTER_RESOLUTION_ERROR').

更新2

我可以使用普通的javax.jms.*和com.ibm.mq.jms.* api将消息发送到JMSReplyTo,但不能通过Apache骆驼发送. Camel用户/开发人员小组的任何人都可以帮助我使用骆驼组件来处理相同的事情.

@Override
public void process(Exchange exchange)
    throws Exception {

    QueueConnection m_connection = this.connectionFactory.createQueueConnection();
    //m_connection.start();
    boolean transacted = false;

    QueueSession session = m_connection.createQueueSession(transacted, QueueSession.AUTO_ACKNOWLEDGE);
    TextMessage outMessage = session.createTextMessage();
    outMessage.setText(exchange.getIn().getBody());
    MQQueue mq = new MQQueue(
        "queue://QM1012/TEST.REPLY");
    QueueSender queueSender = session.createSender((MQQueue) mq);
    queueSender.send(outMessage);

    /* producerTemplate.send("wmq:" + "queue://QM1012/TEST.REPLY", exchange); */
}

解决方法:

您想与两个不同的队列管理器进行通信,因此您需要相应地定义两个Camel JMS组件实例.骆驼无法神奇地知道QM1000或QM1012的含义以及如何访问QM.

首先,两个WMQ QM需要两个JMS连接工厂实例.如何获得这些取决于您的执行环境.在JEE服务器上,配置后可以使用JNDI访问连接池.查看有关如何设置JMS池的appserver文档.如果您独立运行,请查看Spring JMS连接缓存或Atomikos(如果需要XA事务).
假设QM1000的CF是sourceCF,而QM1012的CF是targetCF.

现在,您可以定义两个Camel JMS组件实例,每个QM实例一个.将连接工厂注入JMS组件(.setConnectionFactory(…)).
假设您定义一个ID为“ jmssource”的Camel JMS组件,注入sourceCF.在JMS组件ID“ jmstarget”中,注入targetCF.
如何做到这一点取决于您的环境(JEE / CDI,Spring,纯Java).看看stackoverflow,有示例.

现在,您可以使用以下语法在骆驼路线上指定骆驼JMS生产者和消费者:

.from("jmssource:INPUT_QUEUE")
  ...
  (do some processing)
  ...
  .to("jmstarget:QUEUE_V1")

您不能使用Camel的JMS答复逻辑(使用JMSReplyTo标头)来答复另一个队列管理器.我认为JMS标准不允许这样做.您需要通过发送到回复队列来明确地进行回复.

对于设置targetClient选项,目标解析器可能会有用:

import org.springframework.jms.support.destination.DynamicDestinationResolver;
import org.springframework.jms.support.destination.DestinationResolver;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Session;
import com.ibm.mq.jms.JMSC;
import com.ibm.mq.jms.MQDestination;

public class WMQDestinationResolver extends DynamicDestinationResolver implements DestinationResolver {
  private int targetClient = JMSC.MQJMS_CLIENT_JMS_COMPLIANT;

  public void setTargetClient(int targetClient) {
    this.targetClient = targetClient;
  }

  public Destination resolveDestinationName(Session session, String destinationName, boolean isPubSubDomain) throws JMSException {
    Destination destination = super.resolveDestinationName(session, destinationName, isPubSubDomain);
    if (destination instanceof MQDestination) {
      MQDestination mqDestination = (MQDestination) destination;
      mqDestination.setTargetClient(targetClient);
    }
    return destination;
  }
}

标签:java,apache-camel,ibm-mq
来源: https://codeday.me/bug/20191013/1906556.html