Не удалось получить ответ от IBM MQ с помощью приложения JMS
Мы общаемся с третьей стороной, используя IBM MQ в форме запроса / ответа. Мы отправляем им запрос, и они дают нам ответ. Сейчас у нас обоих есть простое приложение IBM MQ на основе Java. Мы планируем переписать наш код с помощью Spring JMS. Но мы не получаем никакого ответа в течение заданного времени, когда используется пружинный jms. Мы используем JMSTemplate для отправки или получения сообщений. Я делюсь своим фрагментом кода. Я что-то здесь не так делаю? Любые другие свойства я должен установить здесь?
// Request Part (we are sending request)
String request // this is the request string
byte[] reqData = request.getBytes(); // converting it into byte array to send
TextMessage txtMsg = session.createTextMessage(String.valueOf(reqData));
Destination replyToQName = jmsTemplate.getDestinationResolver().resolveDestinationName(session, responseQueueName, false);
txtMsg.setJMSReplyTo(replyToQName);
Destination requestQ = jmsTemplate.getDestinationResolver().resolveDestinationName(session, requestQueueName, false);
((JmsDestination) requestQ).setBooleanProperty( WMQConstants.WMQ_MQMD_WRITE_ENABLED, true );
((MQQueue) requestQ).setTargetClient(WMQConstants.WMQ_CLIENT_NONJMS_MQ); // setting this because third party application is native websphere mq java application
jmsTemplate.convertAndSend(requestQ, txtMsg);
// saved msgId of request for late use
String messageId = txtMsg.getJMSMessageID();
// Response fetching part
Destination responseQ = jmsTemplate.getDestinationResolver().resolveDestinationName(session, responseQueueName, false);
((JmsDestination) responseQ).setBooleanProperty(WMQConstants.WMQ_MQMD_READ_ENABLED, true);
((JmsDestination) responseQ).setObjectProperty( WMQConstants.JMS_IBM_MQMD_CORRELID, msgIdText);
jmsTemplate.setReceiveTimeout(30000L);
String filter = "JMSCorrelationID='" + messageId + "'"; // to match request message's messageId with response message's correlationId
TextMessage respMsg = (TextMessage) jmsTemplate.receiveSelected(responseQ, filter);
Ниже мой код соединения фабрики:
MQConnectionFactory factory = new MQQueueConnectionFactory();
factory.setHostName("hostname");
factory.setPort(1420);
factory.setQueueManager("QM1");
factory.setChannel("TEST.CHANNEL");
factory.setIntProperty(WMQConstants.WMQ_CONNECTION_MODE, WMQConstants.WMQ_CM_CLIENT);
3 ответа
Основной проблемой здесь является то, что базовая диагностика не была проведена, или если они есть, то результаты, не представленные в вопросе. Я не знаю Spring, но я знаю базовую отладку MQ. Я также жил в штате Миссури, штат "Покажи мне", достаточно долго, чтобы принять девиз штата как свой собственный. Покажите мне, как все предположения были проверены. Как администратор MQ я бы работал с разработчиком, чтобы подтвердить все предположения визуальным осмотром. Вот как я подхожу к этому:
Проверить исходящее сообщение
- Остановить исходящий канал
- PUT сообщение с запросом
- ПОЛУЧИТЬ (ВКЛЮЧИТЬ) XMitQ и просмотреть сообщение
а) появляется ли сообщение?
б) Имеет ли сообщение правильный формат и значения?
c) Правильно ли заполнены поля Reply-To?
d) Срок действия сообщения истек, и если да, то достаточно ли велик срок действия?
Проверьте ответное сообщение
- Остановить приложение
- Перезапустите исходящий канал
- Просмотр очереди ответа
а) приходит ли сообщение?
б) Правильно ли отформатирован и заполнен?
Резюме
В конце концов, есть только два вероятных сценария, где это может пойти не так, и оба легко проверить.
Во-первых, возможно, новая программа вообще не помещает никаких сообщений. На самом деле это довольно часто встречается при рефакторинге кода для использования нового фреймворка. Попытка отладки без положительной проверки сообщения приводит к PUT (и явно указывает в вопросе, как это было сделано и каков результат), делает очень большое предположение. Не думай Убедитесь, что сообщение создано, и сообщите нам детали при запросе, чтобы мы могли устранить его как основную причину.
Во-вторых, работая в обратном направлении от приложения, принимающего запросы, не имеет значения, какое приложение отправляет сообщение, если они совпадают. Предполагая, что приложение-запросчик на самом деле помещает сообщение, оно не может совпадать со старым, поскольку оно получает другую реакцию от приложения удаленного сервера. Сравните сообщения для одной и той же транзакции из старой и новой версий приложения. Распечатайте их в шестнадцатеричном виде и сравните байт для байта, если необходимо.
После проведения такого дифференциального диагноза можно было бы сузить фокус и найти причину. Список вещей, которые нужно проверить, если сообщение не создано, сильно отличается от списка вещей, чтобы проверить, действительно ли сообщение создано. Может быть возможно решить эту проблему без проведения базовой диагностики, но это будет исключением. Таким образом, мой ответ без ответа: начните с выполнения основной диагностики.
Вы конвертируете идентификатор сообщения из байтов в строку, а затем используете его в строке фильтра. Я предпочел бы использовать нижеприведенное, потому что MQ JMS уже выполняет необходимое преобразование байтов в строковое значение.
String filter = "JMSCorrelationID='" + txtMsg.getJMSMessageID() + "'";
Вы должны использовать ID:
префикс, смотрите также этот IBM Technote:
// Create IBM MQ specific correlation ID
public static String jmsCorrelId(String correlId) {
return "ID:" + javax.xml.bind.DatatypeConverter.printHexBinary(correlId.getBytes()).toLowerCase();
}
// Create IBM MQ specific JMS selector to receive message by correlation ID
public static String jmsCorrelIdSelector(String correlId) {
return "JMSCorrelationID='" + jmsCorrelId(correlId) + "'";
}
Используйте вышеупомянутые вспомогательные функции в вашем коде следующим образом:
String correlId = "MyCorrelId";
txtMsg.setJMSCorrelationID(correlId);
...
String filter = jmsCorrelIdSelector(correlId);
TextMessage respMsg = (TextMessage) jmsTemplate.receiveSelected(responseQ, filter);