Ответ, получаемый от ibm mq, иногда не совпадает с запросом
Я копирую код 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 ответа
Можете ли вы использовать другую тему для дифференциации?
Это плохая идея, когда вы делаете обмен сообщениями точка-точка.
destination = context.createQueue("queue:///" + responseQueue + "?targetClient=1");
Похоже, что ваш responseQueue разделен между несколькими потребителями. У вас есть 2 варианта:
- Создайте собственную временную динамическую очередь и установите ее в качестве очереди "Ответить"
т.е.
Queue replyQ = session.createTemporaryQueue();
- Используйте шаблон сообщений MsgId / CorrelId "запрос-ответ".
т.е. следуйте рекомендациям на этой странице: не удалось получить ответ от IBM MQ с помощью приложения JMS
Похоже, все ответы отправляются на 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);