Приложение-потребитель IBMMQ не может использовать TextMessage (JMSCMQ1049: набор символов '1208 (UTF-8) Unmappable Action: REPORT)

0

У меня есть потребительское приложение, которое использует IBMMQ для получения сообщений от администратора очередей. Я не контролирую издателя, только потребителя. Вот часть кода для моего потребителя:

while(true) {
    message = (TextMessage) queueReceiver.receive(200);
                
    if (message != null) {
             messageFile = messageTypeToListenerMapping.get(type).generateMessageNameAndWriteToDisk(message.getText(), source, saveDirectory);
    } else {
             break;
    }      

Этот код отлично работает и может получать сообщение как TextMessageобъект почти для всех моих очередей, кроме одной. Когда приложение пытается получить сообщение из этой очереди, я получаю эту ошибку:

2021-10-05 22:12:31.831 DEBUG 30050 --- [nio-8181-exec-8] o.s.web.servlet.DispatcherServlet        : GET "/retrieveAllMessagesFromQueue", parameters={}
2021-10-05 22:12:31.832 DEBUG 30050 --- [nio-8181-exec-8] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to public java.util.Map<java.lang.String, java.util.Map<java.lang.String, java.util.Map<java.lang.String, java.lang.Integer>>>  ,
2021-10-05 22:12:36.882 DEBUG 30050 --- [nio-8181-exec-8] .m.m.a.ExceptionHandlerExceptionResolver : Using @ExceptionHandler public Exception.ApiErrorResponse Octopus.controller.OctopusRestController.handleJmsException(javax.jms.JMSException)
2021-10-05 22:12:36.899 DEBUG 30050 --- [nio-8181-exec-8] m.m.a.RequestResponseBodyMethodProcessor : Using 'application/json', given [*/*] and supported [application/json, application/*+json, application/json, application/*+json]
2021-10-05 22:12:36.899 DEBUG 30050 --- [nio-8181-exec-8] m.m.a.RequestResponseBodyMethodProcessor : Writing [[email protected]]
2021-10-05 22:12:36.900 DEBUG 30050 --- [nio-8181-exec-8] .m.m.a.ExceptionHandlerExceptionResolver : Resolved [com.ibm.msg.client.jms.DetailedJMSException: JMSCMQ1049: The character set '1208(UTF-8) Unmappable Action: REPORT, Unmappable Replacement: 63, spaceByte: 32' cannot convert some or all of the string '[[email protected]'
An attempt was made to send or receive string data using a character set not capable of translating the strings content.
Only encode a message using a character set known to be appropriate for the string data being transmitted.]
2021-10-05 22:12:36.901 DEBUG 30050 --- [nio-8181-exec-8] o.s.web.servlet.DispatcherServlet        : Completed 500 INTERNAL_SERVER_ERROR

После некоторой отладки я обнаружил, что ошибка возникает при выполнении этого кода: message.getText()

Я считаю, что, возможно, сообщение, помещаемое издателем в очередь, содержит какие-то специальные символы, которые приложение не может обработать. Поэтому я попытался посмотреть, смогу ли я использовать сообщение для этой конкретной очереди, используя BytesMessageвместо этого. Вот код ниже:

BytesMessage byteMessage;

byteMessage = (BytesMessage) queueReceiver.receive(200);
int TEXT_LENGTH = new Long(byteMessage.getBodyLength()).intValue();
byte[] text_bytes = new byte[TEXT_LENGTH];
byteMessage.readBytes(text_bytes, TEXT_LENGTH);
String codePage = byteMessage.getStringProperty(WMQConstants.JMS_IBM_CHARACTER_SET);
String textString = new String(text_bytes, codePage);

     if (textString != null) {
              messageFile = messageTypeToListenerMapping.get(type).generateMessageNameAndWriteToDisk(textString, source, saveDirectory)
     } else {
              break;
     }

Однако я сталкиваюсь с этой ошибкой:

2021-10-27 22:29:34.046 DEBUG 20987 --- [nio-8181-exec-1] o.s.web.servlet.DispatcherServlet        : Failed to complete request: java.lang.ClassCastException: com.ibm.jms.JMSTextMessage cannot be cast to javax.jms.BytesMessage
2021-10-27 22:29:34.053 ERROR 20987 --- [nio-8181-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.ClassCastException: com.ibm.jms.JMSTextMessage cannot be cast to javax.jms.BytesMessage] with root cause
java.lang.ClassCastException: com.ibm.jms.JMSTextMessage cannot be cast to javax.jms.BytesMessage

Насколько я понимаю, сообщение не может быть преобразовано из TextMessageв ByteMessage, что также означает, что издатель отправил сообщение как TextMessage. Если издатель отправил сообщение как TextMessage, то почему я вообще сталкиваюсь с этой проблемой? Я немного смущен всем этим и был бы признателен за некоторые рекомендации.


РЕДАКТИРОВАТЬ: Я amqsbcgвыполнил запрос @MoragHughson, и вот подробности одного из сообщений:

 MQGET of message number 14861, CompCode:0 Reason:0
****Message descriptor****

  StrucId  : 'MD  '  Version : 2
  Report   : 0  MsgType : 8
  Expiry   : -1  Feedback : 0
  Encoding : 546  CodedCharSetId : 1208
  Format : 'MQSTR   '
  Priority : 0  Persistence : 1
  MsgId : X'414D5120514D2E44303014D5120514D2E443030A0EF121'
  CorrelId : X'000000000000000000000000000000000000000000000000'
  BackoutCount : 0
  ReplyToQ       : '                                                '
  ReplyToQMgr    : 'QM.1010101_4642                                 '
  ** Identity Context
  UserIdentifier : 'user2      '
  AccountingToken :
   X'0A31303030303639333331639333331639333331004568490000000000000006'
  ApplIdentityData : '                                '
  ** Origin Context
  PutApplType    : '6'
  PutApplName    : 'mqm_sender             '
  PutDate  : '00000000'    PutTime  : '00000000'
  ApplOriginData : '    '

  GroupId : X'000000000000000000000000000000000000000000000000'
  MsgSeqNumber   : '1'
  Offset         : '0'
  MsgFlags       : '0'
  OriginalLength : '-1'

****   Message      ****

 length - 64 of 64 bytes

00000000:  0000 0000 B3DC B059 6400 0000 524D 5320           '.....ܰYd...RMS '
00000010:  2052 3235 3139 3435 3734 3437 3030 3030           ' R25194574470000'
00000020:  3120 2020 2020 2020 2020 2020 2020 2032           '1              2'
00000030:  3032 3131 3032 3231 3431 3333 3730 3020           '021102214133700 '



 No more messages
 MQCLOSE


Похоже, что CodedCharSetId - 1208, что похоже на UTF-8. Если это так, тогда TextMessages должны работать нормально, если я не ошибаюсь?

8
  • Ваш инстинкт - попытаться просто увидеть байты сообщения - хороший. Я предлагаю вам попробовать запустить что-то вроде предоставленного IBM образца обзора для amqsbcgвашей очереди, чтобы вы могли видеть все шестнадцатеричные байты сообщения. Это поможет отладить проблему, вероятно, как вы говорите с недопустимым символом в сообщении. Для запуска amqsbcgукажите имя очереди в качестве параметра 1 и QMgrName в качестве параметра 2. Если вам нужно работать как клиент, можно использовать переменную среды MQSERVER. 2 дня назад
  • Один вопрос, пока вы пробуете все вышесказанное. Есть ли вероятность, что к этой очереди применена политика защиты на уровне сообщений? т.е. данные сообщения зашифрованы? 2 дня назад
  • @MoragHughson Большое спасибо за ваш ответ! Я все еще в процессе запуска, amqsbcgно я немного покопался в коде производителя (который написан на C, не уверен, что это что-то меняет). Я посмотрел на свойства очереди, которые были установлены для этой очереди, и объект MQMD был установлен на MQMD_DEFAULT. Однако в документации значение по умолчанию для кодировки «зависит от среды». Не уверен, что эта информация полезна, но я свяжусь с вами, как только запущу образец. 2 дня назад
  • @MoragHughson Я добавил результаты сэмпла в свой пост. Мне еще предстоит выяснить, зашифровано ли сообщение (мне нужно будет связаться с моим коллегой), однако, если оно действительно зашифровано, как это может вызвать беспокойство / каково будет решение для этого? вчера
  • Ваше сообщение не зашифровано. Если бы это было так, и вы не были правильно настроены для его расшифровки, вместо ваших данных вы бы получили всевозможные странные символы. Глядя на ваши данные, это не только строковые данные, поэтому я думаю, что это проблема. вчера
1

Итак, у вас есть интересная проблема, и я уже проходил этот путь раньше.

Это противоположно тому, что сказал бы Джордж Костанза из «Друзья»: «Это я, а не ты». В вашем случае это отправитель, а не вы.

Из дампа amqsbcg можно выделить 3 важных элемента:

Encoding : 546  CodedCharSetId : 1208
Format : 'MQSTR   '
00000000:  0000 0000 B3DC B059 6400 0000 524D 5320           '.....?Yd...RMS '

(1) Это сообщение не является сообщением JMS (также известным как MQRFH2), но уровень JMS / MQ превратит его в сообщение JMS для приложения.

  • Если в поле «Формат MQMD» установлено значение «MQSTR», то слой MQ / JMS создаст текстовое сообщение.
  • Если в поле MQMD Format установлено значение «» (все пусто), то уровень MQ / JMS создаст BytesMessage.

(2) Поскольку для поля формата MQMD входящего сообщения установлено значение «MQSTR», уровень JMS / MQ попытается преобразовать его из CCSID 1208 в CCSID вашей JVM. Проблема возникает из-за того, что в вашем сообщении используются не буквенно-цифровые данные. Много двоичных нулей в первых 12 байтах.

У вас есть 2 варианта:

(1) Попросите отправителя прекратить включать в сообщение не буквенно-цифровые данные.

(2) Если важны не буквенно-цифровые данные, попросите отправителя установить в поле формата MQMD сообщения значение «» (все пусто). Затем, когда вы получаете сообщение, вы просто передаете его как BytesMessage.

Скорее всего, какой-то младший программист скопировал код из StackOverflow или где-то еще и использовал его, не понимая, что делает код.

Примечание для будущих разработчиков / программистов MQ: если полезная нагрузка вашего сообщения содержит не буквенно-цифровые данные, никогда не устанавливайте в поле MQMD Format сообщения значение «MQSTR».

1
  • 1
    Большое вам спасибо, и спасибо @MoragHughson за помощь в выяснении виновника. Я бы не смог разобраться, если бы не вы, добрые люди :) вчера