I have a setup where there is a JMS Producer and JMS receiver. The sender application sends a message like :
source text ⟨е, ё, и, ю, я⟩ abcdefg
JMS receiver after receiving the message, puts it to a IBM MQ queue using pure IBM MQ API classes.
While putting this message to MQ I am getting the below exception:
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)
Below is my MQ PUT code :
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();
}
}
It is unable to put the message to the queue due to Unmappable character. The encoding is set to UTF-8 at Queue Manager level.
However when I replace the below line : m.characterSet = MQC.MQCCSI_Q_MGR;
With the line : m.characterSet = 1208; The issue is no more there.
My question is why this conversion is not getting done at MQ level. What are settings I need to check to ensure the correct conversion. I have tried the below techniques, but not working :
Setting java parameter as : -Dfile.encoding=UTF-8
My environment :
Server : Linux
MQ : 9.0 or 7.5
Java : 1.8
One more thing to mention, the same setup was working with 7.5 but not working with MQ 9.0 after migration. I know with my above one line code change I can pass the message. But I want to understand in MQ level, if I am missing out some configurations. Any advise would be much appreciated.
Thank You.
UPDATE
The Client Machine from where I am sending the Message over to MQ has CCSID : MQMD.CodedCharSetId = 1208
The MQ server where I am connecting and sending the message has this :
getDefaultProperty(Object) returns [819(0x333)] Integer
setCCSID(int) setter [819(0x333)]
So when I am setting 1208 explicitely in my code it is working. When not the conversion is failing.
UPDATE-2
The value MQC.MQCCSI_Q_MGR is Zero as I saw in the jar. Hence the code is designed like this, if the value is Zero, it will fetch the default value from the Jar which is set to 819. I learnt this when I turned on the MQ tracing. And the code is like this :
getDefaultProperty(Object) returns [819(0x333)] Integer
setCCSID(int) setter [819(0x333)]
This code is present inside the jar. So we need to explicitly set the charset value on the message. In my case it is 1208.