|
|
YOUR FEEDBACK
SOA World Conference
Virtualization Conference $200 Savings Expire May 16, 2008... – Register Today! Did you read today's front page stories & breaking news?
SYS-CON.TV |
TOP THREE LINKS YOU MUST CLICK ON J2EE
Message-Driven Beans and WebSphere 4.0
By: Marcel Heijmans
Digg This!
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.
Requirements 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:
The last item is added to provide the previously mentioned single EAR.
Message Monitor and Collector 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, 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) (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 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:
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.).
Conclusion 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. Resources
WEBSPHERE LATEST STORIES . . .
SUBSCRIBE TO THE WORLD'S MOST POWERFUL NEWSLETTERS SUBSCRIBE TO OUR RSS FEEDS & GET YOUR SYS-CON NEWS LIVE!
|
SYS-CON FEATURED WHITEPAPERS MOST READ THIS WEEK BREAKING WEBSPHERE NEWS
|
|||||||||||||||||||||||||||||