IBM MQ 消费者应用程序无法使用文本消息(JMSCMQ1049: The character set '1208(UTF-8) Unmappable Action: REPORT)
Posted
技术标签:
【中文标题】IBM MQ 消费者应用程序无法使用文本消息(JMSCMQ1049: The character set \'1208(UTF-8) Unmappable Action: REPORT)【英文标题】:IBMMQ consumer application unable to consume TextMessage ( JMSCMQ1049: The character set '1208(UTF-8) Unmappable Action: REPORT)IBM MQ 消费者应用程序无法使用文本消息(JMSCMQ1049: The character set '1208(UTF-8) Unmappable Action: REPORT) 【发布时间】:2021-12-13 06:54:13 【问题描述】:我有一个消费者应用程序,它使用 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 [com.ApiErrorResponse@4be14d5e]
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 '[B@47412132'
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
的形式发送消息,那么我为什么首先会遇到这个问题?我对这一切有点困惑,希望得到一些指导。
编辑:
我已按照@MoragHughson 的要求运行amqsbcg
,以下是其中一条消息的详细信息:
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 应该可以正常工作?
【问题讨论】:
您尝试查看消息字节的直觉是好的。我建议您尝试针对您的队列运行 IBM 提供的浏览示例amqsbcg
之类的东西,以便您可以看到消息的所有十六进制字节。这将有助于调试问题,正如您所说的消息中的字符无效。要运行amqsbcg
,请将队列名称作为参数 1,将 QMgrName 作为参数 2。如果您需要作为客户端运行,可以使用 MQSERVER 环境变量。
尝试上述方法时提出一个问题。此队列是否有可能应用了消息级别的保护策略?即消息数据被加密?
@MoragHughson 非常感谢您的回复!我仍在运行amqsbcg
,但我在生产者代码中做了一些挖掘(它是用 C 编写的,不确定这是否会改变任何东西)。我查看了为此队列设置的队列属性,MQMD 对象设置为MQMD_DEFAULT
。但是在文档中,编码的默认值“取决于环境”。不确定这些信息是否有用,但我会在运行示例后立即与您联系。
@MoragHughson 我已将样本结果添加到我的帖子中。我还没有弄清楚消息是否被加密(我将不得不联系我的同事),但是,如果它确实被加密了,这将如何引起关注/解决方案是什么?
您的邮件似乎没有加密。如果是这样,并且您没有正确设置来解密它,那么您将获得各种奇怪的字符而不是您的数据。查看您的数据,它不仅仅是字符串数据,所以我想这就是问题所在。
【参考方案1】:
所以,你遇到了一个有趣的问题,而我以前也曾走这条路。
这与《老友记》中的 George Costanza 所说的相反:“是我而不是你”。在您的情况下,是发件人而不是您。
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 层将创建一个 TextMessage。 如果 MQMD 格式字段设置为“”(全为空白),则 MQ/JMS 层将创建一个 BytesMessage。(2) 由于传入消息的 MQMD 格式字段设置为“MQSTR”,JMS/MQ 层将尝试将其从 1208 的 CCSID 转换为 JVM 的 CCSID。问题来自您的消息中包含非字母数字数据这一事实。前 12 个字节中有很多二进制零。
你有两个选择:
(1) 要求发件人停止在邮件中包含非字母数字数据。
(2) 如果非字母数字数据很重要,则告诉发送方将消息的 MQMD 格式字段设置为“”(全为空白)。然后,当您收到消息时,只需将其转换为 BytesMessage。
很可能一些初级程序员从 *** 或其他地方复制代码并在不了解代码的作用的情况下使用它。
未来 MQ 开发人员/程序员注意事项:如果您的消息负载包含非字母数字数据,则 永远不要设置消息的 MQMD 格式字段到“MQSTR”。
【讨论】:
非常感谢,感谢@MoragHughson 帮助我找出罪魁祸首。如果不是你们这些好心人,我将无法弄清楚这个问题:)以上是关于IBM MQ 消费者应用程序无法使用文本消息(JMSCMQ1049: The character set '1208(UTF-8) Unmappable Action: REPORT)的主要内容,如果未能解决你的问题,请参考以下文章