【问题标题】:Issue While Setting MQRFH2 header in IBM MQ在 IBM MQ 中设置 MQRFH2 标头时出现问题
【发布时间】:2018-04-11 03:10:02
【问题描述】:

我正在尝试发送设置了 MD 和 RFH2 标头的 MQ 消息。 我需要消息在 AppWatch 上显示为这样。

但 RFH2 部分作为消息数据的一部分作为连续字符串出现。

我正在使用以下代码:

MQMessage msg = new MQMessage();
msg.writeString("Data to go as Message Content"); 

//Setting MQMD values
msg.persistence = MQConstants.MQPER_PERSISTANT;
msg.encoding = MQConstants.MQENC_S390;
msg.characterSet = 500;

//Setting RFH2 Values
MQRFH2 rfh2 = new MQRFH2();
rfh2.setEncoding(CMSQC.MQENC_NATIVE);
rfh2.setCodedCharSetId(CMSQC.MQCCSI_INHERIT);
rfh2.setFormat(CMSQC.MQFMT_STRING);
rfh2.setFlags(0);
rfh2.setNameValueCCSID(1208);
rfh2.setFieldValue("mcd","msd","jms_text");
rfh2.setNameValueData(<xml><usr><ENTRYNUM>123</ENTRYNUM><text>TEST123</text></usr></xml>);

//Setting the Header to the Message
rfh2.write(msg);

MQQueue queue = qmngr.accessQueue(qname,MQConstants.MQOO_OUTPUT);
queue.put(msg,pmo);
queue.close;

谁能帮我正确设置 RFH2 值。

注意:以上截图只是示例,代码与截图无关

【问题讨论】:

  • 你已经问过这个问题,罗杰已经回答了。根据他的回答和您尝试设置的值,我认为应该只是两次调用rfh2.setFieldValue,不需要rfh2.setNameValueData
  • rfh2.setFieldValue("usr", "ENTRYNUM", "123");
  • rfh2.setFieldValue("usr", "text", "TEST123");
  • 嗨@JoshMc 实际上在这里寻找正确的格式,如果您观察到代码,我使用的方式与该线程中建议的方式完全相同。 Buty 问题是,我无法像在屏幕截图中那样以正确的格式查看消息。这里有什么我想念的吗?

标签: java ibm-mq


【解决方案1】:

但是 RFH2 部分作为消息数据的一部分作为连续的 字符串。

是的,从技术上讲,MQRFH2 标头和文件夹是消息正文的一部分。

看来我在其他关于 MQRFH2 类的帖子中不够明确。做事的顺序很重要。

即如果你做 A 那么 B 你的信息将是 AB。如果你做 B 那么 A 你的信息将是 BA。 MQ 不会重新排序。

您是否查看过原始形式的 MQRFH2 消息?看这里:https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_9.0.0/com.ibm.mq.ref.dev.doc/q099250_.htm

有几种工具可以显示原始布局:amqsbcg、MQ Visual Edit、MO71 等...

从上面的代码中,你做的事情倒退了。您添加了消息有效负载,然后添加了 RFH2 标头和文件夹。这对 MQ 来说是垃圾。

正确的顺序应该是 MQRFH2 后跟消息负载。

MQMessage msg = new MQMessage();

//Setting RFH2 Values
MQRFH2 rfh2 = new MQRFH2();
rfh2.setEncoding(CMQC.MQENC_NATIVE);
rfh2.setCodedCharSetId(CMQC.MQCCSI_INHERIT);
rfh2.setFormat(CMQC.MQFMT_STRING);
rfh2.setFlags(0);
rfh2.setNameValueCCSID(1208);
rfh2.setFieldValue("usr", "ENTRYNUM", "123");
rfh2.setFieldValue("usr", "text", "TEST123");

//Setting the Header to the Message
rfh2.write(msg);

msg.writeString("Data to go as Message Content");

//Setting MQMD values
msg.persistence = CMQC.MQPER_PERSISTANT;
msg.format = CMQC.MQFMT_RF_HEADER_2;

MQQueue queue = qmngr.accessQueue(qname, CMQC.MQOO_FAIL_IF_QUIESCING + CMQC.MQOO_OUTPUT);
queue.put(msg,pmo);
queue.close;

2018 年 4 月 5 日更新。

Ok Faizan,通过你下面的 cmets,你仍然没有得到它。

我运行了一个示例 JMS MQ 程序并将以下消息数据放入队列中:“非常简单的测试。'ms' 中的时间是 -> 1522946795894”。

注意:我将 MQ 可视化编辑首选项从“将消息属性显示为命名属性”更改为“将消息属性显示为消息正文中的 MQRFH2 结构”。 (有关 MQGetMessageOptions 的更多信息,请参阅这篇文章的底部)。

MQ Visual Edit 的前 3 个屏幕截图向您展示了消息在队列中的外观(如您所见):

屏幕截图 #1 显示消息的 MQMD 格式为“MQHRF2”:

屏幕截图 #2 显示了 HEX 格式的消息负载:

屏幕截图 #3 显示了为 MQRFH2 正确格式化的消息:

如果我将 MQ Visual Edit 的首选项切换回“将消息属性显示为命名属性”,那么(这完全是相同的消息):

屏幕截图 #4 显示消息的 MQMD 格式为“MQSTR”(字符串):

屏幕截图 #5 显示了 HEX 格式的消息负载:

屏幕截图 #6 将消息负载显示为:

屏幕截图 #7 显示 MQRFH2 文件夹中的所有值现在都是命名属性:

注意:在这两种情况下,它是相同的消息,但不同之处在于您希望 RECEIVING 应用程序如何处理它。

MQGetMessageOptions 类有一个名为“options”的选项字段。您可以向该字段添加(或)MQGMO_PROPERTIES_IN_HANDLE 或 MQGMO_PROPERTIES_FORCE_MQRFH2 选项。现在,您似乎正在使用 MQGMO_PROPERTIES_FORCE_MQRFH2。更多信息请看这里:https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_9.0.0/com.ibm.mq.ref.dev.doc/q096780_.htm

【讨论】:

  • 嗨@Roger,感谢您的解决方案,我了解您解释排序的部分。我尝试了您给我的上述解决方案,但仍然面临问题,rfh2 标头不像屏幕截图中那样显示为单独的部分。 它仍然出现在消息数据部分但这次在消息内容之前
  • 以下是我尝试您提供的代码时在 AppWatch 中可见的消息数据的内容:。 RFH[x00][x00][x00][x02][x00][x00][x00]'[x00][x00][x02]"[x00][x00] [x01]μMQSTR[x00][ x00][x00][x00][x00][x04],[x00][x00][x00]8123TEST123数据到作为消息内容去
  • 叮,叮,叮——我们有一个赢家。给那个人一只泰迪熊!!这是一个格式正确的 MQRFH2 消息(又名 JMS 消息)。如果您仍然不明白,请阅读我上面提供的 IBM 链接。
  • 哈哈,这是个玩笑吗?哦...!!!这很有趣,我会给你那个,反正我是 MQ 的初学者,所以我可能无法理解你的解决方案,或者你没有得到我的查询。无论如何感谢您的兴趣。我宁愿等待有人向我解释为什么 RFH2 部分没有出现在屏幕截图中。
  • 其实是你不理解,做出了错误的假设。如果您阅读我给您的 IBM 链接,您就会明白。 MQRFH、MQRFH2、MQCIH、MQDEAD、MQIIH、MQXMIT 等消息在消息负载中都有 EMBEDDED 头结构。嵌入消息意味着消息有效负载将具有标头结构和应用程序的消息数据。这将完全扭曲您的想法:在消息负载中,您可以拥有 MQRFH2 和消息数据,然后是另一个 MQRFH2 和消息数据,另一个 MQRFH2 和消息数据。 ALL 在相同的消息负载中。
【解决方案2】:

通过稍微修改代码而不使用 MQRFH2 类,我能够查看屏幕截图中显示的消息。

我还必须考虑 Roger 在他的回答中建议的点,首先设置标头,然后设置消息负载。

参考:http://www.mqseries.net/phpBB2/viewtopic.php?t=35456

  String m_usr_data = "<usr><ENTRYNUM>123</ENTRYNUM><text>TEST123</text></usr>"
  MQMessage msg = new MQMessage();

  //Setting MQMD values
  msg.persistence = CMQC.MQPER_PERSISTANT;
  msg.format = CMQC.MQFMT_RF_HEADER_2;

  //Setting RFH2 Values
  msg.writeString(rfhStrucID);      //StrucID 
  msg.writeInt4(rfhVersion);        //Version 
  msg.writeInt4(rfhStrucLength );     //StrucLength 
  msg.writeInt4(CMQC.MQENC_NATIVE);       //Encoding 
  msg.writeInt4(CMQC.MQCCSI_INHERIT); //CodedCharSetID 
  msg.writeString(CMQC.MQFMT_STRING);       //Format 
  msg.writeInt4(0);          //Flags 
  msg.writeInt4(1208); //NameValueCCSID 
  msg.writeInt4(m_usr_data.getBytes().length);//NameValueLength <usr> 
  msg.writeString(m_usr_data);      //NameValueData <usr> 
  msg.write(rfhDataBytes);       //Actual MESSAGE data 

  msg.writeString("Data to go as Message Content");

  MQQueue queue = qmngr.accessQueue(qname, CMQC.MQOO_FAIL_IF_QUIESCING + CMQC.MQOO_OUTPUT);
  queue.put(msg,pmo);
  queue.close;

【讨论】:

  • 坏主意。真是个坏主意。我可以看到几个问题:(1) 缺少 'mcd' 文件夹,(2) 缺少 'jms' 文件夹,(3) 所有文件夹必须用空格填充并对齐到 4 字节边界。返回使用 MQRFH2 类,并确保按照我的示例将消息的 Format 字段设置为 CMQC.MQFMT_RF_HEADER_2。
  • 是的,你说得对,代码中缺少 2 个文件夹。感谢您指出我将在我的答案中更新代码。
  • 回到使用 MQRFH2 类的一部分,我不会这样做,因为即使它使用 rfh2 标头设置消息,我们有一个 JMS 应用程序抱怨他们的应用程序无法读取来自 rfh2 标头的任何数据,我的意思是它们在从 rfh2 读取数据时得到空值。一旦我修改了代码,他们就能够阅读它。
  • @Roger 除了你提到的那 3 件事,我错过了包括在我的代码中。为什么你建议我重新使用 MQRFH2 类?
  • 好的。我为您创建了一个完整的工作示例并将其发布到我的博客capitalware.com/rl_blog/?p=4823。因此,请阅读并使用 MQRFH2 类,而不是自行编写代码。
猜你喜欢
  • 2018-12-28
  • 1970-01-01
  • 1970-01-01
  • 2019-03-17
  • 1970-01-01
  • 2015-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多