This document explains how the power of EJBs can be leveraged using asynchronous Java Messaging technology. The document explains the limitations inherent in the EJB architecture and illustrates how (if you can't wait until EJB 2.0) you can use any JMS implementation to provide support for asynchronous EJB method invocation. In particular, the example code shows how this can be achieved using Fiorano's implementation of JMS. The reader is expected to be familiar with the basic concepts and working of JMS and EJB.
Limitation of Enterprise Java Beans
EJBs do not provide for an asynchronous method invocation for the following reasons:
- EJBs do not run as a daemon service. EJBs are server-side reusable components can be passivated and put back into the container's available pool whenever they time-out or when there are no more active references to the bean.
- EJBs can be accessed only through a remote interface. An EJB cannot be made to receive a JMS Message asynchronously since this results in the invocation of the Bean methods directly. By definition, an EJB can only be accessed through its remote interface. The EJB's container is responsible for managing and invoking all calls on the Bean. Since the EJB container manages transactions as well as thread safety operations of the Bean, direct access to the bean's method is restricted, since this can result in a potentially catastrophic operation. EJBs cannot be used to create a JMS message listener to asynchronously receive messages, as this would result in the invocation of the Bean methods directly.
Asynchronous Method Invocation using Delegation Model
Using the services provided by any JMS implementation, it is possible for one EJB to asynchronously invoke methods on another bean. You can achieve this through a delegation model that allows a given EJB (or a Client Application using EJBs) to trigger methods on any other Bean. The delegator class is responsible for listening on a JMS Queue, marshaling the incoming JMS messages and invoking appropriate remote methods on the desired target Bean.
The delegator class can be executed as either an Application-Server specific startup class or as a standalone JMS Application. If the delegator class is assigned as one of the startup classes of the Application-Server, then the Application-Server is responsible for firing up this class in a JVM instance. Note that it is not necessary for the delegator class to be in the startup group of classes of the Application-Server. The FioranoMQ JMS-EJB sample that illustrates EJB integration has not made the delegator class a member of the startup class of any application server, since startup classes are Application-Server specific and make the code non portable. The sample illustrates how FioranoMQ (or any Message Queue Software that implements JMS) can be integrated with any Application Server through a single standalone application.
Please consult documentation of your Application Server, to see how the delegator class can be made a startup class.
EJB JMS Sample Application
Fig 1.0 Illustrating the use of JMS for asynchronous method invocation on EJBs
The example in figure 1.0 above illustrates how JMS can be used to asynchronously invoke methods on an EJB. The sample, and the JMS-EJB integration, works as follows:
- Client applications (referred to as "Client EJB Stubs") publish a JMS message each time they want to invoke a method on a remote EJB
- All published JMS messages are received by a "delegator" application, which invokes the appropriate methods on the remote EJB using the Java reflection API.
The JMS-EJB integration application thus has the following three components:
- Event Generator (the Client applications generating the requests to invoke the remote EJB methods)
- Delegator (a JMS application which reads the message and invokes each remote EJB method)
- EJBs (the actual EJB whose methods are invoked).
The Event generator is responsible for publishing JMS Messages to a Queue ("primaryqueue" by default), with each message containing relevant information about methods to invoke in specific remote EJBs. As a real world example, the Event Generator might be a "Shopping cart" bean that needs to asynchronously trigger the method of another Bean depending when the user clicks "checkout" on an HTML page.
The file Publisher.java contains the Event Generator, which simulates an event that is used to invoke appropriate EJBs. The goal of the generated event is to invoke one of three beans (Add, Delete or Update) every 2 seconds. Since there are no limitations in an EJB publishing JMS Messages, the Event Generator is itself an EJB whose sole task is to generate JMS messages that encapsulate the Add/Delete/Update events that need to be invoked on a remote bean. The JMS message (i.e. event) includes the following information:
- the name of the target EJB to lookup
- the API that is used to create instances of the EJB, plus arguments if any
- the name of the method to invoke in the target EJB, plus arguments if any
The above information is required by the Delegator class to invoke the appropriate method asynchronously on the target bean.
The Delegator represents a generalized application that is responsible for receiving events asynchronously and invoking appropriate methods on the target EJB. This JMS Application listens for messages on a queue ("primaryqueue" by default), demarshalls the message and invokes the appropriate method in the target EJB. The delegator class is a generalized class that uses reflection to invoke any remotely accessible method in the requested EJB. The class Subscriber.java represents the delegator class. This JMS Application implements an asynchronous listener to listen for messages published on the queue "primaryQueue". The Delegator receives JMS Messages that are published on the Queue, demarshalls the content of the JMS Message, and finally looks up and invokes the appropriate methods on the EJB with appropriate parameters using reflection. This class can be optionally placed in an Application- Server's startup class, thereby passing on the responsibility of the Delegator to the Application Server.
Enterprise Java Beans
Three simple stateless session beans (namely AddBean, UpdateBean and SessionBean) are used to as the target EJBs, whose methods are invoked by the Delegator of the previous section.
Download Sample Code and Fiorano MQ