This article is aimed at integration developers whose role involves integrating MQ messaging engines using Service Component Architecture (SCA). It describes how to use a Data Handler to change the transformation logic based on an MQ header, while ensuring the handler remains protocol neutral. Topics that will be covered are:
- Explanation of a Data Handler
- Accessing MQ headers from a Data Handler
- Altering the behavior of my Data Handler based on a header
- Ensuring the Data Handler remains protocol neutral
After reading this article you will be able to author reusable data handlers that dynamically transform data based on a MQ header.
A Data Handler is responsible for transforming the input and output types of an operation to the format used on the wire and visa versa. Previously the MQ binding used Data Bindings to perform this function. A Data Binding would have access to the wire format i.e. MQ message, and could read or write directly to or from the message respectively. This connected each Data Binding to a particular binding type e.g. a MQ Data Binding could not be used on a JMS binding.
Data Handlers provide a generic way of transforming data by using canonical formats. The transform method is used for reading data and one of the following types is passed to read the input:
- InputStream - for reading bytes
- Reader - for reading text
- Object - for reading Java Objects
The transformInto method is used for writing data and one of the following types is passed in to write the output:
- OutputStream - for writing bytes
- Writer - for writing text
- Object - for writing Java Objects
This makes the wire format of the message transparent to the Data Handler allowing them to be reused by any of the supported bindings.
Data Handlers and Message Headers
When authoring a Data Binding the message headers were passed into the read or write method, allowing transformation logic to be determined by a field in the protocol header. However, for Data Handlers the method input parameters do not include the protocol headers, so how do we access them?
In WebSphere Enterprise Service Bus (WESB) V6.2, protocol headers are stored in a repository called ContextService. The ContextService is accessed using a common SPI and can be referenced from any Java code, including POJOs, Function Selectors, or Data Handlers. Example code for obtaining the MQHeader from the ContextService is shown in Listing 1.
Listing 1. Accessing Protocol Headers using Context Service
HeadersType headers = ContextService.INSTANCE.getHeaders(); MQHeaderType mqHeader = headers.getMQHeader(); |
Using the MQHeader in a Data Handler
Now we know how to access the MQ Header in the Data Handler lets make a transformation decision, based on one of the fields. The format field of the MQMD is often used to determine the message body format. The format, encoding and coded character set of the message body are stored in the MQControl structure, contained in the MQ Header. The code shown in Listing 2 demonstrates how to modify the transformation logic depending on the value of the format field in the MQMD.
Listing 2. Changing Behaviour based on MQMD format field
package com.ibm.custom.datahandlers;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Map;
import com.ibm.websphere.bo.BOFactory;
import com.ibm.websphere.bo.BOXMLDocument;
import com.ibm.websphere.bo.BOXMLSerializer;
import com.ibm.websphere.sca.ServiceManager;
import com.ibm.websphere.sca.mq.structures.MQControl;
import com.ibm.websphere.sibx.smobo.HeadersType;
import com.ibm.websphere.sibx.smobo.MQHeaderType;
import com.ibm.wsspi.session.ContextService;
import commonj.connector.runtime.DataHandler;
import commonj.connector.runtime.DataHandlerException;
import commonj.sdo.DataObject;
@SuppressWarnings("serial")
public class MQHeaderDataHandler implements DataHandler {
Map bindingContext;
String delimiter = "%";
/**
* Reads a DataObject from an InputStream (Bytes support only)
*/
public Object transform(Object source, Class target, Object options)
throws DataHandlerException {
System.out.println("MyDataHandler: Calling
transform(" + source + "," + target + "," + options + ")");
DataObject output = null;
InputStream is = (InputStream) source;
//Handle InputStreams and DataObjects
if (source instanceof InputStream &&
target.getName().equals("commonj.sdo.DataObject")) {
if (("MQXML").equals(getMQMessageFormat())) {
//If the format field of the incoming message
is XML use BOXMLSerializer
ServiceManager serviceMgr = new ServiceManager();
BOXMLSerializer xmlSerializer =
(BOXMLSerializer) serviceMgr
.locateService
("com/ibm/websphere/bo/BOXMLSerializer");
try {
BOXMLDocument xmlDoc = xmlSerializer.
readXMLDocumentWithOptions
(is , options);
output = xmlDoc.getDataObject();
((InputStream)source).close();
} catch (IOException e) {
throw new
DataHandlerException
("Exception reading DataObject "
+ e.getLocalizedMessage());
}
} else {
//Read delimited data
byte[] ch = new byte[2];
StringBuffer buffer = new StringBuffer();
try {
int len = is.read(ch);
while (len != -1) {
buffer.append(new String(ch), 0, len);
len = is.read(ch);
}
} catch (IOException e) {
throw new DataHandlerException(e);
}
//Split the values using the delimiter
String[] values = buffer.toString().split(delimiter);
System.out.println("Found name: "+values[0]+" and id: "
+values[1]);
//Build the CustomerType
ServiceManager serviceManager = new ServiceManager();
BOFactory bofactory =
(BOFactory) serviceManager.locateService
("com/ibm/websphere/bo/BOFactory");
output =
bofactory.create("http://
MQHeaderDataHandlerModule", "CustomerType");
output.setString("name", values[0]);
output.setInt("id", Integer.parseInt(values[1]));
}
} else {
throw new
DataHandlerException("Source type " +
source.getClass().getName() + " or Target type "
+ target.getName() + " unsupported by
MyDataHandler");
}
return output;
}
/**
* Writes the DataObject out to a OutputStream (Bytes support only)
*/
public void transformInto(Object source, Object target, Object options)
throws DataHandlerException {
System.out.println("Calling
transformInto(" + source + "," + target + "," + options + ")");
if (source instanceof DataObject && target instanceof OutputStream) {
OutputStream os = (OutputStream) target;
DataObject bo = (DataObject) source;
if (("MQXML").equals(getMQMessageFormat())) {
//If the format field of the outgoing message is XML use
BOXMLSerializer
ServiceManager serviceMgr = new ServiceManager();
BOXMLSerializer xmlSerializer = (BOXMLSerializer)
serviceMgr.locateService("com/ibm/websphere/
bo/BOXMLSerializer");
try {
xmlSerializer.writeDataObject(bo, bo.getType().
getURI(), bo.getType().getName(), os);
} catch (IOException e) {
throw new
DataHandlerException("Exception writing
DataObject " + e.getLocalizedMessage());
}
} else {
//Write delimited data
String name = bo.getString("name");
int id = bo.getInt("id");
String message = name+delimiter+id;
try {
os.write(message.getBytes());
} catch (IOException e) {
throw new
DataHandlerException("Exception writing
DataObject " + e.getLocalizedMessage());
}
}
} else {
throw new
DataHandlerException("Source type " + source.getClass()
.getName() + " or Target type "
+ target.getClass().getName() +
" unsupported by MyDataHandler");
}
}
/**
* Returns the format of the MQHeader or null if there is no MQHeader
* @return
*/
private String getMQMessageFormat() {
String format = null;
HeadersType headers = ContextService.INSTANCE.getHeaders();
MQHeaderType mqHeader = null;
if(headers!= null){
mqHeader = headers.getMQHeader();
if (mqHeader != null) {
MQControl mqControl = mqHeader.getControl();
if (mqControl != null) {
format = mqControl.getFormat();
if (format != null) {
format = format.trim();
}
}
}
}
return format;
}
public void setBindingContext(Map context) {
bindingContext = context;
}
}
|
This handler uses the MQHeader format field and if it is set
to MQXML the message body is treated as XML, otherwise the body will be treated as delimited data.
If this Data Handler was used with a non MQ binding then the MQHeader will not be defined in the ContextService.
In this case the getMQMessageFormat() method will return null, resulting
in the body being treated as delimited data, therefore the Data Handler remains protocol neutral.
First of all lets create a simple module with an MQ binding. It is assumed that WebSphere MQ has been installed and is accessible within WebSphere ESB.
- In WID create a new module called
MQHeaderDataHandlerModule - In the MQHeaderDataHandlerModule project create a new Data Type called
CustomerType
Figure 1. CustomerType Business Object

- Add a String field called
nameand an int field calledid - Save and close the new data type
- Create a new Interface called
CustomerInterface - Add a one way operation called
processCustomerthat accepts CustomerType as the input parameter
Figure 2. Customer Interface

- Add a new export to the assembly diagram
- Add the CustomerInterface to the export
- On the export configure an MQ binding
- Set the request queue manager name
- Set the receive destination
- Set the connection details appropriately for your WebSphere MQ Queue Manager
- For the default request data format, click select
- Select Select your custom data format transformation from the workspace and click select
- Choose the MQHeaderDataHandler and click ok
- Tick the Add custom class to binding registry and click next (this will make it available in the existing data format list)
- Enter the name
MQHeaderDataHandler - Add a description
- Select the type of bindings it applies to, for now tick MQ and JMS
Figure 3. Setting Data Format

- On the import configure an MQ binding with the same data format as above
- To ensure the DataObject is being created correctly we will print it out using a Java component, so add one to the canvas
- Wire the Java component to the export and the import, your module should now look like Figure 4
Figure 4. MQHeaderDataHandlerModule

- Double click on the Java component to create an implementation
- Replace the implementation of processCustomer with the code from Listing 3
Listing 3. Printing Data Object
BOFactory factoryService = (BOFactory) new
ServiceManager().locateService("com/ibm/websphere/bo/BOFactory");
BOXMLSerializer xmlSerializerService =(BOXMLSerializer) new
ServiceManager().locateService("com/ibm/websphere/bo/BOXMLSerializer");
try {
xmlSerializerService.writeDataObject(input1, input1.getType().getURI(),
input1.getType().getName(), System.out);
} catch (IOException e) {
e.printStackTrace();
}
locateService_CustomerInterfacePartner().processCustomer(input1);
|
- Save the Java component
- Save the module
To test the module we will use RFHUtil which allows us to create MQ messages and put them to the exports receive destination. We can then use the server log view in WID to see the DataObject printed by the Java component and use RFHUtil again to view the message output by the import.
- Create a file called
CustomerType.xmlin the MQHeaderDataHandlerModule project - Set the contents to the XML shown in Listing 4
Listing 4. CustomerType XML Data
<?xml version="1.0" encoding="UTF-8"?> <p:CustomerType xmlns:p="http://MQHeaderDataHandlerModule" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://MQHeaderDataHandlerModule CustomerType.xsd "> <name>Tim</name> <id>114923</id> </p:CustomerType> |
- Create a file called
CustomerType.txtin the MQHeaderDataHandlerModule project - Set the contents to the XML shown in Listing 5
Listing 5. CustomerType Delimited Data
Tim%114923 |
- Deploy your module to the server
- Start RFHUtil, and set the queue manager and the queue used by the export
- Use Read File to read in CustomerType.txt, you should be able to see the message body under the data tab
- Press the WriteQ button to send the message to the queue
- Check the Server Logs view in WebSphere Integration Developer for the print out of the DataObject
- Back in RFHUtil Change the queue to that used by the import and click ReadQ
- Flick to the Data tab to see the message body which should look like Figure 5
Figure 5. Output Delimited Message

- Flick back to the Main tab in RFHUtil
- Use Read File to read in CustomerType.xml, you should be able to see the message body under the data tab
- Go to the MQMD tab and set the message format to
MQXML
Figure 6. Setting MQXML message format

- Back on the Main tab press WriteQ to send the message
- Change the queue to that used by the import and click ReadQ
- Flick to the Data tab to see the message body which should look like Figure 7
Figure 7. Output XML message

Congratulations, you have successfully created and tested a protocol neutral Data Handler whose behavior is controlled by a field in the MQ Header. We can see that if the format field is set to MQXML then the message is treated as XML. If there is no MQ Header, then the data would also be treated as delimited. Try using this data handler with another binding and check the behavior.
In this article we concentrated on using the MQ format field to change the data handler logic, we could also have used fields in any of the other headers, such as JMS Header or HTTP Header if dealing with these protocols. It is worth noting that the headers are only available to the Data Handler if Propagate protocol header is enabled, which it is by default. To view the setting check the Propagation tab in the binding properties panel.
| Description | Name | Size | Download method |
|---|---|---|---|
| Project Interchange for MQHeaderDataHandlerModule | MQHeaderDataHandlerModulePI.zip | 14KB | FTP |
Information about download methods
- Participate in the discussion forum.
- WebSphere ESB product information
Product descriptions, product news, training information, support information, and more. - WebSphere ESB Information Center
A single Eclipse-based Web portal to all WebSphere ESB documentation, with conceptual, task, and reference information on installing, configuring, and using WebSphere ESB. - WebSphere ESB support
A searchable database of support problems and their solutions, plus downloads, fixes, problem tracking, and more. - WebSphere Integration Developer product page
A single Eclipse-based Web portal to all WebSphere Integration Developer documentation, with conceptual, task, and reference information on installing, configuring, and using your WebSphere Integration Developer environment. - WebSphere Integration Developer information center
Product descriptions, product news, training information, support information, and more. - WebSphere Integration Developer support
A searchable database of support problems and their solutions, plus downloads, fixes, problem tracking, and more. -
Getting started with WebSphere Enterprise Service Bus and WebSphere Integration Developer
This article introduces developers to the IBM WebSphere Enterprise Service Bus server and its accompanying tooling, WebSphere Integration Developer. -
Developing custom mediations for WebSphere Enterprise Service Bus
This article introduces the use of custom mediations using the WebSphere Integration Developer V6 environment for WebSphere Enterprise Service Bus V6. -
Invoke Web Services with WebSphere MQ and WebSphere ESB
This tutorial introduces the WebSphere ESB MQ bindings and uses a custom body data binding to read and write MQ messages. -
Invoking a Web Service using a JMS client
This tutorial introduces the WebSphere ESB JMS bindings and shows how a JMS message can be used to invoke a Web Service.

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. You can reach Philip at nortonp@uk.ibm.com

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

Dr. Fenglian Xu works as a software developer in the WebSphere Enterprise Service Bus development team at IBM Hursley Lab in the UK. Her expertise includes the JMS and Web services over JMS bindings in WebSphere Enterprise Service Bus and WebSphere Application Server. She has worked in various IT companies from middleware to application for 10 years. She has gained her main expertise in Java, J2EE, and SOA. She obtained her PhD degree in computer science from the University of Southampton in 1998.
Comments (Undergoing maintenance)





