There are preferred MQI functions for dealing with message properties. But sometimes you may have requirements for converting between MQRFH2 and properties. This post came out of a question posed by a developer on another IBM product. Oddly, it was the same product (though a different person) that prompted a previous Snippet. And I was able to use the same basic framework from that test to demonstrate how simple it can be.
The request
“Our product receives an MQ message, does some processing on it and then passes the message to user-written functions. We would like to be able to work with message properties on the inbound message for simplicity, but pass the message onwards using MQRFH2 for compatiblity.
Summary of what was asked
This is not a case of passing messages via a queue to the next processor. The user-written code is called “inline” a bit like an exit. So the format of what gets handed on is important.
The solution
There are two little-known MQI verbs that can help here. They are MQBUFMH and MQMHBUF. These convert between message handles, for direct access to properties, and the flattened MQRFH2 structure that an application may expect or need to parse.
The original specification material for message properties said:
MQBUFMH and MQMHBUF are the least likely calls to be used by customers, but are provided for advanced users, especially vendors.
Internal document
The word “vendor” here primarily referred to people writing API Exits. And indeed, that’s where I’ve seen most use of these verbs. The exit cannot control what the application is doing, and may need to work with either format for manipulating properties. It’s much easier to add a new property using MQSETMP
than shuffling bytes in the RFH2 format. But it turns out that these verbs also solve the problem asked here.
What I recommended here was to do the MQGET without a message handle, and then convert the message to a properties format with MQBUFMH
. That allows us to work directly with properties and still pass the RFH2 onwards for compatibility.
As a quick demonstration, I modified amqsbcg0.c:
else if (PropOption == PROPS_IN_MQRFH2) { MQBMHO BufMsgHOpts = {MQBMHO_DEFAULT}; MQLONG DataLength2; BufMsgHOpts.Options = MQBMHO_NONE; /* Don't STRIP properties from the RFH2 */ MQBUFMH(Hconn, Hmsg, &BufMsgHOpts, pmdin, BufferLength, Buffer, &DataLength2, &CompCode, &Reason); if (CompCode == MQCC_OK) { printProperties(Hconn, Hmsg); } DataLength -= (BufferLength - DataLength2); }
The default MQBMHO
strips the RFH2 from the input buffer so it is no longer available and the message body is moved down to offset 0 in the buffer. So use NONE as the processing option instead. That way, we can pass on exactly what was originally received. The DataLength values will be adjusted if we decided to do the stripping, but it’s not really needed here.
Exploring beyond …
While I was checking that this all worked, I did do a couple of other experiments. One was to add the opposite processing to amqsbcg0.c using MQMHBUF
. Just to show it working. The program gets the message with properties, and then I converted them to an RFH2 buffer:
if (PropOption == PROPS_IN_MSG_HANDLE) { printProperties(Hconn, Hmsg); { MQCHARV Name = {MQPROP_INQUIRE_ALL}; /* browse all properties */ MQMHBO MsgHBufOpts = { MQMHBO_DEFAULT}; MQLONG DataLength2; memset(PropsBuffer,0,BufferLength); MQMHBUF(Hconn, Hmsg, &MsgHBufOpts, &Name, pmdin, BufferLength, PropsBuffer, &DataLength2, &CompCode, &Reason); hexDump(PropsBuffer,BufferLength,DataLength2); } }
With the output looking like this:
00000000: 52464820 02000000 F8000000 22020000 'RFH ........"...' 00000010: FEFFFFFF 20202020 20202020 00000000 '.... ....' 00000020: B8040000 60000000 3C757372 3E3C636F '....`...<usr><co' 00000030: 6C6F7572 3E677265 656E3C2F 636F6C6F 'lour>green</colo' 00000040: 75723E3C 73697A65 3E6C6172 67653C2F 'ur><size>large</' 00000050: 73697A65 3E3C6861 6E646C65 50726F70 'size><handleProp' ...
One interesting thing there is the empty Format
field in the structure, as there is not really any association with a message body now.
And I also mashed together the rfh2put.c program with the amqsstm.c sample, so that I could try putting a message with both an RFH2 and explicit properties. My interest there was if there was any ordering or precedence happening. The result was that the handle-based properties appeared to take precedence, if both the RFH2 and the handle were trying to set the same property. Probably not something that can be relied on, but at least the test did something reasonable.
As I expected, enumerating the properties using MQINQMP
didn’t seem to have any particular order (like alphabetic). But all the properties did appear.
Summary
There is a lot of flexibility with message properties. Hopefully this has shone some light on one of the more obscure features for developers.
One thought on “Snippet 3 – Converting between MQRFH2 and properties”