基于JMS收发SWIFT FileAct消息的格式问题求助
问题根源
你当前的错误在于把RFH2头的字节直接写入了BytesMessage的消息体中,导致头和payload合并成连续字节流,接收时无法区分。RFH2是IBM MQ的消息头结构,不属于消息体内容,应该通过MQ API正确设置为消息的头部属性,而非消息体的一部分。
解决方案步骤
1. 修正发送端代码:正确设置RFH2头
使用IBM MQ JMS的扩展类MQBytesMessage访问底层MQMessage,将RFH2作为消息头附加,而非写入消息体:
public void sendSwiftFileActMessage(JmsConnectionFactory connectionFactory, Destination destination) throws Exception { String ifCobaString = "IF_COBA"; String filename = "/opt/mq/TC.SB13.0015484631.zip"; // 构建RFH2头 MQRFH2 mqrfh2 = new MQRFH2(); mqrfh2.setEncoding(CMQC.MQENC_NATIVE); mqrfh2.setCodedCharSetId(CMQC.MQCCSI_INHERIT); mqrfh2.setFormat(CMQC.MQFMT_NONE); mqrfh2.setFlags(0); mqrfh2.setNameValueCCSID(1208); // 设置SWIFT FileAct相关字段 mqrfh2.setFieldValue(ifCobaString, "OriginatorApplication", "data"); mqrfh2.setFieldValue(ifCobaString, "Requestor", "ou=data,o=data,o=swift"); mqrfh2.setFieldValue(ifCobaString, "Responder", "ou=data,o=data,o=swift"); mqrfh2.setFieldValue(ifCobaString, "Service", "swift.data"); mqrfh2.setFieldValue(ifCobaString, "RequestType", "data"); mqrfh2.setFieldValue(ifCobaString, "Compression", "Zip"); mqrfh2.setFieldValue(ifCobaString, "FileName", "data.zip"); mqrfh2.setFieldValue(ifCobaString, "FileReference", "data.zip"); // 创建JMS上下文和消息 try (JMSContext producerContext = connectionFactory.createContext(); FileInputStream inStream = new FileInputStream(filename)) { MQBytesMessage bytesMessage = (MQBytesMessage) producerContext.createBytesMessage(); MQMessage mqMessage = bytesMessage.getMQMessage(); // 将RFH2头附加到MQMessage mqrfh2.write(mqMessage); // 写入payload/附件到消息体 byte[] buf = new byte[4096]; int bytesRead; while ((bytesRead = inStream.read(buf)) != -1) { bytesMessage.writeBytes(buf, 0, bytesRead); } // 设置消息格式为RFH2,告知MQ这是带扩展头的消息 mqMessage.format = CMQC.MQFMT_RFH2; // 发送消息 producerContext.createProducer().send(destination, bytesMessage); } }
2. 修正接收端代码:解析RFH2头并提取payload
接收时先解析RFH2头,再读取剩余消息体作为payload/附件:
// 处理接收到的消息 if (message instanceof MQBytesMessage) { System.out.println("-- reading MQ BYTE-message with RFH2 header.."); MQBytesMessage bytesMessage = (MQBytesMessage) message; MQMessage mqMessage = bytesMessage.getMQMessage(); try { // 解析RFH2头,读取后指针自动定位到消息体起始处 MQRFH2 mqrfh2 = new MQRFH2(); mqrfh2.read(mqMessage); // 验证RFH2字段 System.out.println("OriginatorApplication: " + mqrfh2.getFieldValue("IF_COBA", "OriginatorApplication")); System.out.println("FileName: " + mqrfh2.getFieldValue("IF_COBA", "FileName")); // 读取消息体内容 long bodyLength = mqMessage.getMessageLength() - mqMessage.getPosition(); byte[] payloadBytes = new byte[(int) bodyLength]; mqMessage.readFully(payloadBytes); // 保存附件文件 try (FileOutputStream fos = new FileOutputStream("/opt/mq/WRITE.zip")) { fos.write(payloadBytes); } System.out.println("Successfully extracted RFH2 header and saved payload as file."); } catch (Exception e) { e.printStackTrace(); } } else if (message instanceof TextMessage) { // 原有TextMessage处理逻辑 System.out.println("-- reading TEXT-message.."); TextMessage textMessage = (TextMessage) message; try { System.out.println("-- MyMessageListener received message with payload: " + textMessage.getText()); } catch (JMSException jmse) { System.out.println("JMS Exception in MyMessageListener class (TextMessage)!"); System.out.println(jmse.getLinkedException()); } }
关键说明
- RFH2的正确位置:RFH2是MQ的扩展消息头,必须通过
MQRFH2.write(mqMessage)附加到头部区域,而非写入消息体。读写后消息指针会自动跳转到消息体起始位置。 - 消息格式标识:发送时必须设置
mqMessage.format = CMQC.MQFMT_RFH2,确保MQ和接收端识别带RFH2头的消息。 - 类型转换:需将JMS标准
BytesMessage转为IBM MQ扩展的MQBytesMessage,才能访问底层MQMessage进行头操作。
内容的提问来源于stack exchange,提问作者the_villian
相关产品推荐
相关产品推荐

