BEA Home | Events | Solutions | Partners | Products | Services | Download | Developer Center | WebSUPPORT
| WebLogic Server Doc Home | Programming WebLogic EJB | Previous Topic | Next Topic | Contents | View as PDF

Using Message-Driven Beans

The following sections describe how to develop message-driven beans and to deploy then on WebLogic Server. Because message-driven beans use parts of the standard JMS API, you should first become familiar with the WebLogic Java Messaging Service (JMS) before attempting to implement message-driven beans. See the Programming WebLogic JMS document for more information.

Note: Message-driven beans are an EJB 2.0 feature.

- What Are Message-Driven Beans?

- Developing and Configuring Message-Driven Beans

- Invoking a Message-Driven Bean

- Creating and Removing Bean Instances

- Deploying Message-Driven Beans in WebLogic Server

- Using Transaction Services with Message-Driven Beans

What Are Message-Driven Beans?

A message-driven bean is an EJB that acts as a message consumer in the WebLogic JMS messaging system. As with standard JMS message consumers, message-driven beans receive messages from a JMS Queue or Topic, and perform business logic based on the message contents. WebLogic Server associates a message-driven bean with a JMS destination, such as a topic or queue, at deployment time, and WebLogic Server automatically creates and removes message-driven bean instances as needed to process incoming messages.

Differences Between Message-Driven Beans and Standard JMS Consumers

Because message-driven beans are implemented as EJBs, they benefit from several key services that are not available to standard JMS consumers. Most importantly, message-driven bean instances are wholly managed by the WebLogic Server EJB container. Using a single message-driven bean class, WebLogic Server creates multiple EJB instances as necessary to process large volumes of messages concurrently. This stands in contrast to a standard JMS messaging system, where the developer must create a MessageListener class that uses a server-wide session pool.

The WebLogic Server container provides other standard EJB services to message- driven beans, such as security services and automatic transaction management. These services are described in more detail in Transaction Managementand in Using Transaction Services with Message-Driven Beans.

Finally, message-driven beans benefit from the write-once, deploy-anywhere quality of EJBs. Whereas a JMS MessageListener is tied to specific session pools, Queues, or Topics, message-driven beans can be developed independently of available server resources. A message-driven bean's Queues and Topics are assigned only at deployment time, utilizing resources available on WebLogic Server.

Note: One limitation of message-driven beans compared to standard JMS listeners is that you can associate a given message-driven bean deployment with only one Queue or Topic, as described in Invoking a Message-Driven Bean. If your application requires a single JMS consumer to service messages from multiple Queues or Topics, you must use a standard JMS consumer, or deploy multiple message-driven bean classes.

Differences Between Message-Driven Beans and Stateless Session EJBs

The dynamic creation and allocation of message-driven bean instances partially mimics the behavior of stateless session EJB instances. However, message-driven beans differ from stateless session EJBs (and other types of EJBs) in several significant ways:

- Message-driven beans process multiple JMS messages asynchronously, rather than processing a serialized sequence of method calls.

- Message-driven beans have no home or remote interface, and therefore cannot be directly accessed by internal or external clients. Clients interact with message-driven beans only indirectly, by sending a message to a JMS Queue or Topic.

Note: Only the WebLogic Server container directly interacts with a message-driven bean by creating bean instances and passing JMS messages to those instances as necessary.

- WebLogic Server maintains the entire life cycle of a message-driven bean; instances cannot be created or removed as a result of client requests or other API calls.

Concurrent Processing for Topics and Queues

Message-driven beans (MDBs) support concurrent processing for both topics and queues. Previously, only concurrent processing for queues was supported.

To ensure concurrency, the container uses threads from the execute queue. The default setting for the max-beans-in-free-pool deployment descriptor found in the weblogic-ejb-jar.xml file provides the most parallelism. The only reason to change this setting would be to limit the number of parallel consumers.

Note: The maximum number of MDBs configured—via the max-beans-in-free-pool deployment descriptor element— to receive messages at one time cannot exceed the maximum number of execution threads. For example, if max-beans-in-free-pool is set to 50 but 25 is the maximum number of execution threads allowed, only 25 of the MDBs will actually receive messages.

For more information on max-beans-in-free-pool, see, max-beans-in-free-pool.

Developing and Configuring Message-Driven Beans

When developing message-driven beans, follow the conventions described in the JavaSoft EJB 2.0 specification, and observe the general practices that result in proper bean behavior. Once you have created the message-driven bean class, configuring the bean for WebLogic Server by specify the bean's deployment descriptor elements in the EJB XML deployment descriptor files.

To develop a message-driven bean:

1. Create a source file (message-driven bean class) that implements both the javax.ejb.MessageDrivenBean and javax.jms.MessageListener interfaces.

   The message-driven bean class must define the following methods:

   - One ejbCreate() method that the container uses to create an instance of the message-driven bean on the free pool.

   - One onMessage() method that is called by the bean's container when a message is received. This method contains the business logic that handles processing of the message.

   - One ejbRemove() method that removes the message-driven bean instance from the free pool.

     For an example of output for a message-driven bean class, see Message-Driven Bean Class Requirements

2. Specify the following XML deployment descriptor files for the message-driven bean.

   - ejb-jar.xml

   - weblogic-ejb-jar.xml

   - weblogic-cmp-rdbms-jar.xml

     For instructions on specifying the XML files, see Specifying and Editing the EJB Deployment Descriptors.

3. Set the message-driven element in the bean's ejb-jar.xml file to declare the bean.

4. Set the message-driven-destination element in the bean's ejb-jar.xml file to specify whether the bean is intended for a Topic or Queue.

5. Set the subscription-durability sub-element in the bean's ejb-jar.xml file when you want to specify whether an associated Topic should be durable.

6. If your bean will demarcate its own transaction boundaries, set the acknowledge-mode sub-element to specify the JMS acknowledgment semantics to use. This element has two possible values: AUTO_ACKNOWLEDGE (the default) or DUPS_OK_ACKNOWLEDGE.

7. If the container will manage the transaction boundaries, set the transaction-type element in the bean's ejb-jar.xml file to specify how the container must manage the transaction boundaries when delegating a method invocation to an enterprise bean's method.

The following sample shows how to specify a message-driven bean in the ejb-jar.xml file.

Figure 3-1 Sample XML stanza from an ejb-jar.xml file:

>     <enterprise-beans>

>     	<message-driven>

>     		<ejb-name>exampleMessageDriven1</ejb-name>

>     <ejb-class>examples.ejb20.message.MessageTraderBean</ejb-class>

>     		<transaction-type>Container</transaction-type>

>     		<message-driven-destination>

>     			<destination-type>

>     				javax.jms.Topic

>     			</destination-type>

>     		</message-driven-destination>

>     		...

>     	</message-driven>

>     	...

>     </enterprise-beans>

1. Set the message-driven-descriptor element in the bean's weblogic-ejb-jar.xml file to associate the message-driven bean with a JMS destination in WebLogic Server.

The following sample shows how to specify a message-driven bean in an weblogic-ejb-jar.xml file.

Figure 3-2 Sample XML stanza from an weblogic-ejb-jar.xml file:

>     <message-driven-descriptor>

>     	<destination-jndi-name>...</destination-jndi-name>

>     </message-driven-descriptor>

1. Compile and generate the message-driven bean class using instructions in Packaging EJBs into a Deployment Directory.

2. Deploy the bean on WebLogic Server using the instructions in Deploying Compiled EJB Files.

The container manages the message-driven bean instances at runtime.

Message-Driven Bean Class Requirements

The EJB 2.0 specification provides detailed guidelines for defining the methods in a message-driven bean class. The following output shows the basic components of a message-driven bean class. Classes, methods, and method declarations are highlighted bold.

Figure 3-3 Sample output of basic components of message-driven beans class

>     public class MessageTraderBean implements MessageDrivenBean,
>     MessageListener{

>     	public MessageTraderBean() {...};

>     		// An EJB constructor is required, and it must not

>     		// accept parameters. The constructor must not be
>     declared as

>     		// final or abstract.

>     	public void ejbCreate() (...)

>     		//ejbCreate () is required and must not accept
>     parameters.

>     		The throws clause (if used) must not include an
>     application

>     		//exception. ejbCreate() must not be declared as
>     final or static.

>     	public void onMessage(javax.jms.Message MessageName) {...}

>     		// onMessage() is required, and must take a single
>     parameter of

>     		// type javax.jms.Message. The throws clause (if
>     used) must not

>     		// include an application exception. onMessage() must
>     not be

>     		// declared as final or static.

>     	public void ejbRemove() {...}

>     		// ejbRemove() is required and must not accept
>     parameters.

>     		// The throws clause (if used) must not include an
>     application

>     		//exception. ejbRemove() must not be declared as
>     final or static.

>     	// The EJB class cannot define a finalize() method

>     }

Using the Message-Driven Bean Context

WebLogic Server calls setMessageDrivenContext() to associate the message-driven bean instance with a container context.This is not a client context; the client context is not passed along with the JMS message. WebLogic Server provides the EJB with a container context, whose properties can be accessed from within the bean's instance by using the following methods from the MessageDrivenContext interface:

- getCallerPrincipal()) — This method is inherited from the EJBContext interface and should not be called by message-driven bean instances.

- isCallerInRole()) — This method is inherited from the EJBContext interface and should not be called by message-driven bean instances.

- setRollbackOnly() — The EJB can use this method only if it uses container-managed transaction demarcation.

- getRollbackOnly() — The EJB can use this method only if it uses container-managed transaction demarcation.

- getUserTransaction() — The EJB can use this method only if it uses bean-managed transaction demarcation.

Note: Although getEJBHome() is also inherited as part of the MessageDrivenContext interface, message-driven beans do not have a home interface. Calling getEJBHome() from within a message-driven EJB instance yields an IllegalStateException.

Implementing Business Logic with onMessage()

The message-driven bean's onMessage() method implements the business logic for the EJB. WebLogic Server calls onMessage() when the EJB's associated JMS Queue or Topic receives a message, passing the full JMS message object as an argument. It is the message-driven bean's responsibility to parse the message and perform the necessary business logic in onMessage().

Make sure that the business logic accounts for asynchronous message processing. For example, it cannot be assumed that the EJB receives messages in the order they were sent by the client. Instance pooling within the container means that messages are not received or processed in a sequential order, although individual onMessage() calls to a given message-driven bean instance are serialized.

See javax.jms.MessageListener.onMessage() for more information.

Specifying Principals and Setting Permissions for JMS Destinations

Message-driven beans connect to the JMS destination using the run-as principal. The run-as principal maps to the run-as element that is set in the ejb-jar.xml file. This setting specifies the run-as identity used for the execution of the message-driven bean's methods. A message-driven bean is associated with a JMS destination when you deploy the bean in the WebLogic Server container. The JMS destination can either be a queue or a topic. You specify the JMS destination by setting the jms-destination-type element to either queue or topic in the message-driven bean's ejb-jar.xml file.

Set the permissions for the bean's run-as principal to receive, as described below, when connecting message-driven beans to the JMS destinations. This allows the message-driven bean to connect to remote queues in the same domain or in another domain as long as the same principal is defined in the other domain. WebLogic Server uses the default guest user if you do not specify the run-as principal. However, whether you use the run-as principal or guest, you must assign the receive permission to the security principal.

To set the receive permission, you must first create a new access control list (ACL) or modify an existing one. are lists of Users and Groups that have permission to access the resources. Permissions are the privileges required to access resources, such as permission to read, write, send, and receive files and load servlets, and link to libraries.

Note: Do not use the system user for message-driven beans that connect to JMS destinations because system prevents the message-driven bean from connecting to a destination in another domain.

For more information on security principal users, see Defining Users.

See the following instructions to create the ACL, specify principals, and set permissions:

1. Start the WebLogic Server Administration Console.

2. Go to the Security—>ACLs node in the left pane of the Administration Console.

3. In the right pane of the Administration Console, click the Create a New ACL link.

   The ACL Configuration window appears.

4. Specify the name of WebLogic Server resource that you want to protect with an ACL in the New ACL Name field.

   For example, create an ACL for a JMS destination named topic.

5. Click Create.

6. Click the Add a New Permission link.

7. Specify the receive permission for the topic JMS destination resource.

8. Specify the run-as-principal user as having the specified permission to the resource.

9. Click Apply.

Specifying Message-Driven Beans as Durable Subscribers

If you associate a message-driven bean with a topic, you can specify that the topic be durable. A durable topic subscription ensures that messages are not missed even if the server is not running. If the server is disconnected it would still receive the message and store it so that when the server is restarted it would receive the message. If you associate a message-driven bean with a topic, but do specify that topic as durable then by default, the topic will be non-durable.

To set the message-driven bean as a durable subscriber, specify the following deployment descriptor elements:

1. Set the message-driven-destination element in the bean's ejb-jar.xml file to specify whether the bean is intended for a Topic or Queue.

2. Set the subscription-durability sub-element in the bean's ejb-jar.xml file when you want to specify whether an associated Topic should be durable.

3. Set the jms-client-id element in the bean's weblogic-ejb-jar.xml file.

   For instructions on specifying the XML files, see Specifying and Editing the EJB Deployment Descriptors.

Note: If you are using message-driven beans instead of the standard JMS listeners to handle messages, be advised that a given message-driven bean is associated with only one topic. If your application requires a single JMS consumer to service messages from multiple topics or queues, you must use a standard JMS consumer or deploy multiple message-driven bean classes.

Configuring Message-Driven Beans for Foreign JMS Providers

You can configure message-driven beans to work with non-BEA JMS providers such as IBM MQSeries. For a discussion of how to configure an MDB to use a foreign provider, see "Using Foreign JMS Providers with WLS Message Driven Beans" at http://dev2dev.bea.com/products/wlserver/whitepapers/jmsproviders.jsp.

Reconnecting to a JMS Server or Foreign Service Provider

A message-driven bean listens to an associated JMS destination on either a JMS server deployed on a non-clustered WebLogic Server instance or a foreign service provider. If the connection to that destination is lost, because the server goes down, the message-driven bean attempts to reconnect to that destination at periodic intervals. You can specify the number of seconds between attempts to reconnect to the destination by setting the jms-polling-interval-seconds element in the bean's weblogic-ejb-jar.xml file.

For instructions on specifying the XML files, see Specifying and Editing the EJB Deployment Descriptors.

Handling Exceptions

Message-driven bean methods should not throw an application exception or a RemoteException, even in onMessage(). If any method throws such an exception, WebLogic Server immediately removes the EJB instance without calling ejbRemove(). However, from the client perspective the EJB still exists, because future messages are forwarded to a new bean instance that WebLogic Server creates.

Invoking a Message-Driven Bean

When a JMS Queue or Topic receives a message, WebLogic Server calls an associated message-driven bean as follows:

1. WebLogic Server obtains a new bean instance.

   WebLogic Server uses the max-beans-in-free-pool attribute, set in the weblogic-ejb-jar.xml file, to determine if a new bean instance is available in the free pool.

2. If a bean instance is available in the free pool, WebLogic Server uses that instance.

   If no bean instance is available in the free pool and the limit specified by max-beans-in-free-pool) has been reached, WebLogic Server waits until a bean instance is free. See max-beans-in-free-pool for more information about this attribute.

   If no bean instance is located in the free pool, and the limit specified by max-beans-in-free-pool has not been reached, WebLogic Server creates a new instance by calling the bean's ejbCreate() method and then the bean's setMessageDrivenContext() to associate the instance with a container context. The bean can use elements of this context as described in Using the Message-Driven Bean Context.

3. WebLogic Server calls the bean's onMessage() method to implement the business logic when the bean's associated JMS Queue or Topic receives a message.

   See Implementing Business Logic with onMessage().

Note: These instances can be pooled.

Creating and Removing Bean Instances

The WebLogic Server container calls the message-driven bean's ejbCreate() and ejbRemove() methods, to create or remove an instance of the bean class. Each message-driven bean must have at least one ejbCreate() and ejbRemove() method. The WebLogic Server container uses these methods to handle the create and remove functions when a bean instance is created, upon receipt of a message from a JMS Queue or Topic or removed, once the transaction commits.

WebLogic Server receives a message from a JMS queue or Topic

As with other EJB types, the ejbCreate() method in the bean class should prepare any resources that are required for the bean's operation. The ejbRemove() method should release those resources, so that they are freed before WebLogic Server removes the instance.

Message-driven beans should also perform some form of regular clean-up routine outside of the ejbRemove() method, because the beans cannot rely on ejbRemove() being called under all circumstances (for example, if the EJB throws a runtime exception).

Deploying Message-Driven Beans in WebLogic Server

Deploy the message-driven bean on WebLogic Server either when the server is first started or on a running server. For instructions on deploying the bean, see Deploying EJBs at WebLogic Server Startup or Deploying EJBs on a Running WebLogic Server.

Using Transaction Services with Message-Driven Beans

As with other types of EJB, message-driven beans can demarcate transaction boundaries either on their own (using bean-managed transactions), or by having the WebLogic Server container manage transactions (container-managed transactions). In either case, a message-driven bean does not receive a transaction context from the client that sends a message. WebLogic Server always calls a bean's onMessage() method by using the transaction context specified in the bean's deployment descriptor file.

Because no client provides a transaction context for calls to a message-driven bean, beans that use container-managed transactions must be deployed with the Required or NotSupported trans-attribute specified for the container-transaction element in the ejb-jar.xml file.

The following sample code from the ejb-jar.xml file shows how to specify the bean's transaction context.

Figure 3-4 Sample XML stanza from an ejb-jar.xml file:

>     <assembly-descriptor>

>     	<container-transaction>

>     		<method>

>     <ejb-name>MyMessageDrivenBeanQueueTx</ejb-name>

>     			<method-name>*</method-name>

>     		</method>

>     	<trans-attribute>NotSupported</trans-attribute>

>     	</container-transaction>

>     </assembly-descriptor>

Message Receipts

The receipt of a JMS message that triggers a call to an EJB's onMessage() method is not generally included in the scope of a transaction. However, it is handled differently for bean-managed and container-managed transactions.

- For EJBs that use bean-managed transactions, the message receipt is always outside the scope of the bean's transaction.

- For EJBs that use container-managed transaction demarcation, WebLogic Server includes the message receipt as part of the bean's transaction only if the bean's transaction-type element in the ejb-jar.xml file is set to Required.

Message Acknowledgment

For message-driven beans that use container-managed transaction demarcation, WebLogic Server automatically acknowledges a message when the EJB transaction commits. If the EJB uses bean-managed transactions, both the receipt and the acknowledgment of a message occur outside the EJB transaction context. WebLogic Server automatically acknowledges messages for EJBs with bean-managed transactions, but you can configure acknowledgment semantics using the acknowledge-mode deployment descriptor element defined in the ejb-jar.xml file.

Copyright © 2001 BEA Systems, Inc. All rights reserved. Required browser: Netscape 4.0 or higher, or Microsoft Internet Explorer 4.0 or higher.