Deploying message-driven beans and JMS applications into the Service Integration Bus

The Service Integration Bus can be used as a backbone for enterprise messaging, a key component to Service-Oriented Architecture. This article shows how IBM® WebSphere® Application Server V6 makes it easy to build message buses and deploy applications, and how IBM Rational® Application Developer enables developers to create and test JMS applications that communicate using the message bus.

Share:

Roland Barcia (barcia@us.ibm.com), Consulting IT Specialist, IBM Software Services for WebSphere

Roland Barcia is a Consulting IT Specialist for IBM Software Services for WebSphere in the New York/New Jersey Metro area. He is co-author of the book IBM WebSphere: Deployment and Advanced Configuration.



Saravana R Chandran, Senior Software Consultant, IBM Software Services for WebSphere

Saravana R Chandran is a senior software consultant for IBM Software Services for WebSphere from Research Triangle Park, NC.



13 April 2005

Introduction

Over the last two years, JMS and message-driven beans (MDBs) have grown into a core J2EE™ technology, providing a foundation for building loosely coupled components into J2EE applications. JMS and messaging have become a foundation for asynchronous "service-oriented applications." The WebSphere Application Server V6 messaging platform is built on top of the Service Integration Bus (SIB), which is an implementation of an Enterprise Service Bus (ESB), a new way of connecting different applications together enabling seamless integration between components.

In this article, we will demonstrate how to deploy and test message-driven beans and JMS applications using IBM Rational Application Developer V6.0 and WebSphere Application Server V6.0, and show you how to configure the Service Integration Bus in WebSphere Application Server to support your messaging applications. In addition, we will use Rational Application Developer to examine the code and deploy the application for unit testing. While examining the code, we will highlight some updates in the JMS 1.1 and EJB 2.1 specifications.

The download file included with this article contains the materials you will need to follow along.


Import and examine a JMS and MDB application

As in the earlier article, we will use a simple "Hello" MDB example. The simplicity of the example will let us focus on the SIB configuration, although real world applications will exchange much more detailed data in the form of XML or Java™ objects, such as Service Data Objects (SDO). Rather than use the wizards to create our application, we will make things even easier and import an existing EAR file into Rational Application Developer and examine its JMS and MDB components. (Using Rational Application Developer wizards to create J2EE components is pretty straightforward and much reference material is available on this topic.)

To import the EAR file:

  1. Launch Rational Application Developer, and go to the J2EE perspective. If J2EE is not one of the choices listed, select Other => J2EE. (Eclipse 3 lazy initializes plug-ins so you may be prompted to enable J2EE support at this time.)
  2. From the main menu, select File => Import. This will launch the File Import wizard.
  3. Select EAR File, then Next.
  4. Enter the EAR file name. If you extracted the download materials to your C: drive, this would be C:\WAS6ESB\MDBTest.ear. Accept the default for the project names and ensure WebSphere Application Server v6 is selected for Target Server. Click Finish. (If you receive warnings regarding unused imports, you may ignore them. You can also disable this warning under the Java Compiler Section in the workspace preferences.)

Examining the code

The EAR file is very simple, containing only one EJB JAR inside. The EJB JAR has a stateless session bean, which is used to produce a message, and a message-driven bean used to consume a message. Figure 1 shows the Project Explorer view expanding the modules to illustrate the components.

Figure 1. EJB JAR modules and components
Figure 1. EJB JAR modules and components

We will look at the message-driven bean first, in the MyMDBBean Java file. This is a very simple message-driven bean. The onMessage() method, shown in Listing 1, just prints out the message. (As a rule, message-driven beans should have more error handling, but the code sample here is just for illustration.)

Listing 1. MyMDBBean message-driven bean
/**
	onMessage
*/
public void onMessage(javax.jms.Message msg) {
	javax.jms.TextMessage txtMsg = (javax.jms.TextMessage)msg;
	try 
	{
		System.out.println("INSIDE MESSAGE DRIVEN BEAN:  MESSAGE -> " + txtMsg.getText());
	} 
	catch (JMSException e) 
	{
		e.printStackTrace(System.out);
	}
}

Next, let's look at the stateless session bean in the MessageProducerBean Java file. This session bean uses JMS to send a message. The code is shown in Listing 2 (log messages have been removed for clarity).

Listing 2. MessageProducerBean stateless session bean
public void publishMessage(String messageString) throws Exception
	{
		try
		{
			
			InitialContext context = new InitialContext();
			ConnectionFactory cf = (ConnectionFactory)context.lookup
					("java:comp/env/jms/MyConnectionFactoryRef");
			Destination dest = (Destination)context.lookup
					("java:comp/env/jms/MyDestinationRef");
			Connection conn = cf.createConnection();
			Session jmsSession = conn.createSession(false,Session.AUTO_ACKNOWLEDGE);
			MessageProducer producer = jmsSession.createProducer(dest);
			TextMessage message = jmsSession.createTextMessage();
			message.setText(messageString);
			producer.send(message);
			producer.close();
			jmsSession.close();
			conn.close();
			
		}
		catch(Exception e)
		{
			logger.log(myLevel,ne.getLocalizedMessage(),ee);
			mySessionCtx.setRollbackOnly();
			throw e;
		}
	}

The important thing about this code is the use of the new JMS 1.1 Unified API. In previous versions of JMS, developers had to know explicitly which messaging model to use: point-to-point or publish/subscribe. Now, instead of using queues and topics directly in the code, we can use generic base classes, such as Destination, to produce the message. The messaging model is then chosen at deployment or configuration time.

Examining the deployment descriptors

To take a look at the deployment descriptor, follow these steps:

  1. Open the EJB deployment descriptor using the Deployment Descriptor editor (Figure 2).
    Figure 2. Open deployment descriptor
    Figure 2. Open deployment descriptor
  2. Go to the Bean notebook page and select MyMDB bean. The top right portion of the editor shows where the EJB deployment descriptor entries go. As you can see, the MDB Bean type is message-driven, and the EJB uses container managed transactions.
  3. There is also a section for Activity Configuration (Figure 3). Under EJB 2.1, message-driven beans use J2C 1.5 inbound connectors to bind MDBs to the application server. Under the Activity Configuration, you can indicate specific configurations for your inbound connector. For example, destination type (queue or topic) can be specified here. We do not specify this information in the example, though, because the deployment descriptor is packaged at development time. If we were to specify it, then your MDB could not be configured to work with either programming model at configuration time. Rather than specify the destination type here, we will use the configured activation specification configuration to do this.
    Figure 3. Activity configuration
    Figure 3. Activity configuration
  4. Go to the WebSphere Binding section of the deployment descriptor. In WebSphere Application Server V5, message-driven beans used listener ports for configuration binding. In Version 6, activation specifications are used. (We will configure an activation specification later.) An activation specification is configured on the server and points to a particular destination. Message-driven beans only need to specify the JNDI name of the activation specification (Figure 4). However, you are free to also specify the JNDI name of the destination, in which case, the destination name you specify in the deployment descriptor overrides the one in the activation specification. (The authorization alias name is also specified here; WebSphere Application Server security is not used in this example, but should be used in live applications.) If your Deployment Descriptor editor does not show the JCA Adapter section under the WebSphere Binding, right-click your EJB project, then select Properties => Server.
    Figure 4. WebSphere bindings
    Figure 4. WebSphere bindings
  5. Go to the Reference notebook page of the Deployment Descriptor editor. Since the session bean uses JMS JNDI objects, references are required (Figure 5).
    Figure 5. Reference notebook page
    Figure 5. Reference notebook page
  6. To defer the messaging model at configuration time, the Connection Factory reference is of type ConnectionFactory rather than QueueConnectionFactory or TopicConnectionFactory (Figure 6).
    Figure 6. Connection Factory reference type
    Figure 6. Connection Factory reference type
  7. The destination uses a new reference type introduced in J2EE 1.4 called the message destination reference (Figure 7). Here, we specify the type to be Destination rather than Queue or Topic. The message destination reference also specifies how the destination is used: to produce messages or consume them. This session bean produces messages for the destination. A message destination reference binds a bean to a resource just like any other EJB reference does, but one can also be used to specify a common destination for multiple beans in the same EAR. (See the EJB 2.1 specification, section 20.7, in Resources for more details.)
    Figure 7. Destination reference type
    Figure 7. Destination reference type

Create and configure the Service Integration Bus

Rational Application Developer includes a full base version of WebSphere Application Server V6. In this section, we will use the WebSphere Application Server administrative console to configure our bus.

A Service Integration Bus (SIB) is a logical concept. Application servers (or clusters) are members of a bus. All applications servers that are members of the same bus share a common infrastructure where applications can exchange information. Figure 8 illustrates this logical concept.

Figure 8. Service Integration Bus
Figure 8. Service Integration Bus

In actuality, all application servers that are part of the bus are collaborating to implement the bus functionality. When an application server becomes a member of a bus, it automatically gets configured with a message engine that implements bus functionality inside the application server. The collaboration of various message engines makes up the bus. Our goal is to configure an application server to support our messaging application as shown in Figure 9.

Figure 9. Service Integration Bus
Figure 9. Service Integration Bus

For publish/subscribe, the picture is a bit different, so we will leave that for another article and focus on point-to-point here.

Figure 9 shows how the message engine is part of the application server:

  • Applications are bound to JNDI objects that represent the JMS provider.
  • The JMS JNDI objects are bound to the actual objects in the message engine.
  • Destinations for point-to-point are queues.
  • A message engine has its own data source, which is uses to store persistent messages.
  • Queues are configured on individual bus members, which means they belong to a message engine.

A message engine has exclusive control of its own data store, so no other message engine can be linked to that data store. In WebSphere Application Server ND, clusters can be bus members, in which case message engines can be highly available, but again, we will focus on the simple case here and leave message clustering for another time.

We will now create our messaging infrastructure.

Create the bus

Creating the bus is rather straightforward:

  1. Start the server in the J2EE Perspective by selecting the Servers view. Right click the Server and select Start from the context Menu.
  2. When the server is started, you can either right-click on the server and select Run the Administrative Console, or use the browser with the default admin console URL: http://localhost:9060/ibm/console.
  3. Logon to the admin console with any ID, expand the Service integration tree, then select Buses (Figure 10).
    Figure 10. Service integration tree
    Figure 10. Service integration tree
  4. Click New, enter the Name as MyBus, and accept all other fields as defaults, then Apply (Figure 11).
    Figure 11. Bus configuration
    Figure 11. Bus configuration

We have now successfully created a bus, represented by Figure 12.

Figure 12. Service Integration Bus
Figure 12. Service Integration Bus

Add your application server as a bus member

We can add our server to the bus with the bus configuration screen by selecting bus members:

  1. On the Additional Properties tab, select Bus members (Figure 13).
    Figure 13. Additional properties
    Figure 13. Additional properties
  2. Select Add => Server.
  3. For Server, select <node_id>:Server1. For Data store, check Default. We can use any supported JDBC database as a data source for the message engine, but by selecting default, WebSphere Application Server will use the internal Cloudscape® database as the data source for the message engine. (Figure 14)
    Figure 14. Add a new bus member
    Figure 14. Add a new bus member
  4. Select Next, then Finish.

At this point, we have now implicitly created a message engine inside the application server (Figure 15).

Figure 15. Service Integration Bus
Figure 15. Service Integration Bus

Create a queue destination

We will now create a queue in the message engine. By doing so, we will define a messaging destination that will be available to the bus:

  1. Select your bus to display its configuration page. In the Additional Properties section under the bus configuration, select Destinations, then New.
  2. Select the destination type as Queue, then Next (Figure 16).
    Figure 16. Create new destination
    Figure 16. Create new destination
  3. In the Identifier field enter MyBusQueue, then Next (Figure 17).
    Figure 17. Create new queue
    Figure 17. Create new queue
  4. In Figure 18, we will assign the queue to a particular message engine by selecting the bus member that will host the queue. In this case, our server should be selected by default. Select Next.
    Figure 18. Assign queue to bus member
    Figure 18. Assign queue to bus member

We have now set up a queue destination inside the message engine, as shown in Figure 19.

Figure 19. Service Integration Bus
Figure 19. Service Integration Bus

Create the JMS resources

J2EE applications use JNDI as a directory service to look up application server resources by name. To support JMS applications, we need to configure JNDI with references to the JMS resources in the bus. We need to define three JMS resource references in the JNDI directory:

  • Connection factory -- used by the application to get connections to the messaging bus.
  • Queue -- used by the application to send and receive messages.
  • Activation specification -- used by the application's message-driven bean to connect to the queue and receive messages.

In the next steps, we will create these resource references and add them to JNDI:

  1. In the admin console, select Resources => JMS Providers => Default messaging (Figure 20).
    Figure 20. Default messaging
    Figure 20. Default messaging
  2. In the Connection Factories tab, select JMS connection factory (Figure 21). Notice that we use a generic JMS connection factory rather than a specific connection factory type. In JMS 1.1, both point-to-point and publish/subscribe applications can share a generic connection factory to allow a single transaction between them.
    Figure 21. JMS connection factory
    Figure 21. JMS connection factory
  3. Click New.
  4. On the Configuration Details Screen, enter or select the following values (Figure 22):
    • Name: MyConnectionFactory
    • JNDI name: jms/MyConnectionFactory
    • Bus name: MyBus
    Accept the remaining default values, then Apply and Save..

There are several configuration options available in the JMS connection factory relevant to connection pooling, message persistence, routing, transactions, and so on. Refer to the WebSphere Application Server V6 Information Center (see Resources) for more details.

Figure 22. Configuration details
Figure 22. Configuration details

Next, we will create our JMS destination:

  1. In the Destinations tab, select JMS queue (Figure 23), then New.
    Figure 23. JMS queue
    Figure 23. JMS queue
  2. On the JMS queue configuration screen, enter or select the following values (Figure 24):
    • Name: MyMDBQueue
    • JNDI name: jms/MyMDBQueue
    • Bus: MyBus (By selecting the bus, the Queue name fields automatically get populated with queue destinations for that bus.)
    • Queue name: MyBusQueue
    Accept the remaining default values, then Apply and Save.
    Figure 24. JMS queue configuration
    Figure 24. JMS queue configuration

Finally, we need to create the activation specification for the message-driven beans. The activation specification has several settings that affect the behavior of messages delivered to message-driven beans, such as the number of concurrent endpoints. Refer to the WebSphere Application Server V6 Information Center (see Resources) for details on these settings.

  1. In the Activation Specifications section, select JMS activation specification (Figure 25), then New.
    Figure 25. JMS activation specification
    Figure 25. JMS activation specification
  2. In the JMS activation specification configuration screen, enter or select the following values:
    • Name: MyActivationSpec
    • JNDI name: eis/MyMDBQueue_Act_Spec
    • Destination type: Queue
    • Destination JNDI name: jms/MyMDBQueue
    • Bus: MyBus
  3. Accept the remaining default values, then Apply and Save all the configuration changes.

We have now configured all of our JMS resources for our application to use (Figure 26).

Figure 26. Service Integration Bus
Figure 26. Service Integration Bus

Before continuing, stop and start the server from the Server view to activate the new configurations.


Deploy and test the J2EE application

There are several ways to deploy applications to WebSphere Application Server; using the administrative console or through scripting, for example. Since we are in the early stages of development and focused on unit testing, we will use Rational Application Developer to deploy the application directly. This is convenient for testing and debugging the application right from the Eclipse workbench. In addition, we can use the built-in Universal Test Client to test our EJB components.

You must configure the test server with the necessary connection factory, destination, and activation specification, as explained in the previous section, before you can test the EAR file from this article. Make sure you have done so before proceeding.

To deploy the application from Rational Application Developer:

  1. Add the application to the WebSphere Application Server test server by right-clicking on the server and selecting Add and remove projects (Figure 27).
    Figure 27. Add and remove projects
    Figure 27. Add and remove projects
  2. In the Add and Remove Projects dialog (Figure 28), select the MDBTest project, select Add, then Finish.
    Figure 28. Add and remove projects
    Figure 28. Add and remove projects
  3. If there are no errors, you have successfully deployed the application. The MDB and session bean will be bound to their respective JMS objects, as shown in Figure 29.
    Figure 29. Service Integration Bus
    Figure 29. Service Integration Bus

To test the application with the Universal Test Environment:

  1. In the Project Explorer view in the J2EE perspective, expand MDBTestEJB. Right-click on the MessageProducer session bean, then select Run => Run On Server (Figure 30).
    Figure 30. Run MessageProducer
    Figure 30. Run MessageProducer
  2. In the Server Selection dialog (Figure 31), ensure that Choose an existing server is selected and that your test server is highlighted. Also, select Set server as project default to avoid this prompt on subsequent tests. Click Finish.
    Figure 31. Define a new server
    Figure 31. Define a new server
  3. When launching the EJB test client, a wizard will pop up ask you to select the Local or Remote Interface of the EJB. Select Local.
  4. Select and invoke the create method of the bean, as shown in Figure 32.
    Figure 32. Invoke create method
    Figure 32. Invoke create method
  5. Select Work with Object on the result section, then select the object's publishMessage(String) method, as shown in Figure 33.
    Figure 33. Select publish method
    Figure 33. Select publish method
  6. In the Value field, enter text for a test message, such as Test Message, as shown in Figure 34, and press Invoke.
    Figure 34. Invoke
    Figure 34. Invoke
  7. When the method completes successfully, go to the Console view in Rational Application Developer to see that your message-driven bean successfully received the message (Figure 35).
    Figure 35. Message in Console view
    Figure 35. Message in Console view

JMS utilities in the Universal Test Client

In WebSphere Studio V5, it was necessary to explicitly create a JMS client to test your message-driven beans, as we did in this example. In Rational Application Developer V6, the Universal Test Client now has JMS utilities that enable you to send messages to a queue and post messages on a topic (Figure 36). If you wish, you can use this feature to test our sample MDB as well.

Figure 36. Universal Test Client
Figure 36. Universal Test Client

Conclusion

Messaging is a key component to Service-Oriented Architecture. With this in mind, this article showed how the Service Integration Bus can be used as a backbone for enterprise messaging, how WebSphere Application Server V6 makes it easy to build message buses and deploy applications, and how Rational Application Developer enables developers to create and test JMS applications that communicate using the message bus.


Acknowledgement

The authors wish to thank Wayne Beaton and Bobby Woolf for reviewing and improving this article.


Download

DescriptionNameSize
Download filesWAS6ESB.zip  ( HTTP | FTP )60 KB

Resources

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=85719
ArticleTitle=Deploying message-driven beans and JMS applications into the Service Integration Bus
publish-date=04132005