Ответ, получаемый от ibm mq, иногда не совпадает с запросом - PullRequest
0 голосов
/ 28 мая 2019

Я копирую код Java-клиента для вызова IBM MQ и передаю запрос в очередь, но иногда получаю неправильный ответ из очереди.

Например, если я отправляю следующеезапрос: F LOYFI6331760101046481882

Я ожидаю от ответа я должен получить F LOYFA36331760101046481882

Но на самом деле я получаю F LOYFA36331760101051292448

Как видите, номер карты неверен.

Вот код

import javax.jms.BytesMessage;
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.msg.client.jms.JmsConnectionFactory;
import com.ibm.msg.client.jms.JmsFactoryFactory;
import com.ibm.msg.client.wmq.WMQConstants;

public class MQClient {
    // System exit status value (assume unset value to be 1)
    private static int status = 1;

    public static byte[] sendAndReceive(String HOST, Integer PORT, String QMGR, String CHANNEL, String requestQueue, String responseQueue, String payload) {
        // Variables
        JMSContext context = null;
        Destination destination = null;
        JMSProducer producer = null;
        JMSConsumer consumer = null;
        BytesMessage receivedMessage = null;
        byte[] result = 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.setStringProperty(WMQConstants.WMQ_TARGET_CLIENT, "1");
            // Create JMS objects
            context = cf.createContext();
            destination = context.createQueue("queue:///" + requestQueue +"?targetClient=1");

            TextMessage message = context.createTextMessage(payload);

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

            destination = context.createQueue("queue:///" + responseQueue + "?targetClient=1");
            consumer = context.createConsumer(destination); // autoclosable
            receivedMessage= (BytesMessage)consumer.receive();
            System.out.println("Receiving message:" + receivedMessage);
            int text_length = new Long(receivedMessage.getBodyLength()).intValue();
            result = new byte[text_length];
            receivedMessage.readBytes(result, text_length);

            System.out.println("\nReceived message:\n" + new String(result));

            recordSuccess();

        } catch (JMSException jmsex) {
            recordFailure(jmsex);
        }finally {
            context.close();
        }

        return result;

    }
}

У меня есть другой проект для одновременного запуска метода MQClient.sendAndReceive() с тем же host, port, QMGR, channel, requestQueue и responseQueue, отличается только payload.

Так как мне исправить приведенный выше код, чтобы всегда получать правильный ответ, соответствующий запросу?

РЕДАКТИРОВАТЬ: 1. Для вопросов JoshMac, приложение означает IBM MQ один?Или приложение, которое будет вызывать мою sendAndReceive функцию?

Вот поток, который у меня есть, я использую поток мулов, беру запрос из POS, обрабатываю запрос, который должен вызвать IBM MQ (который находится на AS400), чтобы получить ответ от MQ, и отправить обратно вPOS.(В этом примере мне нужно отправить запрос на INQ1 и получить ответ от INQR1).Исходя из ответа ниже, кажется, что функция sendAndReceive рассматривается как Requester, мне нужен другой поток для вызова Responder для обработки ответа, поэтому receivedMessage= (BytesMessage)consumer.receive(); не застрянет?Поправь меня, если я не прав

Ответы [ 2 ]

0 голосов
/ 29 мая 2019

Похоже, что все ответы отправляются в INQR1.Чтобы помочь вашему приложению определить, какие из ответов предназначены для него, а какие можно игнорировать, вы можете использовать селектор, и обычно селектор по идентификатору корреляции, хотя вы можете использовать другие поля.

По сути, вы используете шаблон запроса / ответа, для которого есть выборки JMS - https://github.com/ibm-messaging/mq-dev-patterns/tree/master/JMS

Ваш запросчик будет иметь такую ​​логику:

String correlationID = String.format("%24.24s", UUID.randomUUID().toString());
message.setJMSCorrelationIDAsBytes(b);

для генерацииИдентификатор корреляции и добавьте его в сообщение.

Затем ваш запросчик создаст селектор на основе идентификатора корреляции для фильтрации очереди ответов:

try {
      b = correlationID.getBytes();
      selector = "JMSCorrelationID='ID:" + getHexString(b) + "'";
    } catch (Exception e) {
       ...
    }

, который вы используете для создания получателя сообщения:

JMSConsumer consumer = context.createConsumer(requestQueue, selector);
Message receivedMessage = consumer.receive();

КогдаВаш респондент получает первоначальный запрос, он может получить идентификатор корреляции:

String correlationID = receivedMessage.getJMSCorrelationID();

и использовать его для установки идентификатора корреляции для ответа:

message.setJMSCorrelationID(correlationID);
0 голосов
/ 28 мая 2019

Можете ли вы использовать разные темы для дифференциации?

Это плохая идея, когда вы делаете обмен сообщениями точка-точка.

destination = context.createQueue("queue:///" + responseQueue + "?targetClient=1");

Звучит так, что ваш responseQueue разделен между несколькими потребителями. У вас есть 2 варианта:

  1. Создайте свою собственную временную динамическую очередь и установите ее как «Reply-To» Очередь

т.е.

Queue replyQ = session.createTemporaryQueue();
  1. Использовать шаблон обмена сообщениями запрос-ответ MsgId / CorrelId.

т.е. Следуйте рекомендациям на этой странице: Не удалось получить ответ от IBM MQ с помощью приложения JMS

...