You are on page 1of 8

Tutorial

Message Driven Beans - A tutorial

This tutorial illustrates how an MDB is written and deployed in an EJB 2.0
Container. The MDB component is invoked by an inbound message from a client. This
is demonstrated with a sample application that is deployable on Pramati Server 3.0.
The application source can be downloaded from www.pramati.com for better
understanding of how MDB components are written.

What is a Message Driven Bean?


A message driven bean is a stateless server-side transaction-aware
component that is driven by a message (javax.jms.message). It is invoked
by the EJB container when a message is received from a JMS Queue or
Topic and acts as a simple message listener.

Messages may be sent by Java clients, enterprise beans, Java ServerPages, or


any non-J2EE application. Though the client sending a message to the
destination need not be aware of the MDBs deployed in the EJB container,
the message must conform to JMS specification.

Before MDBs were introduced, JMS described a classical approach to


implement asynchronous method invocation. The approach used an
external Java program that acted as the listener, and on receiving a message,
invoked a session bean method. However, in this approach, the message was
received outside the application server and thus not part of a transaction in
the EJB Server. MDB solves this problem.

Structure of an MDB
» MDB has no home or remote interfaces, and is only a bean class.
» A client interacts with the MDB in the same way it interacts with a JMS
application or JMS server.
» Through the MDB, EJB 2.0 container sets itself up as a listener for
asynchronous invocation and directly invokes the bean (no interfaces),
which then behaves like an enterprise bean.
» All instances of a particular MDB type are equivalent as they are not
directly visible to the client and maintain no conversational state. This
means that the container can pool instances to enhance scalability.
Message Driven Beans - A tutorial

MDB Pool
invokes onMessage ()
{
}

Client JMS
Container
picks message

picks up an MDB instance

executes onMessage method

Lifecycle of an MDB
The EJB container performs the following tasks at the beginning of the life cycle
of the MDB:
1 Creates a message consumer (a QueueReceiver or TopicSubscriber) to
receive the messages
2 Associates the bean with a destination and connection factory at deployment
3 Registers the message listener and the message acknowledgment mode
As MDBs are stateless, bean instances are typically pooled by the EJB Server
and retrieved by the container when a message becomes available on the Topic
or Queue.

Writing an MDB
Writing an MDB involves the following tasks:
1 Implement the javax.ejb.MessageDrivenBean and
javax.jms.MessageListener interfaces in the MDB class
2 Provide an implementation of the business logic inside the onMessage()
3 Provide a setMessageDrivenContext() method that associates the bean with
its environment
4 Provide an ejbCreate() method that returns void and takes no arguments.
This method may be blank
5 Provide an ejbRemove() method implementation. This method may be
blank, unless certain resources need to be acquired before the bean goes out
of scope.

2
Message Driven Beans - A tutorial

Sample Application
To illustrate the writing of an MDB, the tutorial uses a sample application,
StockTrader—available for download at www.pramati.com. It uses a simple
message driven bean, buyAgentMDB that is contacted by a client which wishes to
buy shares. The client looks up the BuyQueue and implements
javax.jms.MessageListener. It provides a private method buy() that takes two
arguments, a double value that holds the price and a string stockSymbol that
holds the scrip symbol.

Defining the MDB Class


1 MDB implements two interfaces:
javax.jms.MessageListener and javax.ejb.MessageDrivenBean

2 It is defined as public and cannot be defined as abstract or final


public class BuyAgentMDB
implements MessageDrivenBean, MessageListener {
private MessageDrivenContext mdbContext;

3 The class must consist of


» a public constructor with no argument
» a single onMessage method
» public void ejbCreate() with no arguments
» public void ejbRemove() usually used to free resources allocated in
ejbCreate method
» public void setMessageDrivenContext(MessageDrivenContext mdc),

called by the container after the instance creation, with no transaction context
4 The class must not contain
» the finalize method.

Implementing Business Logic


Execution of business logic for the EJB is triggered by the onMessage() method
of the MDB. This is called by the container when the JMS Queue or Topic
receives a message. It does not return any result and has one argument. The full
JMS message object is passed as an argument. The signature for the method is:
public void onMessage(Message msg) {}

In the sample, when there is a message on the BuyQueue, the onMessage()


method of the BuyAgent picks up the message and sends it to the Topic
StockMarket. The StockRepository in turn looks up this Topic. The following
code of the buyAgentMDB performs this function
3
Message Driven Beans - A tutorial

public void onMessage(Message msg) {


// Retrieves the text message
TextMessage priceMessage = (TextMessage) msg;
try {
}
catch(JMSException ex)
{ ex.printStackTrace();
}
}

Implementing the ejbCreate Method


The ejbCreate() is called at the time of bean instantiation. The MDB can
allocate resources such as connection factories if the bean sends messages or
lookup datasources, if the bean accesses databases. This method is invoked once
in the lifecycle, when the bean is created. The following code of the
BuyAgentMDB performs this function:
public void ejbCreate () throws CreateException
{
}

Providing Methods for Transaction Management


The setMessageDrivenContext provides the methods for transaction
management. The BuyAgentMDB implements setMessageDrivenContext. This
method is called by the EJB container to associate the BuyAgent instance. The
context is maintained by the container.
The input parameter for setMessageDrivenContext is an instance of the
MessageDrivenContext interface. It gives the MDB access to information about
runtime environment.
In container-managed transactions, de-queuing occurs out of the method,
onMessage(). The only methods in the MessageDrivenContext, accessible to the
MDB are transaction-related methods.

Removing the Instance


Application server vendors may implement an arbitrary algorithm that decides
when to remove MDB instances from the pool. The method, ejbRemove() is
invoked when an MDB is being removed from the pool. The following code of
the BuyAgentMDB performs this function:
public void ejbRemove()
{
//Removes the bean from the pool
}

Acknowledging Messages
For MDBs that use container-managed transactions, the container automatically
4
Message Driven Beans - A tutorial

acknowledges a message when the EJB transaction is committed. The


container overrides the acknowledgement mode given in the deployment
descriptor. If the EJB uses bean-managed transactions, both the receipt and
the acknowledgement of a message occur outside the EJB transaction context.

Setting up the Response


Some business cases may require responding to the Sender of the message that
triggered the MDB. To register the “reply to” destination of the Sender, the client
may use the header, getJMSReplyTo.

The JMSReplyTo header field contains a destination supplied by the client along
with the message. This destination is where a “reply to the message” may be sent.
Messages sent with JMSReplyTo value typically expect a response. The code to
use JMSReplyTo header looks like this:
public void onMessage(Message msg){
try {
destination d = msg.getJMSReplyTo()
}
catch(JMSException jmse){}
}

Deploying the MDB


The destination type associated with an MDB is specified in its deployment
descriptor. A destination is a JMS administered object accessible via JNDI.
<message-driven-destination>
<destination-type>javax.jms.Topic</destination-type>
<subscription-durability>NonDurable</subscription-durability>
</message-driven-destination>

Elements in the Deployment Descriptor


The description of an MDB in the EJB 2.0 deployment descriptor contains the
following elements:
1 JMS acknowledgement mode: auto-acknowledge or dups-ok-acknowledge
2 Eventual JMS message selector: this is a JMS concept, which allows filtering
of messages sent to the destination
3 Message-driven-destination, which contains the destination type (Queue or
Topic) and the subscription durability (in case of Topic)
The MDB deployment descriptor specifies whether the bean is intended for a
Topic or a Queue. A bean set for a Topic can act as a durable subscriber
guaranteeing that the listener receives all messages even if the listener is
unavailable for some time.

5
Message Driven Beans - A tutorial

If the transaction type is “container,” the transactional behavior of MDB


methods is defined, as for other enterprise beans in the deployment descriptor.
An entry for transaction type in the deployment descriptor:
<transaction-type>Container</transaction-type>
<acknowledge-mode>Auto-acknowledge</acknowledge-mode>

For the onMessage method, either “Required” or “NotSupported” transaction


attribute must be used, as there is no incoming transaction context.
The important thing to notice is that the deployment descriptor contains all the
information except the destination name required to deploy a MDB. The
destination name is set in an application server's vendor-specific configuration
file or as a system property (deploy time mapping).

Message Server configuration


By default, the following destinations are entered in the configuration file of the
Message Server:
» BuyQueue
» SellQueue
» StockMarket

The configuration file, jms-config.xml is located in [install_dir]/jms/config.

Deployment steps
The following steps will deploy the application on Pramati Server:
1 Start Pramati Server along with the JMS Server (you may refer to
documentation on www.pramati.com for further details on working with
Pramati Server)
2 Start Pramati Management Console from the Windows shortcut. Unix users
must run runadmin.sh from the Server installation directory.
3 In the Console, select Server > Start from the main menu. This brings up the
Start Server dialog where the J2EE Server to be started is identified. Check
the Start JMS Server option to start the Message Server along with the J2EE
Server. This is essential to run the message driven beans.

Deploying the application


1 After the Server has started, click on the Deploy button in the view panel of
the Console to start the Deploy Tool
2 Select Archive > Open and open the application stockapp.ear from
[install_dir]/samples/mdb
3 Deploy the application

6
Message Driven Beans - A tutorial

Running the client


Setting up Classpath : Windows
1 Execute the file, run.bat from the directory [install_dir]/samples/mdb
2 Add the following location of the application classes to the client classpath:
[install_dir]/server/samples/mdb/classes

Setting up Classpath : Unix


Execute the following command in the shell:
export CLASSPATH=$install_root/server/samples/mdb/
classes:%$CLASSPATH

Starting the stock repository


The stock repository is run by the client, StockServer.java. Start the client by
executing
java com.pramati.samples.mdb.StockServer

This brings up the stock repository panel, which displays the scrip and the price
along with a Buy/Sell advisory message. Observe the price fluctuations on
buying or selling of stocks.

Summary
MDBs overcome the limitations of synchronous messaging using session and
entity beans in the EJB 1.1 container. MDBs can be deployed in EJB 2.0
container, which acts as a message listener and uses inbound messages as a
trigger to invoke business methods in an asynchronous manner.
Pramati Technologies, based in Hyderabad, India but with significant operations
in the U.S. and abroad, is a global provider of Java software development
technology for small-to-medium sized businesses. Pramati Server and Studio
together are a complete platform developers use to create and deploy applications
based on Sun Microsystems' Java 2 Enterprise Edition platform but at a fraction
of the cost typically required.
Use the sample MDB application with a free full-feature Development License of
World’s First J2EE 1.3 certified Pramati Server from www.pramati.com.
Try out the free evaluation license of Pramati Studio for complete J2EE 1.3
component lifecycle management.

7
Pramati Technologies
www.pramati.com

Bangalore +91 (80) 299-6510


Chennai +91 (44) 822-3289
Hyderabad +91 (40) 341-1672
San Jose +1 (877) PRAMATI

© 2001–02, Pramati Technologies (P) Ltd.


Information and specifications are subject to change without notice. Pramati and Pramati
Logo are trademarks and/or service marks of Pramati Technologies in the United States
and/or other countries. Java and Java based marks are the registered trademarks of Sun
Microsystems Inc., in United States and other countries. All other product or service names
mentioned in this document may be trademarks of the companies with which they are
associated.

1270-001 c 06/02

You might also like