Skip to main content

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

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

All information submitted is secure.

  • Close [x]

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.

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

All information submitted is secure.

  • Close [x]

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

Routing messages with mediations

Dan Murphy (d_murphy@uk.ibm.com), Software Engineer, IBM Hursley, UK
Author photo
Dan Murphy works in IBM Hursley in the United Kingdom. He has been with IBM for more than 11 years and is currently a test designer and developer for WebSphere Messaging. He enjoys cooking good food and collecting edible mushrooms. Dan is very much looking forward to the forthcoming Saint George's Day mushroom crop. In order to counter his gourmand eating, Dan recently resumed his martial arts training with the IBM Hursley Karate club. Dan can be reached at d_murphy@uk.ibm.com.

Summary:  Learn why and how to route messages using message mediations, including how to develop mediations that change the message routing path, and how to route cloned messages.

Date:  11 May 2005
Level:  Intermediate

Activity:  4641 views
Comments:  

Introduction

Part 1 of this article series introduced you to the basics of message mediation. You should now know why and when to use mediations, as well as how to develop, assemble, deploy, and test a simple mediation handler. In this second article, you will learn how to route messages with mediations. We will start by describing how messages can be routed without mediations, and then move on to learn how and why mediations can be used to extend this capability.

Preparation

To develop and test the mediations contained in this article, you must have installed one of the following combinations:

  • IBM® WebSphere® Application Server Toolkit Version 6.0 and IBM WebSphere Application Server V6.
  • IBM Rational® Application Developer for WebSphere Software V6, including the integrated WebSphere Application Server V6 test environment.
  • IBM Rational Application Developer for WebSphere Software V6 and WebSphere Application Server V6.
  • IBM Rational Software Architect V6.0, including the integrated WebSphere Application Server V6 test environment.

You should also download and apply the latest service levels for the products you install. At the time of writing, WebSphere Application Server V6 Refresh Pack 1 (V6.0.1) is the latest fixpack to be released. See Resources for details on WebSphere Application Server fixpacks and how to obtain them. Updates to the Rational products can be obtained using the Rational Product Updater, which is installed automatically when you install the any Rational products. Alternatively, you can manually download fixpacks from the IBM Rational Support Website

The screen images that appear in this article are from Rational Application Developer V6. If you use the WebSphere Application Server Toolkit, you can still use the steps documented here, as they are identical for both Application Developer and the toolkit. You can install the WebSphere Application Server Toolkit from the WebSphere Application Server installation media or images.

Ideally, you will have followed the previous article successfully and will have developed, deployed, and tested a mediation handler already. If you haven't read the previous article, be sure to follow the special additional steps as they are noted later in this article.


Routing messages using administered routing paths

The default messaging provider of WebSphere Application Server V6 enables destinations to have administered routing paths, providing a simple way to route messages when they are put to a destination. For the purpose of this article, we will use a simple retail example to illustrate a potential use of message routing:

  • Each store in a chain of multinational superstores interacts electronically with the head office to report transactions, order stock, and perform other business activities. The Point Of Sale (POS) terminals and other store systems communicate with head office systems using JMS messaging. For additional control and flexibility, each store uses a dedicated destination.
  • To ensure that messages are forwarded to the head office system, each store destination has an administered forward routing path defined to the central destination. In effect, the store destination acts as a "next hop" for messages as they are routed to the central destination, where they are processed by the head office system. Figure 1 illustrates this messaging topology.
    Figure 1. Logical messaging topology using routing paths to forward messages
    Logical messaging topology

Automatically routing messages between destinations can be used to enable better separation between components, services, or applications. In this example, message routing is achieved without using mediations, which leads to the question why use mediations for routing?


Routing messages with mediations

Mediations enable conditional processing of in-flight messages; by comparison, administered routing paths have no conditional element, they are applied to all messages sent to the destination. The use of administered routing paths in our example is valid because all messages need to be routed identically. If messages at the same destination need to be routed differently, then administered routes cannot be used. If you need to conditionally route messages, use mediations.

Modifying our example illustrates one reason why you may need to perform selective routing:

  • The superstore chain has developed a new version of the head office POS application that makes use of a different message format. Previously, the solution was based on JMS object messages; the new application uses XML messages that are sent using JMS text messages. The new version of the application defines a specific destination to receive messages that uses the new format. It is possible to switch all stores to the new version simultaneously, but a more practical approach is to let some or all of the stores upgrade just a few of its POS terminals to start with. Once proven reliable, the new application would then be rolled out to all terminals in all stores.

This change in the scenario gives us a simple set of requirements that we can implement using mediations: Essentially, the mediation handler will be invoked, examine the message format, and then route the message accordingly. The mediation is applied to each of the store destinations. When invoked, the mediation will route JMS text messages (which have a "JMS:text" format) to the destination defined for the new version of the POS application that processes the XML messages. Messages sent using the old "JMS:object" format will not have their routing path modified, so they will be routed to the original centralised destination.


A message routing mediation

The previous article provided detailed instructions on how to develop and test a basic mediation handler, so this time we will focus on the code for the mediation handlers. (If you have not read the first article you should consider doing so now; those basics will not be covered here.)

Mediation parameters and context properties

Making mediation handlers configurable enables them to be re-used with less difficulty; consider this a "best practice". When you assemble a mediation handler, the tooling introspects the Java™ class for fields that could be exposed as parameters for the handler. If a handler field has corresponding getter and setter methods, then it can be exposed as a parameter. The assembly wizard presents you with a list of potential parameters, from which you can then select the fields you want to expose as parameters to your mediation handler.

Simple Java primitives are defined in the deployment descriptor; you can assign values by selecting the parameter and clicking the Edit button in the mediation handlers panel. Before a mediation handler is invoked to mediate a message, the handler's parameters are set using the value defined in the deployment descriptor. Fields that reference objects can also be exposed as mediation handler parameters. These object reference parameters are exposed as resource references in the deployment descriptor which will be resolved at run time. The deployer of a mediation must ensure that resource references are mapped to appropriate objects, otherwise run time errors will occur.

To change a mediation handler's parameters you must:

  • edit the deployment descriptor
  • change the parameters
  • redeploy assembled handler.

You may want to avoid these steps by providing an override mechanism for some or all parameters. Administrators can define context properties on destinations and mediations which can be retrieved at run time using the javax.xml.rpc.handler.MessageContext reference passed to a mediation handler when it is invoked. Providing an override capability using context properties is simple, as illustrated later in our sample handlers.

We will expose some properties that control whether a message needs to be routed, and where it is routed to. The table below shows the mediation handler's properties and the effects they can have. All properties are of type java.lang.String.

Property Purpose
RouteMessageFormat The message format of messages to re-routed. This value could be hard coded, but if configurable the mediation handler is more re-useable. By default, messages with a JMS:text format are routed; this can be changed in the deployment descriptor or overridden by setting the "RouteMessageFormat" context property. (For more information on JMS message formats, see the WebSphere Application Server Information Center.
RouteMessageDestinationThe destination to which messages are re-routed.

Develop the route message mediation handler

A version of the source code for this mediation is available in a download file, which also contains an administrative script for creating a test messaging environment. You can download and import the supplied mediation code, or follow these step to create the mediation handler:

  1. Start Application Developer, using the same workspace from the previous article. If you do not have the workspace available, then:
    • Create a new Java project called MessageMediation.
    • Use the project context menu to select the project properties by right-clicking on the Java project and selecting Project Properties from the menu that appears.
    • Select the Server property, and then set the Target Server to be WebSphere Application Server Version 6.0.
  2. Using the Create Java Class wizard, add a new mediation handler class to the MessageMediation project. As shown in Figure 2, the class name is RoutingMediation , the package is mediation.handlers and it must implement the com.ibm.websphere.sib.mediation.handler.MediationHandler interface.
    Figure 2. Creating the routing mediation handler class
    Create Java class wizard image
  3. You need to add the two fields corresponding to the mediation parameters with appropriate setter and getter methods in the handler class. The mediation also logs messages using the standard Java logging APIs. Add the code shown in listing 1.

    Listing 1. Routing mediation parameters and logging references

    // Mediation parameters
        private String routeMessageFormat = "JMS:text";
        private String routeMessageDestination = "routeToQueue";
    
        // Used for logging and tracing the execution of the handler
        private String logName = "MsgMediation";
        private Logger log;
    
        public String getRouteMessageDestination() {
            return routeMessageDestination;
        }
    
        public void setRouteMessageDestination(String routeMessageDestination) {
            this.routeMessageDestination = routeMessageDestination;
        }
    
        public String getRouteMessageFormat() {
            return routeMessageFormat;
        }
    
        public void setRouteMessageFormat(String routeMessageFormat) {
            this.routeMessageFormat = routeMessageFormat;
        }
    
        private Logger getLog() {
            if (log == null) {
                log = Logger.getLogger(getLogName());
            }
            return log;
        }
    
        public String getLogName() {
            return logName;
        }
    
        public void setLogName(String logName) {
            this.logName = logName;
        }

  4. The handle(MessageContext) method is invoked when a message is to be mediated. Our handle method will delegate most of the processing to other methods, and change the existing handle() method to match that of Listing 2. We will code the required methods in a moment.

    Listing 2. Routing mediation handle() method

    public boolean handle(MessageContext msgCtx) throws MessageContextException {
            boolean contMsgProcessing = true;
    
            SIMessageContext siMsgCtx = (SIMessageContext) msgCtx;
            SIMessage msg = siMsgCtx.getSIMessage();
    
            if (shouldRouteMessage(siMsgCtx)) {
                setRoutingPath(siMsgCtx);
                getLog().log(Level.INFO, "Re-routed message {0}", msg.getApiMessageId());
            } else {
                getLog().log(Level.INFO, "Message {0} does not require re-routing", msg.getApiMessageId());
            }
            return contMsgProcessing;
        }

  5. The shouldRouteMessage(MessageContext) method decides if the message needs to be routed; if the conditions are met then true is returned. This decision is made by comparing the message format of the message to be mediated with the value configured for the mediation handler. So that the required message format can be overridden by an administrator, getRouteMessageFormat(MessageContext) is invoked. This method returns a message context property if one has been set, otherwise it returns the value of the defined mediation parameter. Both the new methods are shown in Listing 3. Add them to the mediation handler class.

    Listing 3. Checking the route message conditions

    private boolean shouldRouteMessage(SIMessageContext siMsgCtx) {
            boolean result;
            SIMessage msg = siMsgCtx.getSIMessage();
            result = msg.getFormat().equals(getRouteMessageFormat(siMsgCtx));
            return result;
        }
    
        private String getRouteMessageFormat(SIMessageContext siMsgCtx) {
            String value = (String) siMsgCtx.getProperty("routeMessageFormat");
            if ((value == null) || (value.equals(""))) {
                value = getRouteMessageFormat();
            }
            return value;
        }

  6. If the message needs to be re-routed, the setRoutingPath(SIMessageContext) method is invoked to change the message's routing path. This uses a com.ibm.websphere.sib.SIDestinationAddressFactory to look-up the destination to be used to set the forward routing. Similar to getRouteMessageFormat(MessageContext), the getRouteMessageDestination(MessageContext) method enables the destination name to be administered using context properties. Add the code shown in Listing 4 to the handler class.

    Listing 4. Modifying the message routing path

    private void setRoutingPath(SIMessageContext siMsgCtx) {
            SIMessage msg = siMsgCtx.getSIMessage();
            List frp = new ArrayList(1);
            String destName = getRouteMessageDestination(siMsgCtx); 
            SIDestinationAddress dest = SIDestinationAddressFactory.getInstance().
                createSIDestinationAddress(destName, false);
            frp.add(dest);
            msg.setForwardRoutingPath(frp);
        }
    
        private String getRouteMessageDestination(SIMessageContext siMsgCtx) {
            String value = (String) siMsgCtx.getProperty("routeMessageDestination");
            if ((value == null) || (value.equals(""))) {
                value = getRouteMessageDestination();
            }
            return value
        }

This completes the code required for our message routing mediation handler. Now it is time to assemble, deploy, and test it.


Assemble, deploy, and test the route message mediation

If you followed the previous tutorial, you only need to define this handler in the DeployableMediationEJB project that already exists. Otherwise, you will need to:

  • Create a new J2EE Enterprise Application project called DeployableMediation.
  • When creating this project, create a new EJB project called DeployableMediationEJB and add to it the existing MessageMediation project.
  • Edit the Java JAR dependencies of the DeployableMediationEJB project and add the MessageMediation project as a dependency.

Assemble the route message mediation

To assemble the mediation handler:

  1. Open the deployment descriptor for the DeployableMediationEJB project.
  2. Select the Mediation Handler tab, as shown in Figure 3.
    Figure 3. Editing the Mediation Handlers defined in the deployment descriptor
    The mediation handlers editor
  3. Add the routing mediation using the Add button, and complete the panel as shown in Figure 4.
    Figure 4. Adding the handler class to the deployment descriptor
    The add mediation handler panel
  4. Save and close the deployment descriptor. You have now assembled the mediation handler.

Deploy the route message mediation

If you followed the previous tutorial then the DeployableMediation enterprise application may still be deployed to your server. If this is the case, then you only need to ensure that the changes have been published. If the enterprise application is not deployed then follow these steps:

  1. Select your server in the Servers view of the development tool you are using. If you do not have any servers defined, right click inside the servers view and select Add and remove projects.
  2. Add the DeployableMediation project to the server.

The project should now automatically be published to the defined server. If necessary, you can force publication of the application using the server context menu.

Test the route message mediation

Before you can test the mediation handler, you need to create a test messaging configuration. The download file includes an administrative script called routingMediationAdmin.jacl, which creates:

  • Two destinations, originalQueue and routeToQueue.
  • A JMS connection factory, jms/CF2, that connects to the bus SimpleBus.
  • Two managed destinations in JNDI, called jms/originalQueue and jms/routeToQueue, and links them to the two destinations.
  • A mediation called RoutingMediation, and applies it to the originalQueue destination.

The script assumes that the bus and bus members exist. If you did not follow the previous article and do not have a bus defined, edit the script file and un-comment the included code that creates a bus: remove the # characters immediately following this comment:

# Uncomment the following section to create a messaging bus and assign the server as a member of the bus.

Execute the script using the Run external admin script context menu item of the server (Figure 5). Navigate to the routingMediationAdmin.jacl file and run it.


Figure 5. Launching an external admin script
Running an admin script

You should see messages logged similar to these:

					Create SIB Queues
$AdminTask createSIBDestination -bus SimpleBus -name originalQueue 
    -type queue -node neodogNode -server server1
$AdminTask createSIBDestination -bus SimpleBus -name routeToQueue 
    -type queue -node neodogNode -server server1
Create JMS JNDI Resources
$AdminTask createSIBJMSConnectionFactory server1(cells/neodogNode04Cell/nodes/neodogNode/servers/server1|server.xml
    #Server_1114261967144) -name CF2 -jndiName jms/CF2 -busName SimpleBus -type queue
$AdminTask createSIBJMSQueue server1(cells/neodogNode04Cell/nodes/neodogNode/servers/server1|server.xml
    #Server_1114261967144) -name originalQueue -jndiName jms/originalQueue -queueName originalQueue
$AdminTask createSIBJMSQueue server1(cells/neodogNode04Cell/nodes/neodogNode/servers/server1|server.xml
    #Server_1114261967144) -name routeToQueue -jndiNamejms/routeToQueue -queueName routeToQueue
Create and apply RoutingMediation to originalQueue
$AdminTask createSIBMediation -bus SimpleBus -mediationName RoutingMediation 
    -handlerListName RoutingMediation
$AdminTask mediateSIBDestination -bus SimpleBus -destinationName originalQueue 
    -mediationName RoutingMediation -node neodogNode -server server1
Configuration saved
				

You must restart the server for the changes to the JNDI server to take effect. Once the server has restarted, you can test the mediation using the Universal Test Client (UTC) :

  1. Launch the UTC using the server context menu item.
  2. Expand the Utilities tab and select the Send JMS Message utility.
  3. Send a message to the jms/originalQueue destination using the jms/CF2 connection factory, as shown in Figure 6.
    Figure 6. Using the UTC to send a message
    Universal test client user interface
  4. Launch the WebSphere Application Server admin console using the server context menu, and you should see a message similar to the following appear (this message will display on a single line):

    [17/04/05 14:40:13:418 BST] 0000005d MsgMediaiton I Routing message ID:
       8fa289e1aff0dd0876a80a48110a134f0000000000000001
    


  5. Log in and expand the Service Integration tab.
  6. Select Buses => SimpleBus => Destinations => routeToQueue => Queue points, and select the queue point shown.
  7. When the panel displays, select the Runtime tab.
  8. Locate the Current Message depth, which should now be 1. In conjunction with the log entries, this indicates that the message you sent to originalQueue has been routed to the routeToQueue destination.

Optionally, you can follow these steps to prove that the message has been routed:

  • Browse the queue by selecting Messages.
  • Select the message from this displayed table.
  • The message identifier written to the log by the mediation should match the API message identifier of the message on this destination.

Trace the downloaded mediation handlers

The download version of the mediation handlers contain additional trace and debug statements. Using the standard Java logging interfaces, the handler writes log entries to trace its execution path. To see the trace entries, enable tracing in the application server. By default, the name of the logger used by all the sample mediations is MsgMediation. To enable tracing using the administrative console:

  1. Expand the Troubleshooting tab.
  2. Select Logging and Tracing => server1 => Change Log Detail Levels.
  3. Wait for the the screen refresh to complete, then change the log level to *=info: MsgMediation=all.
  4. Restart the server. A trace file, called trace.log will be created in the server's log directory.
  5. Send another message to the originalQueue destination. The mediation will write additional messages to the trace log file, which can be used for debugging. (The sample code illustrates how you can add trace and log to your own applications. For more information on log and trace see Resources.)

Send cloned messages with mediations

When developing or integrating applications with messaging, you may want to capture a flow of messages. Alternatively, you may be required to send copies of messages to another destination for auditing purposes or other reasons. Mediation handlers can send messages using the SIMediationSession, obtained by invoking the getSession() method on the handler's SIMessageContext reference. SIMessage messages implement the java.lang.Cloneable interface, enabling mediations to clone and then send the cloned message to another destination. Let's extend our example to illustrate why and how mediations can be used for this purpose.

While the new POS application goes through final testing, a copy of all messages needs to be captured to verify that all messages sent to the new application are correctly processed. In addition, this lets you examine the contents of any messages that fail to be processed.

Again, the mediation handler needs to be configurable so that administrators can define some of the properties that control the creation and routing of cloned messages. The following table shows the mediation handlers' parameters and their purpose; all parameters are of type java.lang.String:

Name Purpose
CloneMessageDestinationDestination to which cloned messages are sent.
ExistingRouteAction Controls what action to take if the message has an existing routing path. Possible values are PREPEND, APPEND and OVERWRITE (default).
CloneMessagePropertyName The name of the boolean property to set on a cloned message. Setting this property prevents cloning cloned messages.

Develop the send clone mediation handler

As with the earlier mediation handler, the source code for this one can also be downloaded, and contains trace and debug statements. The download file also contains an administrative script to create the required test environment. To develop the send clone mediation handler:

  1. Create a new mediation handler class, mediation.handlers.SendCloneMediation that implements the com.ibm.websphere.sib.mediation.handler.MediationHandler.
  2. Add the mediation parameters with the appropriate "setters and getters" and logging references to the class, as shown in Listing 5.

    Listing 5. Mediation parameters and logging references

    // Mediation parameters
        private String cloneMessageDestination = "clonedMsgQueue";
        private String existingRouteAction = "OVERWRITE";
        private String cloneMessagePropertyName = "messageCloned";
    
        // Used for logging and tracing the execution of the handler
        private String logName = "MsgMediation";
        private Logger log;
    
        private Logger getLog() {
            if (log == null) {
                log = Logger.getLogger(getLogName());
            }
            return log;
        }
    
        public String getCloneMessageDestination() {
            return cloneMessageDestination;
        }
    
        public void setCloneMessageDestination(String cloneMessageDestination) {
            this.cloneMessageDestination = cloneMessageDestination;
        }
    
        public String getCloneMessagePropertyName() {
            return cloneMessagePropertyName;
        }
    
        public void setCloneMessagePropertyName(String cloneMessagePropertyName) {
            this.cloneMessagePropertyName = cloneMessagePropertyName;
        }
    
        public String getExistingRouteAction() {
            return existingRouteAction;
        }
    
        public void setExistingRouteAction(String existingRouteAction) {
            this.existingRouteAction = existingRouteAction;
        }
    
        public String getLogName() {
            return logName;
        }
    
        public void setLogName(String logName) {
            this.logName = logName;
        }

  3. The mediation framework will invoke the handle() method of the handler. This method checks to see if the message should be cloned, using the shouldSendClone() method. If the value returned is true, then a clone of the message is sent using the sendClone() method. Modify the generated handle() method, as shown in Listing 6.

    Listing 6. The send clone handle() method

    public boolean handle(MessageContext ctx) throws MessageContextException {
            boolean contMsgProcessing = true;
            SIMessageContext siCtx = (SIMessageContext) ctx;
    
            if (shouldSendClone(siCtx)) {
                sendClone(siCtx);
            }
            return contMsgProcessing;
        }

  4. The shouldSendClone() method is invoked to check if a message should be cloned. The cloned message property is checked first to make sure that we don't clone cloned messages. We then make sure that the mediation is not being invoked on the same destination that it was configured to send cloned messages to. These two checks ensure that the mediation does not trigger a "message storm" from simple configuration errors. The CloneMessagePropertyName can be overridden by an administrator. The getCloneMessagePropertyName(SIMessageContext ctx) method is used to check and use the context property if it is set. Add the code in Listing 7 to the mediation handler:

    Listing 7. The shouldSendClone(SIMessageContext) code

    private boolean shouldSendClone(SIMessageContext ctx) {
            boolean sendClone = true;
            SIMessage msg = ctx.getSIMessage();
            try {
    	        Boolean clonedMsgProperty;
                String clonePropName = getCloneMessagePropertyName(ctx);
                clonedMsgProperty = (Boolean) msg.getUserProperty(clonePropName);
                if ((clonedMsgProperty != null) && clonedMsgProperty.booleanValue()) {
                    sendClone = false;
            	}
            } catch (Exception e) {
                getLog().log(Level.SEVERE, "Exception getting message property: " + getCloneMessagePropertyName(ctx), e);
            }
            String mediationDest = ctx.getSession().getDestinationName();
            if (getCloneMessageDestination(ctx).equals(mediationDest)) {
    			sendClone = false;
            }
            return sendClone;
        }
    
        private String getCloneMessagePropertyName(SIMessageContext ctx) {
            String value = (String) ctx.getProperty("cloneMessagePropertyName");
            if ((value == null) || (value.equals(""))) {
                value = getCloneMessagePropertyName();
            }
            return value
        }

  5. If the message needs to be cloned, the handler invokes the sendClone() method, which is responsible for cloning the message and sending the clone to the configured destination, and then delegates setting the cloned messages routing path to the setRoutingPath(clone, ctx) method. This method also sets a message property to indicate that the message is a clone. Add the code in Listing 8 to the handler:

    Listing 8. The sendClone(SIMessageContext) code

    private void sendClone(SIMessageContext ctx) {
            SIMediationSession session = ctx.getSession();
            SIMessage clone = null;
    
            try {
                clone = (SIMessage) ctx.getSIMessage().clone();
                setRoutingPath(clone, ctx);
                clone.setUserProperty(getCloneMessagePropertyName(ctx), Boolean.TRUE);
                session.send(clone, false);
                getLog().log(Level.INFO, "Message {0} cloned and routed to {1}",
                             new Object[] { clone.getApiMessageId(), clone.getForwardRoutingPath() } );
            } catch (Exception e) {
                getLog().log(Level.SEVERE, "An exception occurred sending the cloned message", e);
            }
        }

  6. You now need to add the setRoutingPath(SIMessage, SIMessageContext) and its dependencies. The setRoutingPath() method modifies any existing routing path according to the ExistingRouteAction property. Add the code in Listing 9 to the handler:

    Listing 9. Setting the cloned message's routing path

    private void setRoutingPath(SIMessage clone, SIMessageContext ctx) {
            List frp = clone.getForwardRoutingPath();
    		String destName = getCloneMessageDestination(ctx);
    		SIDestinationAddress dest = SIDestinationAddressFactory.getInstance().
    		     createSIDestinationAddress(destName, false);
            if ((frp.isEmpty()) || (getExistingRouteAction().equalsIgnoreCase("OVERWRITE"))) {
                List newFrp = new ArrayList(1);
                newFrp.add(dest);
                clone.setForwardRoutingPath(newFrp);
            } else {
                if (getExistingRouteAction().equalsIgnoreCase("APPEND")) {
                    frp.add(dest);
                } else {
                    frp.add(0, dest);
                }
                clone.setForwardRoutingPath(frp);
            }
        }
    
        private String getCloneMessageDestination(SIMessageContext ctx) {
            String value = (String) ctx.getProperty("cloneMessageDestination");
            if ((value == null) || (value.equals(""))) {
                value = getCloneMessageDestination();
            }
            return value;
        }

You can now assemble, deploy and test this new mediation handler.

Assemble, deploy and test the send clone mediation

To assemble the mediation:

  1. Open the deployment descriptor for the DeployableMediationEJB project.
  2. Select the Mediation Handlers tab (Figure 7) and add a new mediation using the Add button.
    Figure 7. Adding the send clone mediation
    Send clone mediation
  3. Save the deployment descriptor

Assuming the server is still running and DeployableMediation is deployed, your changes should be published automatically. If necessary, start the server and publish the changes.

To test the mediation, you need to define some messaging resources . (An administrative script is included in the download file.) Run the sendCloneMediationAdmin.jacl script to set up the following configuration:

  • Two destinations, called messageQueue and clonedMsgQueue.
  • Three JMS resources, called jms/messageQueue , jms/clonedMsgQueue and jms/CF3.
  • A mediation called SendCloneMediaiton , applied to messageQueue.

Restart the application server, launch the UTC, and send a test message to the jms/messageQueue. If the mediation handler is invoked successfully, the result will be a clone of the message being set to the clonedMsgQueue destination. This can be verified by checking the server log entries and by using the administrative console to browse the two queue points. You should see an entry similar to the following (this message will display on a single line):

[17/04/05 15:54:00:912 BST] 0000005e MsgMediaiton I Message ID:
   ee5d090dc9dc751359fe3936110a134f0000000000000001 cloned and sent to [[ clonedMsgQueue, false, null, ]]


Conclusion

The goal of this article was to demonstrate message routing using mediation handlers. First, we saw how how to modify the route of a message, enabling it to be delivered to a different destination. Second, we saw how to develop mediation handlers that copy messages from one destination to another. By following these examples, you will have gained more experience with assembling, deploying, and testing mediations and message-based solutions.

The next article in this series is concerned with accessing message payloads, which enable you to process messages based on their content. We will extend the DebugMediation to output the message contents, and develop a simple mediation that modifies the content of messages.


Acknowledgements

Once again, I would like to thank my colleagues Alasdair Nottingham and Dave Vines for helping with the review of this article. (I hope it was easier this time around.)



Download

NameSizeDownload method
mediatingMessages2.zip9 KBFTP|HTTP

Information about download methods


Resources

About the author

Author photo

Dan Murphy works in IBM Hursley in the United Kingdom. He has been with IBM for more than 11 years and is currently a test designer and developer for WebSphere Messaging. He enjoys cooking good food and collecting edible mushrooms. Dan is very much looking forward to the forthcoming Saint George's Day mushroom crop. In order to counter his gourmand eating, Dan recently resumed his martial arts training with the IBM Hursley Karate club. Dan can be reached at d_murphy@uk.ibm.com.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


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. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

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.

(Must be between 3 – 31 characters.)

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

 


Rate this article

Comments

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere
ArticleID=86248
ArticleTitle=IBM WebSphere Developer Technical Journal: A practical introduction to message mediation -- Part 2
publish-date=05112005
author1-email=d_murphy@uk.ibm.com
author1-email-cc=Copy email address