Skip to main content

Integrating Message-Driven Beans into Enterprise Applications with WebSphere Studio: Part 1 -- JMS and Message-Driven Beans

Ying Zhao (yingzhao@ca.ibm.com ), Software Developer , IBM Toronto Lab
Ying Zhao is currently working as a Software Developer on WebSphere Studio Application Developer at the IBM Software Solutions Toronto Lab, Canada. Ying received her Master of Science degree in Electrical Engineering at Technion - Israeli Institute of Technology in 1999. Ying is an IBM Certified Enterprise Developer, Solution Developer, XML Developer and Specialist for WebSphere Studio Application Developer. You can reach Ying at yingzhao@ca.ibm.com.
Colin Yu (coliny@ca.ibm.com ), Technical Designer , IBM Toronto Lab
Colin Yu is a Technical Designer on the WebSphere Business Scenarios team at the IBM Toronto Lab, Canada. Colin received a Bachelor of Engineering degree in 1995 and a Master of Applied Science degree from the University of Waterloo, Ontario in 2000. Colin is an IBM Certified Enterprise Developer and Systems Expert on WebSphere Application Server, and an IBM Certified Solution Developer on WebSphere Studio Application Developer and VisualAge for Java. You can reach Colin at coliny@ca.ibm.com.
Jane Fung (jcyfung@ca.ibm.com ), Software Developer, IBM Toronto Lab
Jane Fung works with the WebSphere Studio Application Developer Technical Support Team. Jane earned a Bachelor of Applied Science degree in Electrical Engineering at the University of Waterloo, Ontario, and is a Sun Java 2 Certified Programmer. She can be reached Jane at. jcyfung@ca.ibm.com.

Summary:  This article discusses JMS in detail, covering the JMS p2p and pub/sub models, then shows how a message-driven bean works and how it integrates with other J2EE components.

Date:  08 Apr 2003
Level:  Intermediate
Activity:  980 views

Introduction

Messaging systems play an increasingly important role in enterprise computing. Java™ Message Service (JMS) is the Java API that enables loosely coupled Java clients to make asynchronous interactions with messaging systems such as IBM ® WebSphere® MQ.

JMS is a low-level API that enables applications to connect to messaging systems. To simplify coding for message consumption, J2EE 1.3 introduces a new kind of enterprise bean based on the JMS API called the message-driven bean (MDB). MDBs are part of the EJB 2.0 specification, and they act as JMS message listeners in the application server container.

MDBs are fully supported by WebSphere Application Server V5 (which is J2EE 1.3 compliant). WebSphere Studio Application Developer V5 (hereafter called Application Developer) -- provides a convenient way to create MDBs and test them in the WebSphere Test Environment (WTE). The WTE has a built-in MQ Simulator that acts as a temporary JMS provider for unit testing. However, the MQ Simulator cannot be used by an actual application server, which requires a production JMS provider to be configured. Some examples of JMS providers that can be used for production are the WebSphere Embedded Messaging Server and WebSphere MQ (previously known as MQSeries). The WebSphere Embedded Messaging Server is a lightweight version that does not have as many features as WebSphere MQ. External messaging systems from other vendors can also be integrated with WebSphere Application Server as JMS providers.

A recent article discusses the creation and unit-testing of MDBs in Application Developer: Developing and Testing Message-Driven Bean Applications with the MQ Simulator for Java Developers in WebSphere Studio V5 by Sheldon Wosnick.

This article, while focusing on basics of JMS and MDBs, supplements the previous two articles. It introduces the point-to-point (queue) and publish-and-subscribe (topic) models and messages in JMS. It also shows in detail how an MDB works and how it integrates with other J2EE components, and then covers some design issues at the end of the article.


Java Message Service (JMS)

JMS is an abstraction of the interfaces and classes that enable Java messaging clients to communicate with messaging systems. Just as JDBC provides an abstract implementation to access relational database, JMS provides an abstract implementation to access messaging systems. With the help of JMS, messaging clients are portable across messaging products such as WebSphere MQ and SonicMQ.

JMS messaging models

JMS provides two types of messaging models: publish-and-subscribe (pub/sub) and point-to-point (p2p). In simple terms, pub/sub is intended for the one-to-many or many-to-many broadcast of messages, while p2p is intended for one-to-one message communication.

Publish-and-subscribe (pub/sub) model

In the pub/sub model, a messaging client (producer of the message or publisher) sends a message through a virtual channel called Topic to messaging clients (consumers of the message or subscribers) that subscribe to this topic. Every consumer receives a copy of every message automatically without having to request or poll the topic for new messages. The pub/sub model is shown in Figure 1 below. MDBs support both the pub/sub and p2p models. In the pub/sub model, MDBs act as the asynchronous subscribers. They implement the MessageListener interface, which uses the asynchronous onMessage() callback for messages arriving in the Topic. For details about the onMessage() method, see Lifecycle of MDBs. The pub/sub model also lets subscribers poll the messages synchronously with the receive() method.


Figure 1. pub/sub model
 pub/sub model

The pub/sub model supports Durable Subscription, which means that while a durable subscriber is disconnected from the JMS server, it is the responsibility of the server to store messages that the subscriber misses. The messaging server sends all if the unexpired messages it stores to the subscriber when it reconnects. MDBs support both the pub/sub and p2p models, so if an MDB subscribes to a topic, it has two options for durability: Durable or Nondurable. If Durable is selected, then when it reconnects, the MDB will get all of the messages that it missed during the disconnected period. If the JMS client is a durable subscriber, the messaging system stores the messages (method of storage is vendor-specific). The MQ Simulator does not support persistence, so after the WTE server is restarted, the messages will no longer be available, which is one of reasons why the MQ Simulator is not for production use.

Point-to-point (p2p) model

The p2p model lets the message clients send and receive messages via a virtual channel called Queue. Here is a comparison between the p2p and pub/sub models:

  1. Like the Topic in the pub/sub model, a p2p queue can either push or pull messages, depending on whether the receiver uses the asynchronous onMessage() callback or a synchronous receive() method. If a receiver uses the synchronous method to receive messages, it needs to poll the message from the queue. An MDB implements the MessageListener interface, so it uses the asynchronous onMessage() callback for messages arriving in the queue.
  2. Messages in a p2p model are consumed once by one and only one receiver, even though a queue may have many receivers. The policies of the JMS provider determine how messages delivered to a queue are distributed to the queue's receivers. Some JMS providers use load-balancing techniques to distribute messages among receivers, while others use more arbitrary policies.
  3. The clients in a p2p model have an option to browse the queue before they poll the messages from the queue.
  4. A message in the queue is durable by default, which means that the message stays on the queue until it is picked up by one consumer.

Figure 2. p2p model
p2p model

Each model has its own advantages -- the choice between them depends on your preferences and the needs of your application. If multiple MDBs listen to a queue, it is hard to predict which one will get the message, which introduces uncertainty. MDBs have their own implementation for concurrent processing (for details, see Lifecycle of MDBs). That's also why it's not a common practice to define different MDBs that listen to the same queue.

TopicConnectionFactory

The TopicConnectionFactory interface in JMS is used to manufacture connections to a Topic in the messaging system. It is a type of object whose attributes can be configured by the messaging system administrator. An MDB that works as a subscriber of a Topic binds to a Topic object and a TopicConnectionFactory object. The container invokes a method called createTopicConnection() on the TopicConnectionFactory to create a TopicConnection instance for the MDBs to communicate with the Topic.

QueueConnectionFactory

The QueueConnectionFactory interface in JMS is used to manufacture connections to a queue in the messaging system. Like the TopicConnectionFactory interface, it is a type of object whose attributes can be configured by the messaging system administrator. An MDB that acts as a receiver of a queue binds to a Queue object and a QueueConnectionFactory object. The container invokes a method called createQueueConnection() on the QueueConnectionFactory to create a QueueConnection instance for the MDBs to communicate with the Queue.

JMS message object

The JMS message object is used to encapsulate the messages that message clients send or receive. It contains three parts: headers, properties, and the message data or payload.

JMS message headers

Every JMS message has a set of standard headers including JMSDestination, JMSDeliveryMode, and so on. For more information on these headers, see the Sun JMS home page.

JMS message properties

JMS Message Properties can be used as additional headers that are assigned to a message. They provide more information about the message. The value of a property can be String, boolean, byte, double, int, long, or float.

Message selector

A message selector is not a part of the Message object, but it is related to the message headers and properties. A message selector lets a JMS consumer declare which messages it wants to receive by using message headers and properties as criteria in conditional expressions. An MDB works as a message consumer; therefore it allows the message selector definition. Message selectors are based on a subset of the SQL-92 conditional expression syntax, which is used in the WHERE clauses of SQL statements. The consumers with a simple message selector like InventoryID = 12345 will receive all messages that have a property named InventoryID with the value 12345.

Message payload

Messages come in various types depending on the payload they carry:

Message typePayload
TextMessagejava.lang.String
ObjectMessageserializable Java object
BytesMessagearray of primitive bytes
StreamMessagestream of primitive Java types (int, double, char, etc.)
MapMessageSet of name-value pairs. The values must be Java primitives or their wrappers, such as Integer.

MDBs

While JMS providers free developers from routing the messages from producers to consumers, the responsibility for implementing the JMS clients is left to developers. In many case, significant effort is needed to create the JMS client infrastructure, such as security, transaction support, and fault-tolerance. The similar infrastructure for session and entity beans is handled by the container. Therefore, EJB 2.0 introduces the message driven bean, which consumes and processes asynchronous JMS message in the same container as session and entity beans, and benefits from the infrastructure that the container provides.

Based on the JMS API, MDBs support both pub/sub and p2p models. They act as a subscriber of a topic or a receiver of a queue, which is a message listener in the asynchronous communication model.

Characteristics of MDBs

Compared to session and entity beans, MDBs have the following characteristics:

  • Like stateless session beans, MDBs do not maintain conversational state between requests. They may have instance variables throughout the life cycle, but due to the pooling of bean instances by the EJB container, the bean instances that consume the messages may be different between requests. That is why the conversational state may not be stored properly.
  • Like a stateless session bean, the EJB container maintains many bean instances of the same type in a pool. This enables concurrent message consumption and processing when several messages are delivered at the same time, which means that MDBs can deliver better performance and scalability.
  • Unlike session and entity beans, MDBs do not have remote or home interfaces. An MDB is a listener and it is not a remote process call component.
  • Unlike session and entity beans, MDBs do not expose any business methods that can be invoked by clients, such as a servlet, EJB, or Java application.
  • Like session and entity beans, MDBs must use the JMS API manually to send messages when they need to act as a message producer. However, sending messages from MDBs is not recommended -- MDBs should delegate this task to the business logic layer.

Lifecycle of MDBs

MDBs implement both the javax.ejb.MessageDrivenBean and javax.jms.MessageListener interfaces. The MessageDrivenBean interface defines the following three methods:

 
public interface MessageDrivenBean{ 
public void ejbCreate(); 
	public void ejbRemove(); 
	public void setMessageDrivenContext(MessageDrivenContext mdc); 
} 

The MessageListener interface defines the onMessage() method.

 
public interface MessageListener{ 
	public void onMessage(); 
} 

The EJB container is responsible for controlling the lifecycle of an MDB, which is summarized below:

  1. The newInstance() method is the first method called by the container to instantiate the bean.
  2. The container calls setMessageDrivenContext() and provides the MDB with an instance of MessageDrivenContext, a subclass of EJBContext with access to a container-provided run time context. For example, an MDB can obtain a UserTransaction by calling the getUserTransaction() method of the EJBContext interface.
  3. The ejbCreate() method is invoked after the setMessageDrivenContext() method and then the bean instance is added to a pool for a particular MDB and is ready to consume and process messages.
  4. When a message arrives, the bean instance is removed from the pool and its onMessage() method is invoked. When the onMessage() method returns, the bean instance is returned to the pool and is ready to process another message. It is the developer's responsibility to implement the onMessage() method that parses the messages and delegates the action to the business logic layer, such as a session bean.
  5. If the container needs to reduce the size of the pool, or if the server is shutting down, the ejbRemove() method is invoked on an instance when it is discarded.

The lifecycle of MDBs is shown in Figure 3.


Figure 3. Lifecycle of MDBs
Lifecycle of MDBs

Transaction

The container provides MDBs with the infrastructure for security. Like session and entity beans, MDBs use the Transaction Type element of the deployment descriptor to declare whether the MDB is of the bean-managed or container-managed transaction demarcation type. The application assembler can use the Transaction Attribute to manage transaction demarcation for EJBs with container-managed transaction demarcation. The transaction attribute for the MDB's onMessage() method specifies how the container must manage transactions for the method when it is invoked as a result of the arrival of a JMS message. However, the application assembler should not define transaction attributes for an MDB with bean-managed transaction demarcation.

Only the NotSupported and Required transaction attributes may be specified for an MDB, because there can be no preexisting transaction context (RequiresNew, Supports) and no client to handle exceptions (Mandatory, Never). The container invokes an MDB method whose transaction attribute is set to NotSupported with an unspecified transaction context. If the onMessage() method invokes another EJB, the container does not pass a transaction context with the invocation. The container must invoke an MDB method with the transaction attribute set to Required and with a valid transaction context.

For example, consider an MDB that invokes many EJBs in the onMessage() method. If the MDB's transaction attribute is set to NotSupported, the EJBs invoked by the MDB do not participate in a global transaction. Each EJB will commit on its own. However, if the MDB's transaction attribute is set to Required, then the EJBs invoked by the MDB will participate in the same transaction. These EJBs may commit or rollback together.

Configuring an MDB's deployment descriptor

An MDB is by definition a JMS consumer. The EJB container takes care of subscribing the bean to the desired topic or connecting it to the desired queue based on its deployment descriptor.

The following information in the deployment descriptor and its IBM extension is needed for the container to deploy the MDBs. It is application assembler's responsibility to make sure that the settings are correct according to the business needs.

Destination

A queue or a topic. An MDB either connects to a queue or subscribes to a topic. The container also needs to know how to look up the instance of the destination through the use of a JNDI name.

Connection factory

For MDBs that connect to a queue, the container needs to know how to look up the QueueConnectionFactory instance, which creates connections to the queue. For MDBs that subscribe to a topic, the container needs to know how to look up a TopicConnectionFactory instance, which creates connections to the topic.

Durability

An MDB that subscribes to a topic can choose to use durable or non-durable subscriptions with the topic. Durability is not applicable to the message receivers of a queue. For details, see Publish-and-subscribe (pub/sub) model.

Message selector

An MDB can select the messages for consumption based on their headers and properties. for details, see Message selector.

Transaction type

Includes container-managed or bean-managed transactions.

Transaction attribute

For container-managed transaction demarcation only. The value should be Required or NotSupported. For details, see Transaction.

A Queue and a QueueConnectionFactory are a pair of objects administered by the application server. The same statement applies to a Topic and a TopicConnectionFactory. WebSphere Application Server introduces a Listener Port object that simplifies the administration and associates a connection factory, a destination, and the deployed MDB. A listener port binds to a destination and connection factory pair, while an MDB binds to a listener port. Furthermore, multiple MDBs can bind to the same listener port. The association between connection factory, destination, listener port, and MDB is shown in Figure 4.


Figure 4. Association between connection factory, destination, listener port, and MDB
Association between                     connection factory, destination, listener port, and MDB

With the help of the listener port object, the deployment descriptor of an MDB does not need to specify the JNDI name of the connection factory and destination. Instead, it must specify the name of the listener port defined in the server configuration of WebSphere Application Server.


Integrating MDB into enterprise applications

MDBs offer a standard way to create a message consumer that is fully managed by the container. The bean provider can concentrate on writing the logic that performs the parsing and processing of the message. Typically, an MDB delegates the execution of business logic to some other EJB -- a session bean in most cases.

Figure 5 below shows the typical way to integrate MDBs into enterprise applications. It is easier to implement MDBs by clearly separating message and business processing. This design pattern promotes component reusability because the business logic session bean can be used by a variety of other clients, such as servlets and standalone Java applications. This programming model also reinforces the concept that the MDB acts only as an interface to the application.


Figure 5. Integrating MDB into enterprise applications
Integrating MDB into                     enterprise applications

In the above design pattern, you should consider some design decisions carefully:

  • Choosing the JMS provider. WebSphere Test Environment has a built-in MQ Simulator, a low-footprint native JMS provider that allows rapid turnaround for developers. However, it does not support inter-process communications. This means that a standalone Java application running outside the server JVM process cannot communicate with this JMS provider. Nor does it support persistent messages. Therefore MQ Simulator is not an option for a production environment, where you need an external JMS provider such as WebSphere MQ or the Embedded WebSphere Messaging Server, which comes with WebSphere Application Server and is a subset of WebSphere MQ with limited functionality. For example, the Embedded WebSphere JMS Messaging Server supports only JMS clients. For more information about WebSphere MQ, see the WebSphere MQ Web site.
  • Selecting the messaging model. The differences between the pub/sub and p2p models are discussed above in Point-to-point (p2p) model. It depends on the business scenario whether the MDB should connect to a queue or subscribe to a topic. Messages in a queue are durable until one consumer picks up a message and no other consumers can get the same copy of the message. That's why no durability option is available for an MDB that acts as a message consumer of a queue. However, you need to specify the durability property as Durable for the topic subscribers (MDB listening to the Topic) if you want the messages to be available to them after they reconnect to the topic. For details, see JMS messaging models and Configuring an MDB's deployment descriptor.
  • Deciding the communication model. An MDB acts as a message consumer that always consumes messages asynchronously. In some cases, an enterprise system needs to involve other components like servlets, session beans, or standalone Java applications that act as message producers, message consumers, or both. Figure 6 shows a business scenario involving submitting user feedback on a product to a corporate web site. The HTML feedback input form invokes a servlet, which produces a message with the destination of a JMS provider and forwards the HTTP request to a JSP, which shows the thank-you information to the user. The message is picked up by a MDB, which delegates the execution of the business logic to a session bean, which processes the feedback according to the business rules. The key point is that the user does not need to know the result of the feedback processing. In this case, having the servlet act as a message producer is an appropriate design choice.
    Figure 6. A scenario using a servlet as the message producer
    A scenario                             using a servlet as the message producer

    However, servlets and session beans cannot implement the MessageListener interface, so they cannot act as asynchronous message consumers like MDBs. As a message consumer, a servlet or session bean must poll the messages from the queue or topic with the synchronous receive() method. In the scenario above, if the servlet needs to tell the user whether the company has processed the feedback successfully as in Figure 7, it has to wait until the reply from the session bean becomes available in the queue or topic. This kind of synchronous model might hold up the user for a long time, so servlets and session beans might not be a good choice as a message consumer in this case.


    Figure 7. A scenario using a servlet as the message producer and consumer
    A scenario                             using a servlet as the message producer and consumer

    One way to work around the problem is to replace the servlet or JSP implementation with a standalone Java application that implements the MessageListener interface, as shown in Figure 8. With this asynchronous communication model, users are allowed further actions after the message is sent. Once the reply message from the company arrives in the topic or in a queue that the Java application listens to, the Java application will be notified, and its onMessage() method will be invoked to handle the message. This asynchronous model greatly improves the scalability and usability of the application.


    Figure 8. A scenario using a Java application as the message producer and consumer
    A scenario                             using a Java application as the message producer and consumer
  • Choosing the Message type. TextMessage is the most common one to use, and is compatible with other non-JMS messaging clients. XML can be encapsulated into TextMessage, which makes the parsing process easier and faster. ObjectMessage is a good choice in some cases, but it may be incompatible with some non-JMS messaging clients.
  • Using the Message Selector. A message selector will help the MDB filter out unwanted messages and lead to better performance.
  • Excluding business logic from MDBs. MDBs should delegate the action to other EJBs, typically a session bean.
  • Configuring appropriate transaction type and transaction attribute for MDBs. Bean-managed transactions are much more complex than container-managed transactions. If the business logic accesses multiple resources, such as an enterprise information system (EIS) and a database, you might want to start the transaction context from the MDBs to guarantee a unit of work.

Conclusion

MDBs are a powerful way to process inbound messages. It provides asynchronous interface to business logic and helps developers create loosely coupled applications. As a message consumer, MDBs support p2p and pub/sub models. The container takes care of the quality of service including transaction, lifecycle, connection pooling and security.


About the authors

Ying Zhao is currently working as a Software Developer on WebSphere Studio Application Developer at the IBM Software Solutions Toronto Lab, Canada. Ying received her Master of Science degree in Electrical Engineering at Technion - Israeli Institute of Technology in 1999. Ying is an IBM Certified Enterprise Developer, Solution Developer, XML Developer and Specialist for WebSphere Studio Application Developer. You can reach Ying at yingzhao@ca.ibm.com.

Colin Yu is a Technical Designer on the WebSphere Business Scenarios team at the IBM Toronto Lab, Canada. Colin received a Bachelor of Engineering degree in 1995 and a Master of Applied Science degree from the University of Waterloo, Ontario in 2000. Colin is an IBM Certified Enterprise Developer and Systems Expert on WebSphere Application Server, and an IBM Certified Solution Developer on WebSphere Studio Application Developer and VisualAge for Java. You can reach Colin at coliny@ca.ibm.com.

Jane Fung works with the WebSphere Studio Application Developer Technical Support Team. Jane earned a Bachelor of Applied Science degree in Electrical Engineering at the University of Waterloo, Ontario, and is a Sun Java 2 Certified Programmer. She can be reached Jane at. jcyfung@ca.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=13788
ArticleTitle=Integrating Message-Driven Beans into Enterprise Applications with WebSphere Studio: Part 1 -- JMS and Message-Driven Beans
publish-date=04082003
author1-email=yingzhao@ca.ibm.com
author1-email-cc=
author2-email=coliny@ca.ibm.com
author2-email-cc=
author3-email=jcyfung@ca.ibm.com
author3-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