IBM WebSphere Developer Technical Journal: A practical introduction to message mediation -- Part 5

Mediating request/response style message interactions

Part 5 of this article series on message mediations, which extend the messaging capabilities of IBM® WebSphere® Application Server, explains how to mediate RPC style message interactions. The examples in this article use the code provided by previous articles in this series.

Alasdair Nottingham, Software Engineer, IBM

Author photoAlasdair Nottingham has been a developer on WebSphere Application Server since 2001. In that time he has been involved in the messaging solution provided in WebSphere Application Server, including the development of the message mediation support included in WebSphere Application Server V6.



24 March 2006 (First published 22 February 2005)

From the IBM WebSphere Developer Technical Journal.

Introduction

If you have read the previous articles in this series, then you will be familiar with creating and using message mediations, a new programmatic extension to the messaging capabilities of IBM WebSphere Application Server V6, that can simplify connecting systems, services, applications, or components that use messaging. These, along with other recent articles by IBM colleagues, have focused primarily on the one-way messaging paradigm. However, it is also common for Java™ Messaging Service (JMS) and other applications to implement request/response style semantics. The JMS specification even provides the QueueRequestor and TopicRequestor classes to simplify this dynamic messaging. In Part 5 of this series, we will explain how to use message mediations to handle request/response messages.

For the purpose of this article, the application example we will look at is a stock inventory management system that sends queries to determine the quantity of an item that is in stock in a warehouse. The information to answer the query will be sent in a response. This article reuses the mediation written for Part 4: Modifying messages with mediations and XSLT.


Mediations in review

Let's begin by reviewing what we mean by a mediation and a message format in the context of WebSphere Application Server.

A mediation handler is a Java class that is associated with a messaging destination, and its mediate method is invoked whenever a message is sent to that destination. A mediation handler can modify, reroute, or even delete the message.

Several sorts of messages can be given to a mediation handler. The mediation handler determines what sort of message it has been given by using the getFormat method to obtain the message format. Possible values of the format include:

FormatDescription
JMS:byteJMS message containing a byte array.
JMS:textJMS message containing a string.
JMS:objectJMS message containing an byte array that can be deserialized into an object using a java.io.ObjectInputStream.
JMS:streamJMS message containing a stream of typed data.
JMS:JMS message with no content (created by constructing a javax.jms.Message object rather than any specific JMS message type).
SOAP:SOAP message to or from a Web service.
Bean:Message to or from a Web service.

Request/Response processing in messaging

Messaging providers do not typically provide direct support for request/response messaging, but there are three conventions which are generally used:

  1. Use temporary reply queue. In this model, the requester creates a temporary destination, puts the address of the response destination into the request message, and then sends it. The responder then sends the response to that destination. This model is commonly used by JMS applications, and has the disadvantage that to correlate individual requests with responses, it is necessary to use a temporary destination per request. To work around this limitation, it is common to use a single temporary destination per client and then use the mechanism described in the next two points to correlate individual requests and responses.

  2. Copy Message ID to Correlation ID. In this model, the requesting application listens on a well known queue for a response. This queue is either known by both the requester and the responder, or the requester specifies in the request message where to send replies. The responding application then copies the message ID of the request into the correlation ID of the response. The requester then uses this in the correlation ID to filter the response. This model is used by the inbound, outbound, and gateway service functions in the service integration bus. It is also commonly used by WebSphere MQ applications.

  3. Copy Correlation ID to Correlation ID. This model is identical to the previous model, except that the requester adds a correlation ID to the request message. The responder then copies the correlation ID of the request message into the correlation ID of the response message. This is commonly used by WebSphere MQ applications.


Request/Response processing in a bus

The bus itself does not have direct support for request/response processing, but does provide support upon which request/response processing can be easily built.

Each message contains it a list (or path) of destinations that the message should visit as it progresses through the bus. This is known as the forward routing path, and typically a request message will be sent with a path containing a single destination. Additionally, a destination can be configured with a default forward routing path, which will be put into a request message if it arrives at the destination without a forward routing path.

A message also contains a reverse routing path. Although this is not processed as a message goes through the bus, this path would typically be taken from the request message and set as the forward routing path of the response message. In this way, the route that the response message takes as it travels through the bus can be affected by the processing of the request message.

If a response is expected, then the request message will have a reverse routing path set. Each destination can have a reply destination specified. This destination will be prepended to the reverse routing path (if one already exists) as the message travels through that destination.


Mediating request/response messaging

As a general rule, mediating request/response message interactions in the bus is not that much more difficult than mediating a one-way message. If you need to mediate a request message, some form of mediation will probably be required on the response path. A simple example is the transformation of a message from a COBOL copybook to XML; if the responder only understands XML and the requester only understands COBOL, then both the request and response message will need to be transformed.

When mediating a request message, there are a number of ways a response mediation can be applied, if one is needed:

  1. Create a mediation that understands whether the message is a request or response, and acts appropriately. The destination on which the mediation is applied could be added to the request message's reverse routing path. This would mean that the response message would travel back via the mediation's destination.

  2. Create two mediations could be created: a request mediation and a response mediation. These are applied to two different destinations. The request message goes through one and the response message goes through the other. Either the request message could simply add the response mediation's destination to the reverse routing path, or simply apply the reverse mediation to the reply destination.

  3. Create a single mediation that does not understand the difference. In this case, the same mediation can be applied to the request and response path and will perform the same logic, but can be parameterised based on the destination to which it is deployed.

The simplest of these to implement is the last, the most complex is the first. By making use of the reply destination field on a destination, the request mediation does not need to do anything to have the response routed to its companion response destination. This is especially useful if you have a generic mediation, such as an XSLT mediation that needs to be applied to perform a different XSLT mediation on the request and response legs.


Design decisions

It is important to choose an appropriate request/response model for your application and environment. For the purpose of this article, we will be using a combination of the first and second models, listed above. In our model, the client will create a temporary destination for all its requests, and will correlate the individual requests and responses by copying the message ID to the correlation ID.

We will go through a relatively simple example of request/response mediations, showing how it can be performed without writing any code. The redbook Patterns: SOA with an Enterprise Service Bus in WebSphere Application Server V6 gives details on more complex examples of aggregating and disaggregating messages.

The example will make use of a simple JMS application to provide the requesting client and the responding service. It is likely in a real world solution that the responding application is some form of enterprise application distinct from the client.

JMS request message

The JMS application sends a JMS BytesMessage to the requestQueue with the XML shown in Listing 1.

Listing 1. Listing 1. Example XML document produced by JMS client
  <?xml version="1.0" encoding="utf-8"?>
  <stockQuery>
    <item number="1234"/>
  </stockQuery>

The responding part of the JMS application requires that the XML be in the format shown in Listing 2.

Listing 2. Listing 2. Example XML document as required by responding JMS application
  <?xml version="1.0" encoding="utf-8"?>
  <stockQuery>
    <item>1234</item>
  </stockQuery>

The request message will need to be transformed before it gets to the responding application. The XSLT shown in Listing 3 will perform the transformation.

Listing 3. Listing 3. The XSLT used to translate the two request XML documents
<?xml version="1.0" encoding="utf-8"?>
<stockQuery xmlns:xslt="http://www.w3.org/1999/XSL/Transform" xslt:version="1.0">
  <item><xslt:value-of select="/stockQuery/item/@number"/></item>
</stockQuery>

JMS response message

The responding JMS application sends the response in a JMS BytesMessage to the JMSReplyTo specified in the request message. It puts the XML shown in Listing 4 into the response message.

Listing 4. Listing 4. Example XML document produced by responding application
  <?xml version="1.0" encoding="utf-8"?>
  <stockAvailability>
    <quantity>2</quantity>
  </stockAvailability>

The client part of the JMS application requires the XML to be in the format shown in Listing 5.

Listing 5. Listing 5. Example XML document required by requesting application
  <?xml version="1.0" encoding="utf-8"?>
  <stockAvailability>
    <item quantity="2"/>
  </stockAvailability>

The response message will need to be transformed before it gets to the client application. The XSLT shown in Listing 6 will perform the transformation.

Listing 6. Listing 6. The XSLT used to translate the two response XML documents
<?xml version="1.0" encoding="utf-8"?>
<stockAvailability xmlns:xslt="http://www.w3.org/1999/XSL/Transform" 
	xslt:version="1.0">
  <item><xslt:attribute name="quantity"><xslt:value-of 
	select="/stockAvailability/quantity"/></xslt:attribute>
	</item>
</stockAvailability>

This example is, of course, trivial and in a real world application a more substantial conversion is required. For example SOAP to COBOL copybook on the request and COBOL copybook to SOAP on the response.


Simple request/response mediation

Here, we will demonstrate how to build request/response mediations, and, specifically, how it is possible to build these mediations without writing any code.

Initial configuration

This example requires that certain resources be created up front, which can be done simply by using the supplied createInitialResources.jacl script included in the download material. This script will create the resources listed in these tables:

A bus will be created with a single bus member:

Common mistake when creating a bus

When creating a bus (especially on a non-federated application server), it is common to forget to add a bus member. I do this all the time.

FieldValue
NamedwBus

Two queue type destinations will be created in separate objects:

FieldValue
IdentifierdwRequestQueue
IdentifierdwResponseQueue

A single mediation:

Good practice

Wherever possible, use the same name for both the mediation and the handler list name. This can avoid much confusion when debugging a mediated message flow.

FieldValue
NamedwXSLTMediation
Mediation handler list namedwXSLTMediation

The destinations dwRequestQueue and dwResponseQueue are then mediated using dwXSLTMediation.

For the supplied JMS application, the following JMS resources will be defined using the default messaging provider.

JMS connection factory:

FieldValue
NamedwCF
JNDI Namejms/dw/CF
Bus NamedwBus

JMS queue:

FieldValue
NamedwDest
JNDI Namejms/dw/dest
Bus NamedwBus
Queue NamedwRequestQueue

Configuring for request/response processing

We now have our initial configuration setup that we can modify to enable request/response processing. (To create the basic resources, see the previous articles in this series, listed in Resources.)

  1. The first change is to set the reply destination name on the request destination:

    1. From the WebSphere Application Server administrative console, expand Service integration => Buses.
    2. Select the bus dwBus.
    3. Under Destination Resources select Destinations.
    4. Select the destination dwRequestQueue.
    5. Scroll down until the Reply destination field is visible and enter dwResponseQueue as shown in Figure 1.
      Figure 1. Figure 1. Configuring a reply destination
      Configuring a reply destination
    6. Click OK.

Common mistake when configuring context properties

When configuring context properties, it is common to not specify the context type. If an incorrect context type is set, then either the data will not be available to the mediation, or it will not be of the correct type, resulting in a ClassCastException. Which of these occurs will depend on the mismatch in question.

  1. This next step is to configure the XSLT mediation so it applies the proper transformation. The XSLT applied by the mediation can be specified using either mediation context properties or destination context properties. These properties are set in the administrative console on the destination or mediation. They are then placed into the SIMediationContext as properties. For this example, the same mediation is applied to two different destinations where each destination needs a different XSLT to be applied. This means that the destination context properties are the appropriate places to specify this information.

    1. From the administrative console, expand Service integration => Buses.
    2. Select the bus dwBus.
    3. Under Destination Resources select Destinations.
    4. Select the destination dwRequestQueue.
    5. Select the link Context Properties.
    6. Click New.
    7. Enter or select the following values (Figure 2):
      • Name:Stylesheet
      • Context type:String
      • Context value:<?xml version="1.0" encoding="utf-8"?><stockQuery xmlns:xslt="http://www.w3.org/1999/XSL/Transform" xslt:version="1.0"><item><xslt:value-of select="/stockQuery/item/@number"/></item></stockQuery>
      Figure 2. Figure 2. Configuring the request mediation XSLT
      Configuring a the request mediation XSLT
  2. This also needs to be done for the response destination specifying the second XSLT.

    1. From the administrative console, expand Service integration => Buses.
    2. Select the bus dwBus.
    3. Under Destination Resources, click Destinations.
    4. Select the destination dwResponseQueue.
    5. Select the link Context Properties.
    6. Click New.
    7. Enter or select the following values (Figure 3):
      • Name:Stylesheet
      • Context type:String
      • Context value:<?xml version="1.0" encoding="utf-8"?><stockAvailability xmlns:xslt="http://www.w3.org/1999/XSL/Transform" xslt:version="1.0"><item><xslt:attribute name="quantity"> <xslt:value-of select="/stockAvailability/quantity"/> </xslt:attribute></item></stockAvailability>
      Figure 3. Figure 3. Configuring the response mediation XSLT
      Configuring the response mediation XSLT

The XSLT mediation

The XSLT mediation used by this application is a slight modification to the mediation provided in the previous article, which performed the XSLT on a copy of the message. The mediation used in this example performs the XSLT on the message being mediated. The code shown in Listing 7 replaces the code in the innerHandle method of the XSLTMediationHandler class. This mediation is stored in the MediationPart5MediationEAR.ear file, included in the download material, and needs to be installed into the server.

Listing 7. Listing 7. The content of the modified innerHandle method
    // Retrieve the message from the context
    SIMessage message = getContext().getSIMessage();

    // Get the message contents in the form of a JMS Bytes message
    try
    {
      // Get a new datagraph for the new message we're about to build - Point 1
      DataGraph graph = message.getNewDataGraph(SIApiConstants.JMS_FORMAT_BYTES);
      DataObject body = graph.getRootObject();
      if (body.isSet("data"))
      {
        // Grab the bytes
        byte[] payload = body.getBytes("data/value");

        // Transform the bytes
        payload = XSLTTransform.transform(payload,getStringProperty(STYLESHEET_PROPERTY_NAME));

        // Replace the payload in the data graph
        body.setBytes("data/value",payload);

        message.setDataGraph(graph, SIApiConstants.JMS_FORMAT_BYTES);
      }
      else
      {
        // No bytes sent, so throw an IllegalArgument so that the message
        // will be sent to the exception destination
        IllegalArgumentException e = new IllegalArgumentException("No body to the message");
        throw e;
      }
    }
    catch(Exception e)
    {
      // Hmm, we had a problem somewhere doing the transformation or maybe the send
      e.printStackTrace();
      throw new MessageContextException(e);
    }

    // If we get here, everything worked and the tracking message has been sent
    return true;

Running the test application

JMS BytesMessage caution

Avoid using the provided writeUTF method when sending a JMS BytesMessage containing XML data; since the UTF encoding adds extra data, the message will not start with the first character of the string. As a result, take care when reading the string from within a mediation. (Our example does not use this method.)

Before running the application, it is important to save the configuration and restart the application server. After this has been done, run the sample application by executing this command: launchClient.bat MediationPart5ClientEAR.ear 5. This should result in the output shown in Listing 8.

The test application is a simple JMS application that acts both as the client and the server, and takes a single number as an argument.

Listing 8. Listing 8. Output from running the test application
IBM WebSphere Application Server, Release 6.0
J2EE Application Client Tool
Copyright IBM Corp., 1997-2004
WSCL0012I: Processing command line arguments.
WSCL0013I: Initializing the J2EE Application Client Environment.
WSCL0035I: Initialization of the J2EE Application Client Environment has completed.
WSCL0014I: Invoking the Application Client class mediation.messages.part5.Main
Sending request message: <?xml version="1.0" encoding="utf-8"?>
<stockQuery>
  <item number="5" />
</stockQuery>
Received request message:<?xml version="1.0" encoding="UTF-8"?><stockQuery>
	<item>5</item></stockQuery>
Sending response message: <?xml version="1.0"  encoding="utf-8"?>
<stockAvailability>
  <quantity>2</quantity>
</stockAvailability>
Received response message: <?xml version="1.0" encoding="UTF-8"?>
  <stockAvailability><item
  quantity="2"/></stockAvailability>

Correlating requests and responses

So far, we have discussed a simple case where the action the response takes is dependent only on the content of the response message. There are cases where this may not be possible, such as if a request message is sent to the bus, is mediated, and then transfered to a WebSphere MQ queue manager; in this case, the reverse routing path is not likely to be maintained, but this is needed for the response to be correctly handled by the bus. Another example is in aggregating and disaggregating messages: if a single message is disaggregated into several messages and a single response is necessary, it must be known when all the responses have been received.

In these cases, it is necessary to store additional information about the request message so it can be seen by the response mediation. This is refered to as correlation. There are two simple ways of storing this correlation information so it can be used from within a mediation.

  • Use a database
  • Use a side queue.

Both mechanisms are commonly used and which one is best will depend on the specifics of the message interactions.

Correlation with a side queue

A side queue is a simple, quick, and effective mechanism for storing data, and has these advantages:

  • Simple administration.
  • The mediation API provides mechanisms for sending and receiving messages.
  • If using transactions, one-phase optimisations are possible.
  • The bus can automatically expire the data when it is no longer valid.

And these disadvantages:

  • Message selection does not perform as well as a database SQL selection, especially when the queue has a large number of messages.
  • When a side queue is localised to a clustered bus member with multiple messaging engines, care must be taken to ensure the correlation information is on the queue point accessed by the response mediation.

Correlation with a database

A database is a powerful mechanism for storing the data, and has these advantages:

  • The correlation information can be easily shared with applications.
  • A database should scale better if a lot of correlation data is stored.
  • A database should scale better if message throughput is high.

And these disadvantages:

  • Some mechanism of expiring old data may be required for lost responses.
  • When using transactions, a two-phase commit is required.
  • Requires more configuration than a side queue.

Conclusion

This article detailed how to mediate request/response interactions using the extended messaging capabilities of WebSphere Application Server V6, and discussed some of the more advanced issues involved in correlating requests and responses.


Acknowledgements

I would like to thank Daniel Murphy and David Vines for their help in writing and reviewing this article.


Download

DescriptionNameSize
Sample application filesmediationpart5.zip  ( HTTP | FTP )30 KB

Resources

Learn

Get products and technologies

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into WebSphere on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere
ArticleID=104301
ArticleTitle=IBM WebSphere Developer Technical Journal: A practical introduction to message mediation -- Part 5
publish-date=03242006