IBM MQ读取XML消息报2110错误 无法转字符串渲染UI
问题背景
从IBM MQ拉取XML消息转字符串渲染到UI时,抛出异常:com.IBM.mq.MQException: MQJE001: Completion Code '1', Reason '2110'。
消息格式为MQSTR时可正常渲染,需调整代码兼容XML格式MQ消息的字符串读取。
原实现代码:
MQQueueManager _queueManager = null; int port = inputPort; String hostname = host; String channel = chanel; String qManager = queuemanager; String inputQName = queuename; MQEnvironment.hostname = hostname; MQEnvironment.channel = channel; MQEnvironment.port = port; _queueManager = new MQQueueManager(qManager); int openOptions = MQC.MQOO_INQUIRE + MQC.MQOO_FAIL_IF_QUIESCING + MQC.MQOO_BROWSE; MQQueue queue = _queueManager.accessQueue( inputQName, openOptions, null, // default q manager null, // no dynamic q name null ); // no alternate user id System.out.println("MQRead is now connected.\n"); int depth = queue.getCurrentDepth(); System.out.println("Current depth: " + depth + "\n"); if (depth == 0) { System.out.println("Depth is zero"); } MQGetMessageOptions getOptions = new MQGetMessageOptions(); getOptions.options = MQC.MQGMO_NO_WAIT + MQC.MQGMO_FAIL_IF_QUIESCING + MQC.MQGMO_CONVERT + MQC.MQGMO_BROWSE_NEXT; ArrayList<MessageDTO> myMessages = new ArrayList<>(); while(true) { MQMessage message = new MQMessage(); try { queue.get(message, getOptions); byte[] b = new byte[message.getMessageLength()]; message.readFully(b); System.out.println (new MQHeaderList (message, false)); String newMessage = new String(b); MessageDTO newMsg = new MessageDTO(); newMsg.setMessage(newMessage); Random rand = new Random(); newMsg.setMessageNumber(rand.nextInt()); myMessages.add(newMsg); model.addAttribute("myMessages", myMessages); System.out.println(myMessages); message.clearMessage(); } catch (IOException e) { System.out.println("IOException during GET: " + e.getMessage()); break; } catch (MQException e) { if (e.completionCode == 2 && e.reasonCode == MQException.MQRC_NO_MSG_AVAILABLE) { if (depth > 0) { System.out.println("All messages read."); } } else { System.out.println("GET Exception: " + e); } break; } catch (MQDataException e) { e.printStackTrace(); } } queue.close(); _queueManager.disconnect();
根因分析
- 2110错误码对应
MQRC_FORMAT_ERROR:代码中配置了MQC.MQGMO_CONVERT参数要求MQ客户端自动做消息格式转换,但XML消息的format字段不是内置的MQSTR字符串类型,MQ无对应转换规则直接抛出异常。 - 原有字节转字符串逻辑未指定字符集,遇到非默认编码的消息会出现乱码。
- 读取字节时用
message.getMessageLength()会把消息头长度算入,若消息带RFH2等格式头会把头部内容读入payload,导致XML解析失败。
修复步骤
- 移除消息获取参数中的
MQC.MQGMO_CONVERT,关闭MQ自动格式转换,直接读取原始字节。 - 读取内容时使用
getDataLength()获取纯payload长度,跳过消息头部分。 - 从消息属性中读取消息自带的CCSID(字符集标识),用对应编码将字节转为字符串,避免乱码。
调整后的核心读取逻辑
// 修改消息获取参数,移除MQC.MQGMO_CONVERT MQGetMessageOptions getOptions = new MQGetMessageOptions(); getOptions.options = MQC.MQGMO_NO_WAIT + MQC.MQGMO_FAIL_IF_QUIESCING + MQC.MQGMO_BROWSE_NEXT; // 消息读取逻辑替换 try { queue.get(message, getOptions); // 解析并跳过MQ消息头 new MQHeaderList(message, false); // 仅读取payload部分字节 byte[] b = new byte[message.getDataLength()]; message.readFully(b); // 按消息自带字符集转字符串 String msgCharset = CCSID.getCodepage(message.characterSet); String newMessage = new String(b, msgCharset); // 原有业务逻辑保持不变 MessageDTO newMsg = new MessageDTO(); newMsg.setMessage(newMessage); Random rand = new Random(); newMsg.setMessageNumber(rand.nextInt()); myMessages.add(newMsg); model.addAttribute("myMessages", myMessages); message.clearMessage(); } // 原有异常捕获、队列关闭逻辑无需修改
可选简化方案
如果确认消息发送方使用固定字符集(如UTF-8)写入XML内容,可直接指定字符集转换,无需动态读取CCSID:String newMessage = new String(b, StandardCharsets.UTF_8);
内容的提问来源于stack exchange,提问作者MaroBhunu
相关产品推荐
相关产品推荐

