How to process WebSphere MQ message headers
WebSphere MQ messages can optionally include additional headers, or alternative headers, to the MQRFH2 header, which contains JMS properties. WebSphere Application Server application programs can use the com.ibm.mq.headers classes to access headers in messages from WebSphere MQ and to construct headers in messages to WebSphere MQ.
WebSphere MQ message headers
WebSphere MQ messages always include a message descriptor (MQMD). They can also include headers containing additional information about the messages; for example, messages to or from JMS applications usually include an MQRFH2 header containing message properties. WebSphere MQ defines the format and usage of some headers (for example, MQRFH2) and also allows users and third-party software providers to define their own custom headers.
Typically it is not necessary for application programs to process WebSphere MQ message headers. Most WebSphere MQ applications either do not use headers at all, or only use the MQRFH2 header, and the service integration and WebSphere MQ messaging providers automatically process the MQRFH2 header when we are communicating with these applications. However, if you are communicating with a WebSphere MQ application that uses or creates additional or different headers, then the WAS application can use the com.ibm.mq.headers classes to create the headers in messages it sends, and process them in messages it receives.
In the WebSphere MQ message, the headers (if there are headers) are at the start of the message, before the message payload. Each header contains fields that describe the following header, or the payload if there are no more headers; the MQMD contains the fields that describe the first header, or the payload if there are no headers. The MQMD and the MQRFH2 header do not normally appear in a JMS message. When the messaging provider converts a WebSphere MQ message into a JMS message, it uses information from the MQMD and MQRFH2 header to set JMS header fields and properties. Similarly, when the messaging provider converts a JMS message into a WebSphere MQ message, it uses the JMS header fields and properties to construct the MQMD and MQRFH2 header.
The JMS provider handles other headers in WebSphere MQ messages by converting the WebSphere MQ message to or from a JMS BytesMessage; the headers appear at the start of the message body, followed by the WebSphere MQ message payload (if any). The JMS_IBM_Format property of the JMS message indicates the format of the data in the message body (in this case, first header) and the JMS_IBM_Encoding and JMS_IBM_Character_Set properties indicate its encoding and CCSID.
Processing WebSphere MQ message headers in a JMS BytesMessage
The com.ibm.mq.headers package contains classes and interfaces that we can use to parse and manipulate WebSphere MQ headers in the body of a JMS BytesMessage. The MQHeader interface provides general-purpose methods for accessing header fields and for reading and writing message content. Each header type has its own class that implements the MQHeader interface and adds getter and setter methods for individual fields. For example, the MQCIH class represents the MQCIH (CICS Bridge) header type. The header classes perform any necessary data conversion automatically, and can read or write data in any specified numeric encoding or character set (CCSID).
Two helper classes, MQHeaderIterator and MQHeaderList, assist with reading and decoding (parsing) the header content in messages:
- MQHeaderIterator works like a java.util.Iterator. For as long as there are more headers in the message, the next() method returns true, and the nextHeader() or next() method returns the next header object.
- MQHeaderList works like a java.util.List. Like MQHeaderIterator, it parses header content, but it also allows us to search for particular headers, add new headers, remove existing headers, update header fields, and then write the header content back to a message. Alternatively, we can create an empty MQHeaderList, then populate it with header instances and write it to a message once or repeatedly.
Every header class implements the MQHeader interface, which provides the methods int read (java.io.DataInput message, int encoding, int characterSet) and int write (java.io.DataOutput message, int encoding, int characterSet). The java.io.DataInputStream and java.io.DataOutputStream classes implement DataInput and DataOutput respectively. We can obtain DataInput and DataOutput objects from byte arrays carried in JMS messages, as in the following example, which processes a single MQCIH header:
import java.io.*; import javax.jms.*; import com.ibm.mq.headers.*; ... BytesMessage bytesMessage = (BytesMessage) msg; // Message received from JMS consumer byte[] bytes = new byte [(int) bytesMessage.getBodyLength ()]; bytesMessage.readBytes (bytes); DataInput in = new DataInputStream (new ByteArrayInputStream (bytes)); MQCIH cih = new MQCIH (in, bytesMessage.getIntProperty("JMS_IBM_Encoding"), 819);Alternatively, we can use the MQHeaderIterator class to process a sequence of headers, replacing the line starting MQCIH cih = new MQCIH with:
MQHeaderIterator it = new MQHeaderIterator (in, bytesMessage.getStringProperty("JMS_IBM_Format"), bytesMessage.getIntProperty("JMS_IBM_Encoding"), 819); while (it.hasNext()) { MQHeader item = (MQHeader) it.next(); ... }This example creates a single header (an MQCIH type header) and adds it into a BytesMessage:
import java.io.*; import javax.jms.*; import com.ibm.mq.constants.CMQC; import com.ibm.mq.headers.*; ... MQCIH header = new MQCIH(); ByteArrayOutputStream out = new ByteArrayOutputStream (); header.write (new DataOutputStream (out), CMQC.MQENC_NATIVE, 819); byte[] bytes = out.toByteArray (); BytesMessage newMsg = origSes.createBytesMessage(); newMsg.writeBytes(bytes);This example uses the MQHeaderList class to add two headers into a BytesMessage:
import java.io.*; import javax.jms.*; import com.ibm.mq.constants.CMQC; import com.ibm.mq.headers.*; ... byte[] outheaders = null; byte[] outbody = ... try { MQHeaderList it = new MQHeaderList (); MQHeader header1 = ... // Could be any header type MQHeader header2 = ... // Could be any header type ByteArrayOutputStream out = new ByteArrayOutputStream (); DataOutput dout = new DataOutputStream(out); it.add(header1); it.add(header2); it.write(dout); outheaders = out.toByteArray(); } catch (Exception e) { System.out.println("error generating MQ message headers : " + e); } BytesMessage newMsg = origSes.createBytesMessage(); newMsg.writeBytes(outheaders); newMsg.writeBytes(bytes); newMsg.setStringProperty("JMS_IBM_Format", "MQCICS"); newMsg.setIntProperty("JMS_IBM_Encoding", CMQC.MQENC_NATIVE); newMsg.setIntProperty("JMS_IBM_Character_Set", 819);Always use the correct values for the encoding and characterSet arguments. When you read headers, specify the encoding and CCSID with which the byte content was originally written. When writing headers, specify the encoding and CCSID to produce. The data conversion is performed automatically by the header classes.
More information about the com.ibm.mq.headers classes
The com.ibm.mq.headers package is part of the WebSphere MQ Resource Adapter, which is installed automatically in WebSphere Application Server. This package comprises a set of classes and interfaces that allow the Java programmer to work with WebSphere MQ Message Headers. These include the MQHeaderIterator and MQHeaderList classes mentioned in this topic, and classes for some commonly used WebSphere MQ Message Headers, including:
- MQCIH - CICS bridge header
- MQIIH - IMS™ information header
- MQSAPH - SAP header
We can also define classes representing our own headers.
Related
Mapping the message body to and from WebSphere MQ format
Related information:
Handling WebSphere MQ message headers Package com.ibm.mq.headers