java - 特殊字符问题:MQ 消息 PUT 错误:java.nio.charset.UnmappableCharacterException
问题描述
我有一个设置,其中有一个 JMS 生产者和 JMS 接收器。发件人应用程序发送如下消息:
source text ⟨е, ё, и, ю, я⟩ abcdefg
JMS 接收器在接收到消息后,使用纯 IBM MQ API 类将其放入 IBM MQ 队列。
在将此消息发送到 MQ 时,我收到以下异常:
INFO | 2020-09-17 09:45:19 | [main] mimq.MQReceiver (MQReceiver.java:211) - IO Exception Occurred: Input length = 1
java.nio.charset.UnmappableCharacterException: Input length = 1
at java.nio.charset.CoderResult.throwException(CoderResult.java:282)
at java.nio.charset.CharsetEncoder.encode(CharsetEncoder.java:816)
at com.ibm.mq.jmqi.system.JmqiCodepage.stringToBytes(JmqiCodepage.java:923)
at com.ibm.mq.MQMessage.writeString(MQMessage.java:2848)
at com.ibm.mimq.MQReceiver.sendToAnotherQueue(MQReceiver.java:192)
at com.ibm.mimq.MQReceiver.main(MQReceiver.java:113)
下面是我的MQ PUT代码:
public static void sendToLocalQueue(String msg) {
int port = 1414;
String host = "some-host";
String channel = "some-channel";
String manager = "some-QM";
String user = "user";
String passwd = "passwd";
String qname = "TEST";
String qmname = "some-QM";
MQQueueManager qMgr;
MQQueue inputQ;
try {
Hashtable<String, String> h = new Hashtable<String, String>();
h.put(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_CLIENT);
MQEnvironment.properties = h;
MQEnvironment.hostname = host;
MQEnvironment.port = port;
MQEnvironment.channel = channel;
MQEnvironment.userID = user;
MQEnvironment.password = passwd;
MQEnvironment.disableTracing();
MQException.log = null;
qMgr = new MQQueueManager(manager);
MQMessage m = new MQMessage();
m.applicationOriginData = "AMPS";
m.messageType = MQC.MQMT_DATAGRAM;
m.format = MQC.MQFMT_STRING;
m.encoding = MQC.MQENC_NATIVE;
m.priority = 4;
m.persistence = MQC.MQPER_PERSISTENT;
m.characterSet = MQC.MQCCSI_Q_MGR;
//m.characterSet = 1208;
m.expiry = MQC.MQEI_UNLIMITED;
m.writeString(msg);
MQPutMessageOptions putOptions = new MQPutMessageOptions();
putOptions.options = MQC.MQPMO_SYNCPOINT | MQC.MQPMO_FAIL_IF_QUIESCING;
logger.info("Putting message to LAN MQ (TEST queue)....");
qMgr.put(qname, qmname, m, putOptions);
qMgr.commit();
} catch(MQException me) {
logger.info("Error Code : " +me.getErrorCode());
logger.info("LocalizedMessage : " +me.getLocalizedMessage());
logger.info("Message : " +me.getMessage());
logger.info("Reason : " +me.getReason());
me.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
logger.info("IO Exception Occurred : " +e.getLocalizedMessage());
e.printStackTrace();
}
}
由于不可映射字符,无法将消息放入队列。编码在队列管理器级别设置为 UTF-8。
但是,当我替换以下行时: m.characterSet = MQC.MQCCSI_Q_MGR;
有了这条线: m.characterSet = 1208;
问题不再存在。
我的问题是为什么这种转换没有在 MQ 级别完成。我需要检查哪些设置以确保正确转换。我尝试了以下技术,但不起作用:
Setting java parameter as : -Dfile.encoding=UTF-8
我的环境:
Server : Linux
MQ : 9.0 or 7.5
Java : 1.8
还要提到一件事,相同的设置适用于 7.5,但在迁移后不适用于 MQ 9.0。我知道通过上面的一行代码更改,我可以传递消息。但是如果我错过了一些配置,我想了解 MQ 级别。任何建议将不胜感激。
谢谢你。
更新
我将消息发送到 MQ 的客户端计算机具有 CCSID :MQMD.CodedCharSetId = 1208
我连接和发送消息的 MQ 服务器有这个:
getDefaultProperty(Object) returns [819(0x333)] Integer
setCCSID(int) setter [819(0x333)]
因此,当我在代码中明确设置 1208 时,它正在工作。如果不是,则转换失败。
更新-2
MQC.MQCCSI_Q_MGR is Zero
我在罐子里看到的价值。因此代码是这样设计的,如果值为零,它将从设置为819的 Jar 中获取默认值。我在打开 MQ 跟踪时了解到这一点。代码是这样的:
getDefaultProperty(Object) returns [819(0x333)] Integer
setCCSID(int) setter [819(0x333)]
此代码存在于 jar 中。所以我们需要在消息上显式设置字符集值。在我的情况下,它是 1208。
解决方案
当本地连接到队列管理器(即使用TRANSPORT_MQSERIES_BINDINGS
)时,代码:-
m.characterSet = MQC.MQCCSI_Q_MGR;
表示“采用队列管理器属性 CCSID 中设置的 CCSID”。您可以使用以下 MQSC 命令查看此属性:-
DISPLAY QMGR CCSID
当作为客户端连接时(如您的代码所示),则代码:-
m.characterSet = MQC.MQCCSI_Q_MGR;
表示“从客户端机器语言环境中查找 CCSID”。
IBM 知识中心指出:-
对于客户端应用程序,
MQCCSI_Q_MGR
根据客户端的语言环境而不是队列管理器上的语言环境来填写。
如果更改代码行以将消息 CCSID 显式设置为 1208 可以解决问题,那么您的客户端计算机区域设置似乎未设置为 UTF-8。
您可以通过浏览队列上的消息(不转换它)并查看MQMD.CodedCharSetId
字段中的内容来查看客户端设置的内容。
推荐阅读
- javascript - 如何在 Vue.js 中过滤数组和循环 V-for
- r - `rows_update` 错误:`x` 键值不唯一
- git - 使用两个不同的分支并将它们合并?
- javascript - 每当我在 react 中保存 app.js 文件时,总是会出现错误并且出现意外令牌
- css - R闪亮的滚动侧边栏/溢出
- linux - 切换用户文件权限
- machine-learning - sklearn:SVR 无法泛化加法器功能
- node.js - 使用 Google Drive API 查看文件夹内容需要什么权限
- c++ - 如何从 C++ 的循环中追加字符串?
- python - 如何绘制带有图例的非结构化 numpy 数组?