Skip to main content

IBM WebSphere Developer Technical Journal: Interfacing WebSphere Extended Messaging with Existing Message Applications

Vernon Green (vernon_green@uk.ibm.com), WebSphere Development, IBM
Vernon Green is a Senior Software Engineer working at IBM on WebSphere Application Server development, based in Hursley, UK. Vernon is an architect and developer responsible for developing function within the application server, and has vast experience developing middleware software for a distributed environment. Vern can be contacted at vernon_green@uk.ibm.com.

Summary:  This article shows you how to use the Extended Messaging Service (EMS) of WebSphere Application Server V5 to interface with existing messaging applications in cases where the message format is already defined and the internal Extended Messaging format is not suitable. This will enable new applications to use the tooling and run-time artifacts provided by Extended Messaging, as well as exchange messages with existing applications that cannot have their message formats modified.

Date:  19 Jan 2004
Level:  Introductory
Activity:  223 views

Introduction

Extended Messaging Service (EMS) is a feature of WebSphere Application Server Enterprise Edition Version 5 (Application Server). EMS provides a simplified programming model based on the Enterprise Java Beans (EJB) programming model to handle incoming messages and their replies. EMS can also handle outgoing messages and provide correlation of responses. You can enable this function using common messaging patterns, which can be combined for different business scenarios. These message patterns are implemented using a private message format based on Java Message Service (JMS) stream messages.

This works well if Extended Messaging is enabled at each end to send and receive messages it has created. However, when you integrate applications so that there is an existing messaging application at one end and an Extended Messaging application at the other, you need to change the EMS message formats to enable them to exchange messages.

This paper describes how to replace the default formatter and parser supplied with Extended Messaging with a customized, user-written formatter and parser. To illustrate the steps, we'll build a simple application sender bean, as well as a simple formatter and parser to handle the message content. In addition, we'll explain the necessary modifications to the sender bean in order to use the new formatter and parser. The sender bean described in this paper is built using WebSphere Studio Application Developer Integration Edition Version 5 (Application Developer).

This paper assumes a basic knowledge of Extended Messaging, as well as a basic working knowledge of JMS.


Sample Application

To explain how this all works let's look at a simple application scenario. Consider we have an existing message serving application that receives a request in the form of a customer number and sends a reply that contains the customer name. This is a greatly simplified application, and to keep things simple, we'll assume that all the data is handled in text format. We need to be able to send messages to the existing application and receive responses by using Extended Messaging to bridge between the client and the existing messaging application.


Figure 1. Sample application
Figure 1. Sample application

Figure 1 shows the parts that make up our sample application. Working left to right across the figure we have:

Client
Calls a sender bean, passing in the customer number. In our example, the client will wait for the sender bean to return the customer name from the response message.
Sender Bean
Takes the input from the client in the form of a single string containing the customer number. It then formats a JMS message, which it writes to message queue Q1. The sender bean also handles retrieving the response from queue Q2. For responses, the bean reads the message from the queue, and then parses the message to extract the response string. The sender bean would typically be called as follows:
     customerName = sb.getCustomerName(custID);
     

Existing messaging application
Retrieves message requests from queue Q1 and, for each message it receives, sends a response to queue Q2. In our simple example, it will send the customer name in response to the request containing the customer number.

Building the Extended Messaging Service Components

To build a simple sender bean and change the standard formatter and parser used by Extended Messaging, we'll do the following steps:

  1. Create a sender bean to handle the request and response.
  2. Create a formatter to construct a JMS text message.
  3. Create a parser to interpret the JMS text message and return the response.
  4. Connect it all together by modifying the sender bean to use the new formatter and parser.

Step 1. Creating the Sender bean

In this step, we'll create the EJB project and EMS sender bean. We'll use the EMS wizard to create the sender bean.

  1. Launch the Application Developer.
  2. Select Window => Open perspective => J2EE to enter the J2EE perspective. If J2EE is not one of the listed options, select Other => J2EE.
  3. Select File => New => EJB Project. Then select Create EJB 2.0 project, and then Next.
  4. Enter the following values in the dialog (Figure 2):
    • Project name: Sender
    • Enterprise application project: New
    • New project name: emsText
  5. Click Finish.
    Figure 2. Create EJB project
    Figure 2. Create EJB project
  6. Select File => New => Other then select Extended Messaging => Create Sender Bean, and click Next.
  7. Select Sender from the EJB project drop-down list.
  8. Click Create sender to start the Create Sender wizard (Figure 3).
  9. Enter the following values in the next dialog:
    • Bean name: Sender
    • Default package: emsText

    Figure 3. Create an Enterprise bean
    Figure 3. Create an Enterprise Bean
  10. Click Next, then Finish. You'll return to the Create Sender bean wizard.
  11. Now enter the following values, as shown in Figure 4.
    • Output port JNDI name: oPort
    • Response Information: Response
    • Data Mapping: Extended Messaging data mapping
    • Message format identifier: TextMessage

      The value specified in the Message format identifier field, which is used to set the JMS Message header field, JMSType, is used by the Extended Messaging receiver bean to identify the inbound message. It is not used by the sender bean to correlate responses. In our case, because the message is not received by a receiver bean but by an existing messaging application, the value specified is not as important as it would normally be.

  12. Click Next.
    Figure 4. Create Sender Bean
    Figure 4. Create Sender Bean
  13. The Sender response dialog is displayed (Figure 5). Enter the following values:
    • Response timeout option: No timeout
    • Method name: getCustomerName
  14. Select Add to remote interface to promote the newly generated method to the remote interface of the sender bean. This enables it to be called by the client.
  15. Click Next.
    Figure 5. Send with response methods
    Figure 5. Send with response methods

    Now we need to specify the data mapping option. In this example, we're going to define the method signature explicitly, by typing the parameters and return values for the sending method (that is, the object types to be sent and what you expect back as a response).

  16. Select Define method signature, then click Next.
  17. In the Define the sending method signature dialog (Figure 6), enter the following values:
    • Return Type: String
    • Parameter List: String custID
  18. Click Next.
    Figure 6. Define the sending method signature
    Figure 6. Define the sending method signature
  19. The summary screen (Figure 7) is presented. Check that all values have been entered correctly, then click Finish.
    Figure 7. Summary screen
    Figure 7. Summary screen

    When the wizard completes, the sender bean is generated, including the getCustomerName() method, which is also added to the remote interface. A resource reference for the output port and its WebSphere binding are also created. Listing 1 shows the code generated for the getCustomerName() method in sender bean Sender. We'll refer back to this later.


    Listing 1. Sender bean generated code for method getCustomerName()
    							
    
    1.	public String getCustomerName(String custID) throws CMMException
    2.	{
    3.	    //	Create sender
    4.	    CMMSender sender = CMMFactory.createSender("ems/oPort");
    5.	    try {
    6.	        //	Create message factory
    7.	        MessageFactory factory = sender.getMessageFactory();
    8.	        //	Create formatter
    9.	        CMMFormatter  formatter = CMMFactory.createCMMFormatter(factory);
    10.	        //	Add parameters to the message
    11.	        formatter.addStringParameter(custID);
    12.	        //	Get the message
    13.	        Object request = formatter.getMessage();
    14.	        //	Set message type
    15.	        sender.setRequestMessageType("TextMessage");
    16.	        //	Send request receive response
    17.	        Object response = sender.sendRequestReceiveResponse(request);
    18.	        //	Create parser
    19.	        CMMParser  parser = CMMFactory.createCMMParser(response);
    20.	        //	Process exception
    21.	        if (parser.containsException()){
    22.	            try{
    23.	                throw parser.getException();
    24.	            }
    25.	            catch(CMMException exc){ throw exc;}
    26.	            catch(Exception exc){ throw  new CMMException("Unexpected Exception", exc);}
    27.	        }
    28.	        //	Extract response and return
    29.	        return parser.getStringParameter();
    30.	    }
    31.	    finally
    32.	    {
    33.	        sender.close();
    34.	    }
    35.	}
    

Step 2. Creating a formatter

Now that we've created the sender bean, the next step is to create the new formatter that the bean will use. If we look at the code generated in the sender bean for the getCustomerName() method, we can see that the sender bean performs three interactions with the formatter to:

  1. Create the formatter, which in turn creates the JMS message. See line 9 in the sender method code above.
  2. Add the parameters that were passed to the sender bean to the message by invoking the addStringParameter() method. See line 11.
  3. Retrieve the formatted JMS message by calling the getMessage() method. See line 13.

To keep this simple we'll assume that all the data is handled in text format, and the JMS messages will use TextMessage format.

We need to create a Java class in Application Developer, called FormatText, which for simplicity is added to the emsText package that contains the sender bean.

In the next steps, we'll create the Java class.

  1. In the J2EE Navigator view in Application Developer, expand the Sender project folder, and select the package emsText.
  2. Select New => Class.
  3. Enter the following value in the Java Class dialog: Name: FormatText.
  4. Click Finish.

Replace the skeleton code in the FormatText.java class file with the code shown in Listing 2, which implements a simple formatter that handles String parameters, and then save the file. The lines are described after the code.


Listing 2. Code for formatter FormatText
					

1.	package emsText;

2.	import javax.jms.TextMessage;
3.	import javax.jms.JMSException;
4.	import com.ibm.websphere.ems.CMMException;
5.	import com.ibm.ws.spi.ems.transport.MessageFactory;
6.	import com.ibm.ws.spi.ems.format.Formatter;

7.	public class FormatText implements Formatter {

8.	   private String         msgText = null;
9.	   private TextMessage    message;	

10.	   public FormatText(MessageFactory factory) throws CMMException
11.	   { 
12.	      message = (TextMessage)factory.createMessage("javax.jms.TextMessage");
13.	   }

14.	   public void addStringParameter(String s) 
15.	   {
16.	      if (msgText == null) 
17.	      {
18.	         msgText = s;
19.	      }	
20.	      else
21.	      {
22.	         msgText = msgText + s;	
23.	      }	    
24.	   }			

25.	   public Object getMessage() throws CMMException
26.	   {
27.	      try
28.	      {
29.	         message.setText(msgText);
30.	      }
31.	      catch (JMSException exc)
32.	      {
33.	         System.out.println("JMS Exception " + exc);
34.	         throw new CMMException("Format error, reason: ", exc);
35.	      }
36.	      msgText = null;	
37.	      return message;
38.	   }	

39.	   public void setException(Exception exc) throws CMMException
40.	   {
41.	   }	

42.	}


Line number Comments
1Define the package name you are going to use, emsText.
2 - 6Define the JMS and Extended Messaging classes required in the formatter.
7Name the class FormatText. The Formatter interface requires that methods getMessage() and setException() are implemented.
8 - 9Define the variables required to build up the JMS message.
10 - 13Define the constructor method. The constructor is passed an Extended Messaging factory object, which is then used by the formatter to create the JMS message. The parameter passed to the createMessage() method, in this case, javax.jms.TextMessage, defines the type of JMS message that is created. Other JMS message types could be created by passing in the appropriate string.
14 - 24 Define the addStringParameter() method. Each String parameter passed to the sender bean is passed, in turn, to the addStringParameter() method in the formatter. This method simply concatenates the strings together to form a single string, which will be set in the JMS message when complete.
25 - 38Define the getMessage() method. This method is called by the sender bean when all parameters passed to the sender bean have been passed to the formatter via the addStringParameter() method. The try block is used to add the string to the JMS message. Should a JMS error be raised, then the catch block reports the error to the log file and throws an Extended Messaging exception. Finally, the saved message is set to null and the JMS message is returned to the sender bean.
39 - 41Define the setException() method. This method is used to set an exception into the message if an error occurs. In this example, the sender bean does not call the method.

In this example, we have deliberately assumed that only String objects would be passed to the formatter. As sender beans can accept a number of different parameter types, they can be generated with different addXxxxParameter methods, where Xxxx depends upon the data type. For example, if an int data type had been defined as one of the parameters to the sender bean, then an addIntParameter() method call would have been generated in the sender bean, which the formatter would have to handle. You only need to define the addXxxxParameter methods in the formatter when they are generated within the sender bean.

Step 3. Creating a parser

The next step, since we are expecting to receive a response to our request, is to create a parser to handle the response. Again, if we look at the code that was generated to handle the response in the sender bean getCustomerName() method, we can see there are four interactions between the sender bean and the parser to:

  • Create the parser and pass the response JMS message. See line 19 in Listing 1 above.
  • Check whether any exception was returned in the response message by invoking the containsException() method. See line 21.
  • Retrieve the exception, if one was returned, by calling the getException() method. See line 23.
  • Get the values from the JMS message by calling the getStringParameter() method. See line 29.

Next we need to create a Java class in Application Developer, called ParseText, which for simplicity we will add to the emsText package that contains the sender bean and FormatText class.

In this section, we'll create the Java class ParseText.

  1. In the J2EE Navigator view in Application Developer, expand the Sender project folder and select the package emsText.
  2. Select New => Class.
  3. Enter the following in the Java Class dialog:
    Name: ParseText.
  4. Click Finish .
  5. Replace the skeleton code in the ParseText.java class file with the code shown in Listing 3, which implements a simple parser that handles a String response, and then save the file. The lines are described after the code.
    Listing 3. Code for parser ParseText
    							
    		
    1.	package emsText;
    2.	import javax.jms.TextMessage;
    3.	import javax.jms.JMSException;
    4.	import com.ibm.websphere.ems.CMMException;
    5.	import com.ibm.websphere.ems.FormatException;
    6.	import com.ibm.ws.spi.ems.format.Parser;
    
    7.	public class ParseText implements Parser {
    
    8.	   private TextMessage message;
    
    9.	   public ParseText(Object message) throws FormatException
    10.	   {
    11.	      if (message instanceof TextMessage)
    12.	      {
    13.	         this.message = (TextMessage)message;
    14.	      }
    15.	      else
    16.	      {
    17.	         throw new FormatException("Unsupported message type");
    18.	      }
    19.	   }
    
    20.	   public String getStringParameter() throws CMMException
    21.	   {
    22.	      String parameter = null;
    23.	      try
    24.	      {
    25.	         parameter = this.message.getText();
    26.	      }
    27.	      catch (JMSException exc)
    28.	      {
    29.	         System.out.println("JMS Exception " + exc);
    30.	         throw new CMMException("Error parsing message: ", exc);
    31.	      }
    32.	      return (parameter);
    33.	   }	
    
    34.	   public boolean containsException()
    35.	   {
    36.	      return (false);
    37.	   }
    
    38.	   public Exception getException()
    39.	   {
    40.	      return null;
    41.	   }		
    
    42.	
    
    

    Line number Comments
    1Define the package name you are going to use, emsText.
    2 - 6Define the JMS and Extended Messaging classes needed in the parser.
    7Name the class, ParseText. The parser interface requires that methods containsException() and getException() are implemented.
    8Define the variable used to save the JMS message passed in on the constructor method.
    9 - 19Define the constructor method. The constructor is passed the response JMS message. The message is checked to determine its type is a TextMessage. If so, it is saved in the defined variable message. If the type is not supported then a FormatException is thrown.
    20 - 33Define the getStringParameter() method. The parser returns the whole text message from the JMS message when this method is called. If a JMS exception occurs, it is reported, and a new Extended Messaging exception is thrown.
    34 - 37Define the containsException() method. With Extended Messaging, the response message that is retrieved may contain details of an exception that occurred at the remote end when the reply was constructed. In our case, the remote end is not an application exploiting Extended Messaging and, therefore, we cannot get any exception returned. This method always returns false.
    38 - 41Define the getException() method. This method returns details of the exception received in the response. As the containsException() method always returns false, this method will never be called. It returns a null exception.

    To keep it simple, we'll make the assumption in the parser code that the response will be returned as a single String. When the sender bean is generated it could generate method calls other than getStringParameter. For example, it could generate a getIntParameter if the return type had been specified as an int data type. If that had been the case then the parser would have to provide the additional method and handle the data.

Step 4. Connecting the pieces together

Now that we've defined the sender bean, formatter, and parser, all that remains is to modify the sender bean to use the new formatter and parser.

Replacing the standard formatter in the sender bean

In method getCustomerName() of the sender bean (Listing 1), we need to change line 9, which creates the formatter. Find the following lines:


 8.     // Create formatter 
 9.     CMMFormatter formatter = CMMFactory.createCMMFormatter(factory);

		

Change line 9 to:


9.     FormatText formatter = new FormatText(factory);

		

Replacing the standard parser in the sender bean

In method getCustomerName() of the sender bean (Listing 1), we need to change line 19, which creates the parser. Find the following lines:


18.     // Create parser
19.     CMMParser parser = CMMFactory.createCMMParser(response);

		

Change line 19 to:

19.     ParseText parser = new ParseText(response);
		

Next save all the files and build the project by selecting Project => Rebuild All.

Now that we've developed our sender bean with its new formatter and parser, all that remains is to test it against the existing messaging system.


Conclusion

This paper has demonstrated how you can exploit Extended Messaging to interface with existing messaging applications, where the message format is already defined and the internal Extended Messaging format is not suitable. This enables new applications to make use of the tooling and run-time artifacts that Extended Messaging provides, and to exchange messages with existing applications that cannot have their message formats modified.


Resources

Simplify Applications by Using WebSphere Extended Messaging.
This article provides an overview and description of Extended Messaging and how it can be used to simplify applications.
Creating Extended Messaging Applications for WebSphere Application Server Enterprise
This article provides a tutorial that describes building and testing a sender-receiver EMS application.

About the author

Vernon Green is a Senior Software Engineer working at IBM on WebSphere Application Server development, based in Hursley, UK. Vernon is an architect and developer responsible for developing function within the application server, and has vast experience developing middleware software for a distributed environment. Vern can be contacted at vernon_green@uk.ibm.com.

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=14108
ArticleTitle=IBM WebSphere Developer Technical Journal: Interfacing WebSphere Extended Messaging with Existing Message Applications
publish-date=01192004
author1-email=vernon_green@uk.ibm.com
author1-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).

Rate a product. Write a review.

Special offers