Skip to main content

Using WebSphere MQ bindings in WebSphere ESB, Part 3: Using custom WebSphere MQ headers with WebSphere ESB

Philip Norton (nortonp@uk.ibm.com), Software Engineer, WebSphere ESB development team, IBM
Philip Norton photo
Philip Norton is a software engineer at IBM Hursley Lab. He works on the WebSphere ESB Development team. His expertise includes Java and JMS for Websphere MQ. He is a certified Java Programmer and he has a degree in Computer Science from Canterbury University.
Alex Wood (wooda@uk.ibm.com), Software Developer, IBM United Kingdom
Alex Wood
Alex Wood works at IBM Hursley Lab in England as a software developer for the IBM WebSphere Business Integration suite of products. He has extensive experience in development on many of the WebSphere products, including WebSphere MQ, WebSphere Message Broker, WebSphere Enterprise Service Bus, and WebSphere Process Server. He received a BSc in Physics with Astrophysics from Birmingham University in the UK in 1998.

Summary:  WebSphere ESB and WebSphere Process Server provide data bindings that enable parsing of various WebSphere MQ headers. However, many native WebSphere MQ applications employ user-defined headers, and this article shows you how to parse them using the data binding API to create custom header data bindings, which let you manipulate their headers using a mediation flow. Includes sample code to create a custom MQ header data binding and manipulate it using a mediation flow.

View more content in this series

Date:  28 Jan 2009
Level:  Intermediate
Activity:  405 views

Introduction

IBM® WebSphere® ESB V6.0.2 introduced WebSphere MQ bindings, which let you send and receive messages via WebSphere MQ. The MQ binding provides out-of-the box header data bindings to transform native MQ headers to DataObjects that can be used within a module. The supported headers are:

  • MQMD
  • MQRFH
  • MQRFH2
  • MQOpaqueHeader

The MQOpaqueHeader data binding deals with unrecognised MQ headers in a standard MQ format. It creates a DataObject with a structure id, version, structure length, encoding, ccsid, format, and flags. The rest of the data is set into a byte[].

Although MQ headers are dealt with by the MQOpaqueHeader data binding, the full structure of the header is not available to the application. It requires a custom header data binding that understands the full structure of the header and can create the required DataObject.

Products used in this article:

  • WebSphere Integration Developer V6.1
  • WebSphere ESB V6.1 Integrated Test Environment (included with WebSphere Integration Developer)
  • WebSphere MQ V6.0.2.2

Modeling the header

This article uses the MQ Dead Letter Header (MQDLH) as the native MQ header. To represent the MQDLH in the module as a DataObject, you need to model the header as a Business Object. Here is the structure of the MQDLH :


MQDLH
FieldDescription
StrucIdStructure identifier
VersionStructure version number
ReasonReason message arrived on dead-letter queue
DestQNameName of original destination queue
DestQMgrNameName of original destination queue manager
EncodingNumeric encoding of data that follows MQDLH
CodedCharSetIdCharacter set identifier of data that follows MQDLH
FormatFormat name of data that follows MQDLH
PutApplTypeType of application that put message on dead-letter queue
PutApplNameName of application that put message on dead-letter queue
PutDateDate when message was put on dead-letter queue
PutTimeTime when message was put on dead-letter queue

  1. Create a new library named MQCustomHeaderLibrary
  2. Open the dependencies on the library, and under Predefined Resources, tick Schema for simple JMS Data Bindings, then click Save.
  3. In the Library, create a new interface called MQBytesInterface.
  4. Create a one-way operation, leaving the operation name as the default.
  5. Change the type of input1 to JMSBytesBody and click Save to save the interface.
  6. In the library, create a new business object called MQDLH.
  7. Add the required fields:

Figure 1. MQDLH Business Object
MQDLH

The Encoding, CodedCharSetId, and Format fields are not modeled here, as they are mapped to the supplied MQControl Business Object. For more information on the MQControl, see Part 1 of this series. You will see below how to map these fields in the data binding.

Writing the Custom Header data binding

  1. In the MQCustomHeaderLibrary, create a new Java class named MQDLHDataBindingImpl in package com.ibm.custom.data.binding that implements MQHeaderDataBinding.
  2. Replace the contents with the code below:

Listing 1. MQDLH Custom Data Binding

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;}
}	

Description of the data binding

When implementing MQHeaderDataBinding, you need to implement several methods:

  • isSupportedFormat receives a format and checks whether this data binding supports it. In this case it returns true only if the format matches the MQDLH format MQDEAD.
  • getDataObject returns the DataObject created by the read method of this data binding.
  • setDataObject sets the DataObject in this data binding.
  • read reads the message header of incoming messages and create the required DataObject. In this case, the MQDLH Business Object is created and populated.
  • write creates the message header for outgoing messages.
  • setNextFormat sets the formatting of either the next header, or if this is the last header in the chain, the body of the message.
  • getNextFormat gets the formatting of either the next header, or if this is the last header in the chain, the body of the message. The format field in this header is normally used to describe the format of the next part of the message, hence it returns the value retrieved by the read method.
  • setNextCCSID sets the Coded Character Set Id of either the next header, or if this is the last header in the chain, the body of the message.
  • getNextCCSID gets the Coded Character Set Id of either the next header, or if this is the last header in the chain, the body of the message. The ccsid field in this header is normally used to describe the ccsid of the next part of the message, hence it returns the value retrieved by the read method.
  • setNextEncoding sets the encoding of either the next header, or if this is the last header in the chain, the body of the message.
  • getNextEncoding gets the encoding of either the next header, or if this is the last header in the chain, the body of the message. The encoding field in this header is normally used to describe the encoding of the next part of the message, hence it returns the value retrieved by the read method.

The MQDataInputStream and MQDataOutputStream provide methods for reading and writing native MQ headers. For more information, see WebSphere ESB information center.

Using the Custom Header data binding in a mediation module

  1. Create a new mediation module called MQCustomHeaderModule. Ensure that Create mediation component is ticked and then click Next.
  2. Tick MQCustomHeaderLibrary and click Finish.
  3. Add an import to the assembly diagram.
  4. Wire the mediation component to the import. When asked to add a reference, select MQBytesInterface.
  5. Right-click on Import1 and select Generate Binding => Messaging Binding => MQ Binding.
  6. Specify your queue manager name, send destination, host name, server channel, and port of your WebSphere MQ installation.
  7. Under Data Configuration, click Browse.
  8. Select the Show predefined data bindings radio button.
  9. Select MQ unstructured binary message, click OK, and then click OK again.
  10. Right-click on the mediation component, select Add => Interface, select the MQBytesInterface, and then click OK.
  11. In the Properties view of the Import on the Bindings tab, under User supplied MQ Header Data Binding Configuration, click Add.
  12. Select the Show data binding classes radio button.
  13. From the list of data bindings, select MQDLHDataBindingImpl and then click OK.

Your module should now look like this:


Figure 2. MQCustomHeaderModule
MQCustomHeaderModule

  1. Double-click on the mediation component MQCustomHeaderModule to generate an implementation.
  2. In the Mediation Flow Editor, wire operation1 to operation1 to create a flow.
  3. In the Palette, select Transformation => Custom Mediation.
  4. Add the custom mediation to the canvas.
  5. Wire the input node to the input terminal of the custom mediation.
  6. Wire the output terminal of the custom mediation to the callout node.
  7. On the properties panel of the custom mediation, select the Details tab.
  8. Click the Java radio button.
  9. Replace the content with the code below and click Save.

Listing 2. Custom Mediation Code for Adding MQDLH Header

//Retrieve the MQ header
MQHeaderType mqHeader = smo.getHeaders().getMQHeader();
//If there is no MQHeader 
if (mqHeader == null) {
	//Create the SMO MQHeaderType.  This contains all the MQ headers
	mqHeader = ServiceMessageObjectFactory.eINSTANCE.createMQHeaderType();
	//Set the MQHeader in the SMO
	smo.getHeaders().setMQHeader(mqHeader);
}

//Use BOFactory to create an instance of MQDLH
ServiceManager serviceManager = ServiceManager.INSTANCE;
BOFactory bofactory = (BOFactory) serviceManager.
	locateService("com/ibm/websphere/bo/BOFactory");
DataObject mqdlh = bofactory.create("http://MQCustomHeaderLibrary", "MQDLH");
//Populate the header
mqdlh.setString("StrucId", "DLH ");
mqdlh.setInt("Version", 1);
mqdlh.setInt("Reason", MQC.MQFB_APPL_TYPE_ERROR);
mqdlh.setString("DestQName", "SD");
mqdlh.setString("DestQMgrName", "QM");
mqdlh.setInt("PutApplType", MQC.MQAT_JAVA);
mqdlh.setString("PutApplName", "WebSphere ESB");
mqdlh.setString("PutDate", "20080319");
mqdlh.setString("PutTime", "0900");

//Get the current list of MQ Headers
List mqHeaders = smo.getHeaders().getMQHeader().getHeader();
//Create a new MQChainedHeaderType
MQChainedHeaderType chainedHeader = 
	ServiceMessageObjectFactory.eINSTANCE.createMQChainedHeaderType();
//Set the CCSID, encoding and format of the header
chainedHeader.setCodedCharSetId(1208);
chainedHeader.setEncoding(MQC.MQENC_INTEGER_NORMAL | 
                      MQC.MQENC_DECIMAL_NORMAL | 
                      MQC.MQENC_FLOAT_IEEE_NORMAL);
chainedHeader.setFormat(MQC.MQFMT_DEAD_LETTER_HEADER);
//Set the value of this header to be the MQDLH                     
chainedHeader.setValue(mqdlh);
//Add the chained header to the list of MQ headers
mqHeaders.add(chainedHeader);

out.fire(smo);			

This code only adds the MQDLH header to the MQHeaderType structure, not the MQMD. If no MQMD is specified when the message reaches the MQ import binding, then a default MQMD will be added. However, if an MQMD was added here, then the MQ import binding uses it instead of adding a default header.

Testing the module

Use the universal test client to test the module:

  1. Right-click on MQCustomHeaderModule mediation component and select Test component.
  2. The body of the message does not matter, so click Continue.
  3. In the Deployment Location, window select WebSphere ESB Server and then click Finish.

The server will start and the application will be deployed and invoked. Once the component test is complete, you will see the invoke returned.

  1. Using WebSphere MQ Explorer, right-click on the Send queue and select Browse Messages.
  2. Double-click on the message and you will see the properties that were set in the mediation component:

Figure 3. MQMessage
MQDLHMessage

Congratulations -- you have successfully created a mediation module that adds a custom MQHeader to a message.



Download

DescriptionNameSizeDownload method
Project Interchange for MQCustomHeaderModuleMQCustomHeaderModulePI.zip17 KBHTTP

Information about download methods


Resources

About the authors

Philip Norton photo

Philip Norton is a software engineer at IBM Hursley Lab. He works on the WebSphere ESB Development team. His expertise includes Java and JMS for Websphere MQ. He is a certified Java Programmer and he has a degree in Computer Science from Canterbury University.

Alex Wood

Alex Wood works at IBM Hursley Lab in England as a software developer for the IBM WebSphere Business Integration suite of products. He has extensive experience in development on many of the WebSphere products, including WebSphere MQ, WebSphere Message Broker, WebSphere Enterprise Service Bus, and WebSphere Process Server. He received a BSc in Physics with Astrophysics from Birmingham University in the UK in 1998.

Comments (Undergoing maintenance)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere
ArticleID=367197
ArticleTitle=Using WebSphere MQ bindings in WebSphere ESB, Part 3: Using custom WebSphere MQ headers with WebSphere ESB
publish-date=01282009
author1-email=nortonp@uk.ibm.com
author1-email-cc=ramaker@us.ibm.com
author2-email=wooda@uk.ibm.com
author2-email-cc=

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Special offers