Subscribe to WebSphere: eMailAlertsEmail Alerts newslettersWeekly Newsletters
Get WebSphere: homepageHomepage mobileMobile rssRSS facebookFacebook twitterTwitter linkedinLinkedIn

IBM WebSphere software products Authors: Liz McMillan, Pat Romanski, Yeshim Deniz, hyper filter, Timothée Bensimon

Related Topics: Java EE Journal, WebSphere

J2EE Journal: Article

Message-Driven Beans and WebSphere 4.0

Message-Driven Beans and WebSphere 4.0

One of the major innovations in the EJB 2.0 specification, the Message-Driven Bean (MDB), is not supported by WebSphere Application Server 4.0. There are several ways to circumvent this shortcoming - you can wait for WAS 5.0, use another application server, or concoct some sort of pseudo MDB. Since the first two are rarely feasible, I'll describe the last.

The Java Message Service (JMS) provides the means for asynchronous communications via Message-Oriented Middleware (MOM). In a J2EE environment, with Enterprise JavaBeans, JMS can be used to produce messages asynchronously. However, EJBs aren't suitable for consuming messages asynchronously. The MDB provides an infrastructure for consuming JMS messages within a J2EE environment. This new EJB type (EJB 2.0) presents the same robust component-based infrastructure that session and entity beans benefit from.

WebSphere Application Server 4.0 supports the latest JMS Specification (1.02b) and is often used in combination with MQSeries 5.2.1 as its MOM. The fact that WAS 4.0 supports JMS doesn't necessarily imply that it also supports MDBs, since MDBs are part of the EJB 2.0 specification and not part of JMS.

WebSphere 4.0 does support more functionality than specified in EJB 1.1, but it lacks several important features of EJB 2.0; for example, the MDB container is not implemented in WAS 4.0. Although MDBs will be available in WAS 5.0, this shortcoming in WAS 4.0 is a nuisance.

Recently, many companies have migrated from WAS 3.5 to 4.0, IBM's mature J2EE platform. Most have invested in the development of mission-critical applications or the migration of their legacy applications to this platform. Due to these investments, the application server market is not as flexible as the desktop market, where new versions are accepted every few months. IBM realized this and came up with an intermediate solution to cope with this deficiency in WAS 4.0. This article provides a brief outline; for a thorough description of the solution, see the IBM Redbook SG24-6283-00.

The proposed solution consists of two parts: a so-called JmsMonitor, which is a queue-monitoring process outside the WebSphere Application Server, and a MessageReader, which is implemented by an ordinary stateless session bean (see Figure 1). Note that the monitor only browses the queue; it doesn't actually read the message. When a message is available on the queue, the monitor invokes the readMessage method of the MessageReader, which reads the message from the queue and invokes its onMessage. The apparent reason for this complicated method is to enable scalability by pooling and container-managed transactions.

What's wrong with this solution? Well, the system administration's having external processes isn't contributing to the maintainability of the system. IBM's solution comes from a Redbook that targets z/OS and OS/390. A solution like this is very natural in these mainframe environments because of the way processes are treated. On other platforms (AIX, Linux, NT, etc.), however, a pure WebSphere solution that can be distributed, deployed, and administered with a single EAR file is preferable. The JmsMonitor doesn't use an event-driven mechanism, it uses a one-time scan through the queue. This "batch" behavior could be extended to some sort of pooling method, but it certainly doesn't fit into an object-oriented J2EE design.

After having tried to circumvent message-driven beans altogether, I came to the conclusion that the only way to develop a high-quality application with asynchronous communications is to brew your own MDBs.

The first step in the design of an MDB surrogate is to compile a wish list of requirements the pseudo MDB should meet. As with any surrogate, resemblance to the real thing is key. WebSphere Application Server 5.0 will provide a genuine MDB as specified in EJB 2.0. A close match with the MDB will simplify migration later.

A real EJB 2.0 MDB is very easy to use; just implementing the MDB interface will suffice. The application server's MDB container handles the JMS-specific issues (connection, session, receiver, and message listener). Hence, a successful pseudo MDB must be just as easy to use.

An MDB has no home or remote interface that can be invoked by other components. The application server (the MDB container) is responsible for the creation and invocation of the MDB methods. Because of this the application server must start a pseudo MDB and invoke its onMessage method when a message is available on the queue.

Similar to other types of EJBs, MDBs are designed in such a way that they can be pooled to enable scalability and used within container-managed transactions. Again, the pseudo MDB solution must support these vital qualities to be a viable alternative.

I came up with the following rudimentary list of requirements that a pseudo MDB must meet. It must:

  • Resemble a real message-driven bean
  • Be invoked by the arrival of messages on a queue
  • Be easily used by J2EE applications
  • Be created during server startup
  • Support pooling
  • Support transactions
  • Be a pure WebSphere solution

    The last item is added to provide the previously mentioned single EAR.

    Message Monitor and Collector
    Since the number of J2EE component types is rather limited, there are only a few possible solutions for building a pseudo MDB. The only thing that will start in WebSphere 4.0 at application server startup is a servlet, and the closest you can get to an MDB is a stateless session bean. A servlet that is started by the application server and implements a MessageListener in combination with a stateless session bean, which receives the message from the servlet, would do the trick (see Figure 2). However, pooling and container-managed transactions aren't supported by this straightforward solution - this was actually a prototype to see whether this works at all. I've included the source code for this prototype servlet/EJB solution for educational purposes, but I won't elaborate on it here (source code for this article is available at www.sys-con.com/websphere/sourcec.cfm).

    The golden rule in computer science is, "A layer of indirection can solve every problem." In the final solution, the purpose of the StartMonitor servlet is solely to start a QueueMonitor stateless session bean, which contains the monitor functionality. In turn, this QueueMonitor EJB invokes another stateless session bean (QueueCollector), which serves as the pseudo MDB (see Figure 3). The code is nearly identical to that of the servlet/EJB solution; the only difference is that the monitor functionality is separated from the bootstrap mechanism.

    Only one StartMonitor servlet is necessary within WebSphere, which can bootstrap all QueueMonitor EJBs at server startup. The initialization parameters of the servlet determine which QueueMonitors should be activated (see Figure 4). Although the QueueMonitor EJBs are different beans (classes) with different home and remote interfaces, there's an EJB polymorphism technique to create different EJBs in a generic way.

    This can be done by extending all the remote interfaces of the QueueMonitor EJBs from both EJBObject and IQueueMonitor and the home interfaces from EJBHome and IQueueMonitorHome (see Figure 5). Since these are interfaces, use of multiple inheritance is allowed. The home interface looks like the following:

    public interface MyQueueMonitorHome extends EJBHome,
    IQueueMonitorHome {
    public IQueueMonitor create() throws

    The IQueueMonitor return type of the create() (which is not the regular remote interface, but its super interface) is crucial. This allows the StartMonitor servlet to create different QueueMonitor EJBs like this:

    IQueueMonitorHome queueMonitorHome = (IQueueMonitorHome)
    PortableRemoteObject.narrow(obj, IQueueMonitorHome.class);
    IQueueMonitor queueMonitor = (IQueueMonitor)

    (More details on polymorphism and EJBs can be found in the August 2002 issue of Java Developer's Journal [Vol. 7, issue 8].)

    After the StartMonitor server is started and all QueueMonitors are activated, this servlet is done.

    The QueueMonitor does most of the work. This stateless session bean handles all communication with the JMS provider (e.g., MQSeries). It connects to the JMS provider, maintains the session, creates the receiver, and implements the message listener and the exception listener. The exception listener provides the means to recover from connection failure with the MOM.

    Your QueueMonitor EJB needs to be derived from the class QueueMonitor. To let the QueueMonitor do its work, it must be initialized in the ejbCreate() and destroyed in the ejbRemove(). The combination of the StartMonitor and the QueueMonitor provides functionality similar to that of the JmsMonitor in the IBM solution (and, of course, the real MDB container). The QueueCollector is merely an empty base class that provides the pseudo-MDB characteristics. It runs in the StartMonitor/QueueMonitor environment, just like real MDBs run in the MDB container.

    The configuration of a real MDB includes a destination, which is JMS terminology for a queue. Since the deployment descriptor of a stateless session bean is very different from that of the new MDB, there is a certain limit to how well it can mimic the real thing. In order to let the QueueCollector resemble the real MDB, it will store the JMS destination in its deployment descriptor. During startup the QueueMonitor retrieves the JMS destination information from the QueueCollector by calling the startCollector() method. The QueueMonitor initializes its JMS resources with the configuration information that this method returns.

    The QueueMonitor uses the same EJB polymorphism described earlier to create the QueueCollector. Similar to the StartMonitor, the QueueMonitor stores the name of the QueueCollector in the deployment descriptor. The "queueCollector" environment variable of the QueueMonitor EJB holds the reference name of the QueueCollector EJB. The result is a rather long chain of names, references, and JNDI names, which is somewhat error-prone (see Figure 6).

    Another difference between the pseudo MDB and the real MDB is that there's no way to protect the remote interface of the session bean QueueCollector from being invoked by some other component. A real MDB doesn't have a home or remote interface. There is no adequate solution to this problem - just tell developers not to alter the remote interface of the pseudo MDB.

    The only function of the QueueMonitor is reading messages from the queue and calling the QueueCollector to process them. If there are multiple messages on the Queue and the processing in the QueueCollector takes longer than just reading from the Queue, then the QueueMonitor will create multiple QueueCollectors (depending on the configuration, of course). This also indicates that every QueueCollector (EJB) type needs its own QueueMonitor (EJB) type.

    If applicable, both stateless session beans need to take part in the same transaction. If you need some form of transactional processing in the QueueCollector, involving the QueueMonitor in the same transaction is mandatory. Otherwise, a rollback would result in loss of the message.

    Run on Server
    The environment in which MOM operates is often quite complex. The included EAR files need some configuration before they'll run on WebSphere 4.0. I use IBM MQSeries as the underlying JMS provider, which is very common in combination with WebSphere. To enable MQSeries to work with JMS, you must download the JMS Support Pac from the IBM Web site (MA88 Support Pac).

    My implementation uses LDAP for the storage of the JMS destinations. I've included the LDIF and the LDAP configuration file for OpenLDAP. More information on the administration of JMS resources (JMSadmin) can be found in the documentation that comes with the MA88 Support Pac and IBM MQSeries. I've also included a WebSphere Studio Application Developer (WSAD) server project that I used during development. The following configurations must be made to the supporting software to run the enclosed solution:

  • MQSeries must be installed and running with a Queue Manager, QM1, and Queue, Q1.
  • The JMS Support Pac (MA88) must be installed in the default MQSeries folder.
  • LDAP (OpenLDAP or IBM SecureWay) must be running with the settings according to the LDIF file.
  • The application server (or WSAD test environment) must be configured according to the svr.zip file.

    You can change the settings, but remember that there's a relationship between the deployment descriptor of the QueueCollector, the LDAP entries, the MQSeries resources, and the application server settings.

    If you experience problems while running the solution on WebSphere, check your configuration. I found that problems are usually caused by small typos in EJB references, JNDI names, or LDAP entries. Moreover, make sure that your supporting middleware is running (e.g., MQSeries QueueManager and Listener service, slapd, etc.).

    The solution described here complies with the requirements stated earlier. It simulates a real MDB to the available J2EE components in WebSphere 4.0 as closely as possible. It's very easy to use by simply inheriting from the QueueMonitor and QueueCollector class (the pseudo MDB) and configuring the beans with the deployment descriptor. The servlet bootstrap mechanism works at server startup and is a pure WebSphere solution. The combination of QueueMonitor and QueueCollector provides the means to comply with both the pooling and container-managed transaction requirements.

    The QueueMonitor and QueueCollector solution operates in the point-to-point communication domain. This means that there's a one-on-one relationship between sender and receiver. A real MDB can be configured by its deployment descriptor to operate in either the point-to-point domain or the publish-and-subscribe domain. The publish-and-subscribe domain allows multiple subscribers to receive messages by subscribing to a topic. It's easy to develop a topic-based pseudo MDB along the lines of the solution described above. Just replace queue with topic, sender with publisher, and receiver with subscriber, and you're as good as finished. A combination solution that supports both point to point and publish and subscribe like a real MDB is also possible, but it overcomplicates things and there's no substantial gain.


  • Roman, E., et al. (2001). Mastering Enterprise JavaBeans (2nd edition). John Wiley & Sons.
  • Java Message Service Documentation: http://java.sun. com/products/jms/docs.html
  • Monson-Haefel, R., et al. (2000) Java Message Service. O'Reilly.
  • IBM Redbook SG24-6283-00, "Enterprise JavaBeans for z/OS and OS/390 WebSphere Application Server 4.0." http://publib-b.boulder.ibm.com/cgi-bin/searchsite. cgi?query=SG24-6283-00
  • IBM MQSeries SC34-5456-07, "Using Java." www.ibm.com/software/mqseries
  • Lenz, B. and Musser, J. (2002). "Making Your EJBs Polymorphic." Java Developers Journal. SYS-CON Media, Inc. Vol. 7, issue 8.
  • More Stories By Marcel Heijmans

    Marcel Heijmans is a senior software engineer and founder of Mnemonics. He created the J2EE Development Coaching concept, which trains and supports novice developers and architects within their projects while minimizing the project risks.

    Comments (0)

    Share your thoughts on this story.

    Add your comment
    You must be signed in to add a comment. Sign-in | Register

    In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.