IBM BPM, V8.0.1, All platforms > Programming IBM BPM > Enterprise Service Bus programming > WebSphere MQ binding > Access the WebSphere MQ header

Use Java to access the WebSphere MQ header

When an import or export, with a WebSphere MQ binding receives a Websphere MQ message, the headers are parsed and made available in the context service. Consequently the headers are available for authors of custom function selectors, data handlers and mediation components.

For outbound messages, the WebSphere MQ binding automatically adds an MQ Message Descriptor (MQMD) to all messages. You cannot modify the MQMD. If the message already contains an MQMD, then it is used, and a new one is not created. If you create an MQMD before the message reaches the WebSphere MQ binding, you are can control the content of the header. The WebSphere MQ binding provides an API that you use to add an MQMD and custom header to a message. You can use this API in a custom mediation, to modify the SMO to include the WebSphere MQ headers.

In a SCA module, WebSphere MQ message headers are stored in the MQHeader SMO structure, shown in Figure 1. The top-level type MQHeaderType is a SMO element. You create it using the ServiceMessageObjectFactory. This type contains a single MQMD, an MQControl type, and an MQChainedHeaderType. The MQMD and MQControl are WebSphere MQ structure types. You must create them using the WMQStructuresFactory:

Figure 1. MQHeader SMO structure


Parsing a WebSphere MQ header using a custom header data binding

WebSphere ESB provides data bindings that enable various WebSphere MQ headers to be parsed. Some native WebSphere MQ applications use user-defined headers. WebSphere ESB provides an API to create custom header data bindings, which parse these headers so they can be changed using a mediation flow.

Before creating the data binding, the user-defined header must be modelled as a business object using the IBM Integration Designer business object editor. An example of a MQ Dead Letter Header (MQDLH) is shown in Figure 2.

Figure 2. An example MQ Dead Letter Header (MQDLH)

The control information; Encoding, CodedCharSetId, and Format fields, of the header are not modeled here. They are mapped to the supplied MQControl Business Object.

The structure of WebSphere MQ headers are exposed differently in the SMO than they are on the wire by Websphere MQ. The key difference is:

You can readily change headers in the SMO. You can add and remove them from a sequence, without modifying the control information in other headers. The control information that is associated with the payload of the WebSphere MQ message, is kept in the control structure at the top level of the WebSphere MQHeader structure in the SMO. A WebSphere MQ header structure is shown in Figure 3.

Figure 3. WebSphere MQ header structure

After modeling the header, you must generate the business object using the data binding that parses the header. To do this create a class that implements the MQHeaderDataBinding interface. When you implement the MQHeaderDataBinding, you must implement the following methods:

The following Java code is an example of a custom header data binding that you use to parse an MQDLH header:

package com.ibm.custom.data.binding;

import java.io.IOException;
import com.ibm.mq.data.MQDataInputStream;
import com.ibm.mq.data.MQDataOutputStream;
import com.ibm.websphere.bo.BOFactory;
import com.ibm.websphere.sca.ServiceManager;
import com.ibm.websphere.sca.mq.data.MQHeaderDataBinding;
import commonj.sdo.DataObject;

public class MQDLHDataBindingImpl implements MQHeaderDataBinding {

	private DataObject dObj;
	private String nextFormat;
	private int nextCCSID;
	private int nextEncoding;
	    
	//MQDLHDataBinding only understands "MQDEAD" format 	public boolean isSupportedFormat(String format)
	{
		return format.trim().equals("MQDEAD");
	} 	  
	public DataObject getDataObject()
	{
		return dObj;
	} 
	public void setDataObject(DataObject dObj)
	{
		this.dObj=dObj;
	} 	  
	public void read(String format, MQDataInputStream input) throws IOException
	{
		//Check the Structure Id is the expected DLH
		String strucId=input.readMQCHAR4();
		if (!strucId.equals("DLH ")) throw new IOException
			("Malformed dead-letter header");
		//Check this is a version 1 header
		int version=input.readMQLONG();
		if (version!=1) throw new IOException("Unsupported DLH version");

		//Create the output DataObject
		BOFactory bof=(BOFactory)ServiceManager.INSTANCE.
			locateService("com/ibm/websphere/bo/BOFactory");
		DataObject dObj=bof.create("http://MQCustomHeaderLibrary", "MQDLH");
		dObj.setString("StrucId", strucId);
		dObj.setInt("Version", version);
		dObj.setInt("Reason", input.readMQLONG());
		dObj.setString("DestQName", input.readMQCHAR48());
		dObj.setString("DestQMgrName", input.readMQCHAR48());
		nextEncoding=input.readMQLONG();
		nextCCSID=input.readMQLONG();
		nextFormat=input.readMQCHAR8();
		dObj.setInt("PutApplType", input.readMQLONG());
		dObj.setString("PutApplName", input.readMQCHAR28());
		dObj.setString("PutDate", input.readMQCHAR8());
		dObj.setString("PutTime", input.readMQCHAR8());

		this.dObj=dObj;
	} 
	public void write(String format, MQDataOutputStream output) throws IOException
	{
		output.writeMQCHAR4("DLH ");     // StrucId
		output.writeMQLONG(1);           // Version 		output.writeMQLONG(dObj.getInt("Reason"));
		output.writeMQCHAR48(dObj.getString("DestQName"));
		output.writeMQCHAR48(dObj.getString("DestQMgrName"));
		output.writeMQLONG(nextEncoding);
		output.writeMQLONG(nextCCSID);
		output.writeMQCHAR8(nextFormat);
		output.writeMQLONG(dObj.getInt("PutApplType"));
		output.writeMQCHAR28(dObj.getString("PutApplName"));
		output.writeMQCHAR8(dObj.getString("PutDate"));
		output.writeMQCHAR8(dObj.getString("PutTime"));
	} 	  
	public void setNextFormat(String format)   {nextFormat=format;} 	public String getNextFormat()              {return nextFormat;} 	public void setNextCCSID(int ccsid)        {nextCCSID=ccsid;} 	public int getNextCCSID()                  {return nextCCSID;} 	public void setNextEncoding(int encoding)  {nextEncoding=encoding;} 	public int getNextEncoding()               {return nextEncoding;} }	

The API provides access to the MQDataInputStream, and the MQDataOutputStream, for reading and writing to a WebSphere MQ message. The methods allow you to access various WebSphere MQ types. For text types, you must know the length of the field in the custom WebSphere MQ header. This is always a multiple of 4, and is accessed using the readMQCHAR XX and writeMQCHAR XX methods, where XX is the number of characters to read or write.

In your binding configuration, you can add the custom header data binding to a list where multiple custom header data bindings are defined for handling sequences of headers. Any messages that contain the supported header, have the header parsed into the MQChainedHeader list provided in the SMO. You can access it using Java code or mediation primitives.


Use Java to access and change a WebSphere MQ header

Access the WebSphere MQ headers using the WMQStructures API, which provides a method to create new headers, or to access existing ones. The WebSphere MQ structures are accessed using the following SMO API:

//Retrieve the MQMD from the MQHeader
MQMD mqmd = smo.getHeaders().getMQHeader().getMd();

MQControl mqControl = smo.getHeaders().getMQHeader().getControl();
Access the headers within a function selector or data handler. The MQHeaderType must first be retrieved using the following context service API:
//Retrieve the headers from the context service HeadersType headers = ContextService.INSTANCE.getHeaders();

MQMD mqmd = headers.getMQHeader().getMd();

MQControl mqControl = headers.getMQHeader().getControl();

The MQMD and MQControl structures provide "getter" and "setter" methods for retrieving or modifying their data. Use the following WMQStructuresFactory API to create new versions of the structures:

//Create a new MQMD structure MQMD mqmd = WMQStructuresFactory.eINSTANCE.createMQMD();
//Set it in the MQHeader
smo.getHeaders().getMQHeader().setMd(mqmd);

//Create the MQControl structure.  This describes the format of the message body
mqControl = WMQStructuresFactory.eINSTANCE.createMQControl();
//Set it in the MQHeader
smo.getHeaders().getMQHeader().setControl(mqControl);

Access the WebSphere MQ header