Skip navigation.
Downloads | Product Documentation | Support

Programming WebLogic Enterprise JavaBeans

# Message-Driven EJBs

The following sections describe the message-driven bean (MDB) lifecycle, design considerations, and instructions for key implementation tasks. For a description of the overall EJB development process, see Implementing Enterprise Java Beans.

- Message-Driven EJB Lifecycle and the Free Pool
- MDBs and Messaging Models
- MDB Deployment Options
- Programming and Configuring MDBs: Main Steps
- Programming and Configuring MDBs: Details
- Migration and Recovery for Clustered MDBs
- Nutshell Summary: Deployment Elements for MDBs

For an introduction to MDBs and how they are typically used in applications, see Message-Driven Beans Implement Loosely Coupled Business Logic and Message-Driven Bean Features. For information about WebLogic JMS, see Programming WebLogic JMS.

# Message-Driven EJB Lifecycle and the Free Pool

This section describes the phases in the lifecycle of a message-driven bean instance and how you can configure an MDB to control the lifecycle. Figure 7-1 illustrates the key events and states in the MDB lifecycle.

Figure 7-1 MDB Life Cycle

## MDBs and the Free Pool

WebLogic Server maintains a free pool where MDB instances that are not currently servicing requests reside. For best response time and throughput, you can configure WebLogic Server to populate the pool at startup by specifying the desired quantity in the bean's initial-beans-in-free-pool element in `weblogic-ejb-jar.xml`. By default, `initial-beans-in-free-pool` is 0.

The number of MDB instances in the free pool is limited by the value of the max-beans-in-free-pool element in `weblogic-ejb-jar.xml` (by default, 1,000), the number of threads in the MDB's execute queue, and available memory. The effect that thread pool size has on the maximum number of MDB instances in the free pool varies, based on whether the MDB uses the default execute queue, or is configured to use another execute queue. For more information, see dispatch-policy.

An MDB processes messages from a JMS destination. When a message is received, the EJB container calls the MDB's `onMessage()` method, which contains the business logic the EJB performs. When an MDB's `onMessage` method is invoked:

- If a bean instance is available in the free pool, WebLogic Server uses that instance. This results in the best response time, as the request is served without waiting for a new instance to be created.
- If no bean instance is located in the free pool, WebLogic Server initializes one by calling:

- The MDB's constructor method
- The MDB's `ejbCreate()` method
- The MDB'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.

- If all instances of an MDB are active, and`max-beans-in-free-pool` has been reached, JMS `onMessage()` requests will be blocked until an active MDB completes a method call. Your application waits until your transaction times out or until a bean instance that already exists in the pool becomes available.

After an MDB instance's `onMessage()` method returns, the request is complete, and the instance it is placed in the free pool for re-use, assuming that doing so does not cause `max-beans-in-free-pool` to be exceeded.

## MDBs and Concurrent Processing

MDBs support concurrent processing for both topics and queues. For more information about topics and queues, see MDBs and Messaging Models.

The default setting for the max-beans-in-free-pool element in `weblogic-ejb-jar.xml`—1,000—provides the most parallelism. The only reason to change this setting would be to limit the number of parallel consumers.

Each MDB that is deployed to a server instance creates a single JMS connection.

In a queue-based JMS application (point-to-point model), each MDB instance has its own session.

In a topic-based JMS application (the publish/subscribe model), all local instances of an MDB share a JMS session. A given message is distributed to multiple MDBs—one copy to each subscribing MDB. If multiple MDBs are deployed to listen on the same topic, then each MDB receives a copy of every message. A message is processed by one instance of each MDB that listens to the topic.

# MDBs and Messaging Models

WebLogic Server MDBs can be used in either a point-to-point (queue) or publish/subscribe (topic) messaging model. These models are described in detail in WebLogic JMS Fundamentals in Programming WebLogic JMS.

The following sections describe the key differences between point-to-point and publish/subscribe messaging applications.

## Point-to-Point (Queue) Model: One Message Per Listener

In the point-to-point model, a message from a JMS queue is picked up by one MDB listener and stays in the queue until processed. If the MDB goes down, the message remains in the queue, waiting for the MDB to come up again.

Example: A department must update its back-end inventory system to reflect items sold throughout the day. Each message that decrements inventory must be processed once, and only once. It is not necessary for messages to be processed immediately upon generation or in any particular order, but it is critical that each message be processed.

Figure 7-2 illustrates a point-to-point application. Each message is processed by single instance of MDB_A. Message "M1" is processed by MDB_A(1), "M2" is processed by MDB_A(2), and "M3" is processed by MDB_A(3).

Figure 7-2 Point-to-Point Model

## Publish/Subscribe (Topic) Model

In the publish/subscribe model, a JMS topic publishes all messages to all subscribed listeners. If an MDB listener goes down, that MDB will miss the message, unless the topic is a durable subscription topic.

For more information on durable subscriptions and for configuration instructions, see Setting Up Durable Subscriptions in Programming WebLogic JMS and Configuring Durable Topic Subscriptions.

Example: A financial news service broadcasts stock prices and financial stories to subscribers, such as news wire services. Each message is distributed to each subscriber.

Figure 7-3 illustrates a publish/subscribe application. In contrast to a point-to-point application, in a publish/subscribe model, a message is processed by one instance of each of the subscribing MDBs. Message "M1" is processed by an instance of MDB_A and an instance of MDB_B. Similarly, "M2" is processed by an instance of each of the subscribing MDBs.

Figure 7-3 Publish/Subscribe Model

## Exactly-Once Processing

An MDB pool processes each message at least once. Potentially, a message can be process more than once:

- If an application fails, a transaction rolls back, or the hosting server instance fail during or after the `onMessage()` method completes but before the message is acknowledged or committed, the message will be redelivered and processed again.
- Non-persistent messages are also redelivered in the case of failure, except for the case where the message's host JMS server shuts down or crashes, in which case the messages are destroyed.

To ensure that a message is processed exactly once, use container-managed transactions so that failures cause transactional MDB work to rollback and force the message to be redelivered.

# MDB Deployment Options

This section describes various approaches for deploying MDBs and the JMS destination to which the MDBs listen.

## Destination and MDBs: Collocated vs. Not Collocated

You can deploy an MDB on the same server instance as the JMS destination to which it listens, or on a separate server instance. These alternatives are referred to as collocation or non-collocation, respectively.

### Collocated Destination/MDBs

Collocating an MDB with the destination to which it listens keeps message traffic local and avoids network round trips. Collocation is the best choice if you use WebLogic Server JMS and want to minimize message processing latency and network traffic.

You cannot collocate the MDB and the JMS destination if you use a third-party JMS provider that cannot run on WebLogic Server, such as MQ Series.

Figure 7-4 and Figure 7-5 illustrate architectures in which the MDB application is deployed to the server instance that hosts the associated JMS destination. These architectures vary in that the first has a distributed destination and the second does not. In an application that uses distributed destinations, the MDB is deployed to each server instance that hosts a member of the distributed destination set. For more information about distributed destinations, see JMS Distributed Destinations. As illustrated in Figure 7-4 the message "M1" is delivered to an instance of MDB_A on each server instance where a distributed destination and MDB_A are deployed.

Figure 7-4 Collocated Destination/MDBs, Distributed Destination

Figure 7-5 Collocated Destination/MDBs, Non-Distributed Destination

### Non-Collocated Destination/MDBs

Figure 7-6 illustrates an architecture in which an MDB runs on a separate server instance than the JMS Destination to which the MDB listens.

Figure 7-6 Non-Collocated Application, Non-Distributed Destination

Running your MDBs on a separate server instance from the JMS Destination to which the MDB listens is suitable if:

- Your application uses a 3rd-party JMS provider, such as MQ Series.
- You want to isolate application code (the MDBs) from the JMS infrastructure. By placing JMS destinations and MDBs on separate server instances, you prevent application problems—for example, MDBs consuming all of your virtual machine's memory—from interrupting the operation of the JMS infrastructure.
- Your MDB application is very CPU-intensive. On a separate machine, your application can use 100 percent of the CPU without having affecting the operation of the JMS infrastructure.
- One machine in your configuration has more processing power, disk space, and memory than other machines in the configuration.
- Your application will process a relatively small number of messages.

The JMS destination and MDBs could also be deployed on non-clustered servers, servers within the same cluster, or to servers in separate clusters.

## JMS Distributed Destinations

If your MDB application runs on a WebLogic Server cluster, you can configure multiple physical destinations (queues or topics) as a distributed destination, which appears to message producers and consumers to be a single destination.

If you configure a distributed destination, WebLogic JMS distributes the messaging load across available members of the distributed destination. If a member of the destination becomes unavailable due to a server failure, message traffic is re-directed to the other available physical destinations in the distributed destination set.

If you deploy an MDB and the associated distributed destination to the same cluster, WebLogic Server automatically enumerates the distributed destination members and ensures that there is an MDB listening on each member.

The MDBs are homogeneously deployed to each clustered server instance. Messages are distributed across the physical destinations on the multiple server instances, and are processed in parallel. If one server instance goes down, other nodes in the cluster can continue to process messages. This architecture is a good choice if:

- Your application has high availability requirements.
- You prefer to deploy applications homogeneously so that each server runs the same set of applications.
- Your application processes a high volume of messages, or requires massively parallel processing.
- The machines in your cluster have identical or similar processing power, disk space, and memory.

For an example, see Figure 7-4. For additional information about distributed destinations, see Using Distributed Destinations in Programming WebLogic JMS.

# Programming and Configuring MDBs: Main Steps

This section provides step-by-step instructions for implementing an MDB.

Note: For a summary of key deployment elements for MDBs, see Nutshell Summary: Deployment Elements for MDBs.

## Required JMS Configuration

The steps in the following section assume that you have created the appropriate JMS components:

- A JMS connection factory—one that supports XA, if your MDBs are transactional.

The default WebLogic MDB connection factory is XA-capable. For information about the default connection factories, see Using the Default Connection Factories in Programming WebLogic JMS. For instructions to configure a custom WebLogic JMS connection factory, see Configuring a JMS Connection Factory in Administration Console Online Help.

The default behavior and configuration methods for other JMS providers vary. If you use a non-BEA JMS provider, see the vendor documentation for details.

- A JMS destination

For instructions on configuring WebLogic JMS destinations, see JMS Destination" in Administration Console Online Help.

Note: If your JMS provider is a remote WebLogic Server JMS provider or a foreign JMS provider, and you use the wrapper approach recommended in Whether to Use Wrappers, in addition to configuring the non-local JMS components, you must also configure a Foreign Connection Factory and Foreign JMS Destination in your local JNDI tree.

## Create MDB Class and Configure Deployment Elements

Follow these steps to implement 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 MDB class must define the following methods:

- One `ejbCreate()` method that the container uses to create an instance of the message-driven bean in the free pool.
- One `onMessage()` method that is called by the EJB container when a message is received. This method contains the business logic that processes the message.
- One `setMessageDrivenContext{}` method that provides information to the bean instance about its environment (certain deployment descriptor values); the MDB also uses the context to access container services. See Using the Message-Driven Bean Context.
- One `ejbRemove()` method that removes the message-driven bean instance from the free pool.

2. Declare the MDB in `ejb-jar.xml`, as illustrated in the excerpt below:

`<ejb-jar>
<enterprise-beans>
<message-driven>
<ejb-name>,,,</ejb-name>
<ejb-class>...</ejb-class>
<transaction-type>Container</transaction-type>
<acknowledge-mode>auto_acknowledge</acknowledge-mode>
<message-driven-destination>
<destination-type>javax.jms.Topic</destination-type>
<subscription-durability>Durable</subscription-durability>
</message-driven-destination>
</message-driven>
</enterprise-beans>
<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>...</ejb-name>
<method-name>onMessage()</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
</assembly-descriptor>
</ejb-jar>`

The key behaviors to configure are:

- Transaction management strategy—The MDB's transaction management strategy, in the `transaction-type` element. For instructions, see Configuring Transaction Management Strategy for an MDB.
- Destination type—The type of destination to which the MDB listens. For more information, see Configuring Destination Type.

3. Configure WebLogic-specific behaviors for the MDB in the `message-driven-descriptor` element of `weblogic-ejb-jar.xml`.

`<weblogic-ejb-jar>
<weblogic-enterprise-bean>
<ejb-name>exampleMessageDrivenA</ejb-name>
<message-driven-descriptor>
<pool>
<max-beans-in-free-pool>...</max-beans-in-free-pool>
<initial-beans-in-free-pool>...</initial-beans-in-free-pool>
</pool>
<destination-jndi-name>...</destination-jndi-name>
<initial-context-factory>...</initial-context-factory>
<provider-url> </provider-url>
<connection-factory-jndi-name>..<connection-factory-jndi-name>
<jms-client-id>.... </jms-client-id>
</message-driven-descriptor>
<jndi-name>someid</jndi-name>
<dispatch-policy>custom_execute_queue</dispatch-policy>
</weblogic-enterprise-bean>
</weblogic-ejb-jar>
`
The key elements to configure are:

- The elements that specify how to access the destination. For instructions, see Configuring MDBs for Destinations.
- The elements related to the free pool. For more information, see Message-Driven EJB Lifecycle and the Free Pool.

4. Set `start-mdbs-with-application` to `false` in the `weblogic-application.xml.` This ensures that the MDB does not start message processing until WebLogic Server is completely booted up. For more information, see Deferring Message Processing Until Completion of Boot Up.
5. Compile and generate the MDB class using the instructions in Compile Java Source.
6. Deploy the bean on WebLogic Server using the instructions in the section Quickstart Guide to Deploying Modules in Deploying WebLogic Server Applications.

If WebLogic Server cannot find an MDB's JMS destination during deployment, deployment succeeds, but WebLogic Server prints a message saying the destination was not found. The MDB bean then periodically tries to connect to its JMS queue until it succeeds. For more information, see Migration and Recovery for Clustered MDBs.

# Programming and Configuring MDBs: Details

The topics in this section supplement the instructions in Programming and Configuring MDBs: Main Steps.

Note: For a summary of key deployment elements for MDBs, see Nutshell Summary: Deployment Elements for MDBs.

- Configuring Destination Type
- Configuring MDBs for Destinations
- Configuring Durable Topic Subscriptions
- Configuring Message Handling Behaviors
- Using the Message-Driven Bean Context
- Configuring a Security Identity for a Message-Driven Bean

## Configuring Destination Type

Configure the type of destination to which the MDB listens the `destination-type` element in the `message-driven-destination` element of `ejb-jar.xml`.``

To specify a topic, set `destination-type` to `javax.jms.Topic`

To specify a queue, set `destination-type` to `javax.jms.Queue`. If the destination is a topic, specify `subscription-durability` as either `Durable` or `NonDurable`. For more information, see Configuring Durable Topic Subscriptions.

## Configuring Transaction Management Strategy for an MDB

An MDB can manage its own transactions or defer transaction management to the container.

To configure container-level transaction management:

- Set the `transaction-type` element in the `message-driven` stanza in `ejb-jar.xml` file to `Container`.
- Set the `trans-attribute` element in the `container-transaction` stanza in `ejb-jar.xml` to `Required`.

Note: If `transaction-type` is set to `Container`, and `trans-attribute` is not set, the default `transaction-attribute` value (`NotSupported` for MDBs) is applied. WebLogic Server allows you to deploy the MDB, and logs a compliance error. However, if you make this configuration error, the MDB will not run transactionally—if a failure occurs mid-transaction, updates that occurred prior to the failure will not be rolled back.

- To change the timeout period for the transaction, set trans-timeout-seconds in the transaction-descriptor stanza of `weblogic-ejb-jar.xml.` If a transaction times out, it is rolled back, and the message is redelivered. By default, transactions time out after 30 seconds. For an application with long-running transactions, it may be appropriate to increase the timeout period.

To configure bean-level transaction management:

- Set the `transaction-type` element in the `message-driven` stanza in `ejb-jar.xml` file to `Bean`.
- Set the `acknowledge-mode` element to specify the desired JMS acknowledgment semantics, either AUTO_ACKNOWLEDGE (the default) or DUPS_OK_ACKNOWLEDGE.

For more information, see Session Object in Programming WebLogic JMS.

## Configuring MDBs for Destinations

WebLogic Server MDBs support Weblogic JMS destinations and foreign (non-BEA) JMS provider destinations.

A local destination is one that runs on the same machine or in the same cluster as the MDB. A remote destination is one that runs on a different machine and is not a member of the same cluster as the MDB. Whether a destination is local or remote depends on whether or not it and the MDB share the same JNDI context.

To be considered local to one another, an MDB and the associated JMS destination must both run either on the same machine or within the same WebLogic Server cluster. An MDB and a JMS destination on server instances in the same WebLogic Server cluster are local to one another even if they are on separate machines, because the server instances in a WebLogic Server cluster each have a copy of the same cluster-wide JNDI tree.

Destinations that run under a non-BEA JMS provider are referred to as foreign. Foreign JMS providers have their own JNDI provider and foreign JMS objects do not share the same context with a WebLogic Server MDB—unless the foreign JMS objects are configured with wrappers to appear in the MDB's JNDI context. This approach is discussed in Whether to Use Wrappers.

The nature of a destination—local versus remote and WebLogic JMS versus non-BEA—governs the configuration alternatives available, and dictates to some extent how you configure these key elements in the message-driven-descriptor for the MDB in `weblogic-ejb-jar.xml`:

- `initial-context-factory`
- `provider-url`
- `destination-jndi-name`
- `connection-factory-jndi-name`

For foreign and remote destinations, the simplest configuration strategy is to use WebLogic Server JMS wrappers. Wrappers allow you to create a "symbolic link" between a JMS object in a third-party JNDI provider or in a different WebLogic Server cluster or domain, and an object in the local WebLogic JNDI tree.

For more information on when wrappers are appropriate, and the rules for configuring the `message-driven-descriptor` in `weblogic-ejb-jar.xml`, see these sections:

- Whether to Use Wrappers
- How to Set provider-url
- How to Set initial-context-factory
- How to Set destination-jndi-name
- How to Set connection-factory-jndi-name

To configure the elements in `message-driven-descriptor` for specific scenarios, see Common Destination Scenarios: Illustrations and Key Element Settings.

### Whether to Use Wrappers

Using wrappers means configuring a Foreign Connection Factory and a Foreign Destination that correspond to remote JMS objects (either non-BEA or WebLogic JMS) as entries in your local JNDI tree.

- The use of wrappers is recommended if you use a foreign JMS provider or a remote WebLogic JMS provider. For more information on JMS wrapper classes, see Simplified Access to Remote or Foreign JMS Providers in Programming WebLogic JMS.
- If you use a wrapper for either the connection factory or the destination, you must use a wrappers for both of these objects.

Whether or not you use the wrapper classes determines how you configure the `initial-context-factory` and `destination-jndi-name`, as described below.

### How to Set provider-url

provider-url specifies the URL of the JNDI service used by the JMS provider for the destination to which the MDB listens.

- If the JMS provider is local to the MDB (by definition, WebLogic JMS), do not specify `provider-url`.
- If the JMS provider is remote, whether WebLogic JMS or a foreign provider, and:

- You do not use wrappers, specify `provider-url`.
- You do use wrappers, do not specify `provider-url`. The URL is implicitly encoded in the wrapper.

### How to Set initial-context-factory

initial-context-factory identifies the class that implements the initial context factory used by the JMS provider.

- If your JMS provider is WebLogic JMS, whether local or remote, do not specify `initial-context-factory.`
- If your JMS provider is foreign, and

- you do not use wrappers, specify the initial context factory used by the JMS provider.
- you do use wrappers, do not specify `initial-context-factory`.

### How to Set destination-jndi-name

destination-jndi-name identifies the JNDI name of destination to which the MDB listens.

- If your JMS provider is local, specify the name bound in the local JNDI tree for the destination.
- If your JMS provider is foreign and:

- You do not use wrappers, specify the name of the destination, as bound in the foreign provider's JNDI tree.
- You do use wrappers, specify the name Foreign Destination you set up in your local JNDI tree that corresponds the remote or foreign destination.

### How to Set connection-factory-jndi-name

connection-factory-jndi-name identifies the JNDI name of the connection factory used by the JMS provider.

- If your JMS provider is local, do not specify `connection-factory-jndi-name` unless you have configured a custom connection factory that the MDB will use.

Custom connection factories are used when the default WebLogic Server connection factory does not satisfy your application requirements. For example, you might configure a custom connection factory in order to specify a particular desired value for the `MessagesMaximum` attribute. The procedure for configuring a connection factory is described in Configuring a JMS Connection Factory in Administration Console Online Help.

Note: If you configure a custom JMS connection factory for an MDB, be sure to set the `Acknowledge Policy` attribute to `Previous`, and that the `UserTransactionsEnabled` attribute is enabled.

- If your JMS provider is remote or foreign, and

- You do not use wrappers, specify the name of the connection factory used by the JMS provider, as bound in the remote JNDI tree.
- You do use wrappers, specify the Foreign Connection Factory you set up in your local JNDI tree that corresponds the remote or foreign JMS provider's connection factory.

### Common Destination Scenarios: Illustrations and Key Element Settings

The figures in this section illustrate common destination configurations. For remote and foreign destinations, scenarios with and without wrappers are included.

- A. Destination on a Local WebLogic JMS Server
- B. Destination On a Remote WebLogic JMS Server—No Wrappers
- C. Destination on Foreign JMS Server—No Wrappers
- D. Destination on a Remote WebLogic Server or Foreign JMS Server—With Wrappers

Table 7-1 summarizes how to configure the elements in the `message-driven-descriptor` stanza of `weblogic-ejb-jar.xml` for each scenario.

Figure 7-7 A. Destination on a Local WebLogic JMS Server

Figure 7-8 B. Destination On a Remote WebLogic JMS Server—No Wrappers

Figure 7-9 C. Destination on Foreign JMS Server—No Wrappers

Figure 7-10 D. Destination on a Remote WebLogic Server or Foreign JMS Server—With Wrappers

Table 7-1 Common Configuration Scenarios

| If destination is on... | Wrappers Configured? | destination-jndi-name | initial- context- factory | provider- url | connection- factory-jndi- name
--- | --- | --- | --- | --- | --- | ---
A | Local WebLogic JMS server | Not applicable for local WebLogic JMS server | Name of the local destination, as bound in local JNDI tree | Do not specify | Do not specify | Specify only if using a custom connection factory
B | Remote WebLogic JMS Server | No wrappers configured | Name of the remote destination, as bound in the remote JNDI tree | Do not specify | URL or cluster address for the remote WebLogic JMS Server | Specify only if using a custom connection factory on the remote provider
C | Foreign JMS Provider | No wrappers configured | Name of the remote destination, as bound in the remote JNDI tree | Name of remote initial context factory, as bound in remote JNDI tree | URL to access the foreign JMS provider | JNDI name of foreign connection factory
D | Remote Weblogic JMS Server or Foreign JMS server | Wrappers configured | The name of the Foreign Destination—as bound in your local JNDI tree —that maps to the remote or foreign destination | Do not specify | Do not specify | The name of the Foreign Connection Factory—as bound in your local JNDI tree —that maps to the remote or foreign connection factory

## Configuring Durable Topic Subscriptions

Durable subscriptions allow an MDB to receive messages that were delivered to a topic while the MDB was not connected.

### Configuring a Durable Topic Subscription for a Non-Clustered Server

Follow these instructions to configure a durable topic subscription for an MDB that is deployed to non-clustered server instances.

1. Configure the `destination-type` in `ejb-jar.xml` to `javax.jms.Topic`.
2. In the `message-driven-destination` stanza of `ejb-jar.xml`, set:

- `destination-type` to `javax.jms.Topic`
- `subscription-durability` to `Durable`.``

3. Configure the `ClientId` for the MDB, as desired:

If you configure your own connection factory to suit specific application requirements, as described in Configuring a JMS Connection Factory in Administration Console Online Help, you can define the `ClientID` for the MDB when you configure the connection factory.

If you set up your connection factory and do not assign it a `ClientID`, or if you use a default connection factory, as described in Using a Default Connection Factory in Administration Console Online Help, the MDB uses the value of jms-client-id in `weblogic-ejb-jar.xml` as its client ID. If `jms-client-id` is not specified, the default value is the ejb-name for the MDB.

### Configuring a Durable Topic Subscription for a Cluster

In a cluster, a JMS durable subscription is uniquely identified by the combination of an MDB's:

- connection ID—`ClientId` for the connection factory, and is unique within a cluster.
- subscription ID—the MDB's `jms-client-id`. The subscription ID must be unique on its topic, hence an MDB with a durable topic subscription cannot run on multiple server instances in a cluster. After a first instance of the MDB starts on a server instance in the cluster, an additional instance of the EJB can deploy successfully on another clustered server, but when the MDB starts, a conflict is detected and that instance of the MDB fails to fully connect to JMS.

To allow a durable subscriber MDB to run on multiple server instances in a cluster, where each MDB instance receives a copy of each topic message, each MDB instance should be deployed with a unique `jms-client-ID` or, if `jms-client-ID` is not specified, `ejb-name`.

Durable subscribers cannot subscribe directly to a WebLogic Server distributed destination topic, but must instead subscribe to the JNDI name of the destination topic physical members. There are two ways to accomplish this:

- Configure each distributed destination topic physical destination with a unique JNDI name and configure each durable subscriber MDB pool with a matching `destination-jndi-name`, or
- Configure each physical destination with the same JNDI name, and:

- Set the `JNDINameReplicated` attribute to `false` for each physical destination. For more information, see JMS Topic->Configuration->General in Administration Console Help.
- Ensure that there is only one physical destination per server instance.

## Configuring Message Handling Behaviors

These topics provide guidelines for behaviors related to message delivery:

- Ensuring Message Receipt Order
- Preventing and Handling Duplicate Messages
- Redelivery and Exception Handling

### Ensuring Message Receipt Order

Make sure that the MDB's business logic allows for asynchronous message processing. Do not assume that MDBs receive messages in the order the client issues them. To ensure that receipt order matches the order in which the client sent the message, you must do the following:

- Set max-beans-in-free-pool to 1 for the MDB. This ensures that the MDB is the sole consumer of the message.
- If your MDBs are deployed on a cluster, deploy them to a single node in the cluster, as illustrated in Figure 7-5.

To ensure message ordering in the event of transaction rollback and recovery, configure a custom connection factory with `MessagesMaximum` set to 1, and ensure that no redelivery delay is configured. For more information see Ordered Redelivery of Messages in Programming WebLogic JMS.

See Sun's documentation on the Interface MessageListener—`javax.jms.MessageListener.onMessage()`—for more information, at http://java.sun.com/j2ee/sdk_1.2.1/techdocs/api/javax/jms/MessageListener.html/.

### Preventing and Handling Duplicate Messages

A JMS producer expects an MDB to acknowledge received messages. If the MDB receives the message, but fails to send an acknowledgement, the JMS producer re-sends the same message.

Your MDB design should allow for the likelihood of duplicate messages. Duplicate messages can be undesirable in certain cases. For example, if an MDB's `onMessage()` method includes code to debit a bank account, receiving and processing that message twice would result in the account being debited twice. In addition, re-sending messages consumes more processing resources.

The best way to prevent delivery of duplicate messages is to use container-managed transactions. In a container-managed transaction, message receipt and acknowledgement occur within the transaction; either both happen or neither happens. However, while this provides more reliability than using bean-managed transactions, performance can be compromised because container-managed transactions use more CPU and disk resources.

If the MDB manages its own transactions, your `onMessage()` code must handle duplicate messages, as receipt and acknowledgement occur outside of a transaction. In some applications, receipt and processing of duplicate messages is acceptable. In other cases, such as the bank account scenario described above, if a transaction is bean-managed, the bean code must prevent processing of duplicate messages. For example, the MDB could track messages that have been consumed in a database.

Even if an MDB's `onMessage()` method completes successfully, the MDB can still receive duplicate messages if the server crashes between the time `OnMessage()` completes and the time the container acknowledges message delivery. Figure 7-11 illustrates this scenario.

Figure 7-11 Server Crash Between Completion of onMessage() and Container Delivery Acknowledgement

### Redelivery and Exception Handling

If an MDB is consuming a message when an unexpected error occurs, the MDB can throw a system exception that causes JMS to resend, delay, and then resend or give up, depending on how JMS is configured.

To force message redelivery for a transactional MDB, use the bean context to call`setRollbackOnly()`.

To force message redelivery for any MDB—transactional or non-transactional—you can throw an exception derived from the RuntimeException or Error thrown by the MDB. This causes the MDB instance to be destroyed and re-created, which incurs a performance penalty.

Configure the redelivery delay based on what type of task the MDB's `onMessage()` method is performing. In some cases, redelivery should be instantaneous, for example, in an application that posts breaking news to a newswire service. In other cases, for example, if the MDB throws an exception because the database is down, redelivery should not occur immediately, but after the database is back up.

Note: For fully ordered MDBs, do not set a redelivery delay.

For instructions on configuring a redelivery delay, and other JMS exception handling features that can be used with MDB see Managing Rolled Back, Recovered, Redelivered, or Expired Messages in Programming WebLogic JMS.

## Using the Message-Driven Bean Context

WebLogic Server calls `setMessageDrivenContext()` to associate the MDB instance with a container context. This is not a client context; the client context is not passed along with the JMS message.

To access the container context's properties from within the MDB instance, use the following methods from the `MessageDrivenContext` interface:

- `getCallerPrincipal())`—Inherited from the `EJBContext` interface and should not be called by MDB instances.
- `isCallerInRole()`—Inherited from the `EJBContext` interface and should not be called by MDB instances.
- `setRollbackOnly()`—Can only be used by EJBs that use container-managed transactions.
- `getRollbackOnly()`— Can only be used by EJBs that use container-managed transactions.
- `getUserTransaction()`—Can only be used by EJBs that use bean-managed transaction demarcations.

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 an MDB instance causes an `IllegalStateException`.

## Deferring Message Processing Until Completion of Boot Up

By default, an MDB starts processing messages as soon as it is deployed, even if its target WebLogic Server instance has not completed booting. This can cause an MDB application to access uninitialized services or applications during the boot process, and to fail. To avoid this problem, set `start-mdbs-with-application` to `false` in `weblogic-application.xml.`

Setting `start-mdbs-with-application` to `false` forces MDBs to defer starting until after the server instance opens its listen port, near the end of the server boot up process.

## Configuring a Security Identity for a Message-Driven Bean

When a message-driven bean (MDB) receives messages from a JMS queue or topic, the EJB container uses a Credential Mapping provider and a credential map to obtain the security identity—username and password—to use when establishing the JMS connection. This credential mapping occurs only once, when the MDB is started.

Once the EJB container is connected, the JMS provider uses the established security identity to retrieve all messages.

To configure a security identity for an MDB:

1. Create a WebLogic user for the MDB. See Users and Groups in Securing WebLogic Resources. Assign the user the username and password that the non-BEA JMS provider requires to establish a JMS connection.
2. In the `ejb-jar.xml` deployment descriptor, define a `run-as` identity for the MDB:

`<security-identity>
<run-as>
<role-name>admin</role-name>
</run-as>
`</security-identity>

3. In the `weblogic-ejb-jar.xml` deployment descriptor, map the `run-as` identity to the user defined in the previous step, as shown below:

`<security-role-assignment>
<role-name>admin</role-name>
<principal-name>``username``</principal-name>
</security-role-assignment>`

where `username` is the username for the user created in step 1.

4. If the JMS provider is not WebLogic JMS, configure the credential mapper:

Note: If the JMS provider is WebLogic JMS, it is not necessary to configure a credential mapper.

To configure the credential mapper:

1. In the left pane of the WebLogic Server Administration Console, expand Deployments to show the types of WebLogic resources that can be deployed.
2. Expand the Applications folder or the EJB folder to navigate to the application containing the MDB for which you want to create a credential map, right-click on it, and choose the Define Policies and Roles for Individual Beans... option.

The Define Policies and Roles for ... page lists the beans in the selected archive.

3. Click the [Define Credential Mappers] link for the MDB for which you want to create a credential map.

The Credential Mappings page is displayed.

4. Click the Configure a new Credential Mapping link.

The Create a new Credential Mapping... page is displayed.

5. Enter the WebLogic Server user name for the user you created in step 1, and the user name of the remote provider, and click Apply.

The Credential Mapping Page displays the new credential map. The map associates the WebLogic Server user name with the remote provider user name, which is shown as a hyperlink.

6. Click the Remote User hyperlink in the Credential Map table.

The `realm-->user` page displays the remote provider user name, and fields for entering and confirming the remote password.

7. Enter the password for the user in the Remote Password and Confirm Remote Password fields, and click Apply to save your changes.

# Migration and Recovery for Clustered MDBs

WebLogic Server supports migration and recovery for clustered MDB applications. In the event of failure, you can bring a JMS destination and MDBs back online. Design your application so that when a server instance fails, your application automatically migrates the JMS destination and its associated MDBs from the failed server in the cluster to an available server instance.

Note: An MDB can use the migratable service with clustered servers only. The migratable service cannot span multiple clusters.

After a MDB application migrates to another server, it reconnects to the migrated JMS destination and begins to receive messages from the JMS destination again.

MDBs do not have migratable targets. Instead, an MDB automatically detects the JMS Server migration target during deployment, and uses that as its migratable target. You must ensure that MDB are deployed everywhere that a JMS Server is deployed. You can do this in two ways:

- Deploy MDBs homogeneously to the cluster.
- Match an MDB's targets to the JMS migratable target list in the `config.xml` file for the server instance's domain. The MDB target server name must match the JMS migratable target list, or MDB migration will fail. For more information on configuring migratable targets, see Defining Migratable Target Servers in a Cluster in Using WebLogic Server Clusters.

In Figure 7-12, Managed Servers 1, 2 and 3 are in the same cluster. Managed Server 2 and Managed Server 3 are configured as Managed Server 1's migratable targets. In the event that Managed Server 1 fails, the JMS destination and MDB migrate to the next available Managed Server. If a Managed Server on the target list is unavailable, the destination and MDBs migrate to the next available Managed Server on the target list. For instance if Managed Server 2 is unavailable with Managed Server 1 fails, the JMS destination and MDB application migrate to Managed Server 3.

Figure 7-12 Migration of JMS Destination

For instructions on implementing the migratable service and for background information on WebLogic JMS migration and recovery services for clustered architectures, see JMS as a Migratable Service within a Cluster in Programming WebLogic JMS.

# Nutshell Summary: Deployment Elements for MDBs

This section lists key deployment elements that affect the behavior of MDBs:

Table 7-2 summarizes the deployment elements in the message-driven-descriptor stanza of `weblogic-ejb-jar.xml`.

Table 7-3 lists key deployment elements for MDBs in the `ejb` stanza of `weblogic-application.xml`.

Table 7-4 lists key J2EE deployment elements for MDBs that you configure in the `message-driven` stanza of `ejb-jar.xml`.

Table 7-2 weblogic-ejb-jar.xml Deployment Elements for MDBs

Element | Description | Default
--- | --- | ---
connection-factory-jndi-name | The JNDI name of the JMS ConnectionFactory that the message-driven EJB should look up to create its queues and topics. See How to Set connection-factory-jndi-name. | `weblogic.jms. MessageDriven BeanConnection Factory`
destination-jndi-name | The JNDI name used to associate a MDB with an actual JMS Queue or Topic deployed in the WebLogic Server JNDI tree. See How to Set destination-jndi-name. | N/A
dispatch-policy | This optional element allows you to specify a particular execute queue for the bean. See MDBs and the Free Pool. |
initial-beans-in-free-pool | The number of inactive instances of an MDB that exist in WebLogic Server when it is started. For more information, see MDBs and the Free Pool. | 0
initial-context-factory | The initial `contextFactory` that the EJB container uses to create its connection factories. See How to Set initial-context-factory. | `weblogic.jndi. WLInitialContext Factory`
jms-client-id | The client id for the a message-driven bean associated with a durable subscriber topic. See Defining the Client ID in Programming WebLogic JMS. | ejb-name
jms-polling-interval-seconds | The number of seconds between attempts by the EJB container to reconnect to a JMS destination that has become unavailable. See Migration and Recovery for Clustered MDBs | The EJB container attempts reconnection every 10 seconds
max-beans-in-free-pool | The maximum size of the free pool of inactive MDBs. See MDBs and the Free Pool | 1000
provider-url | The URL provider to be used by the `InitialContext`. Typically, this is the host:port. See How to Set provider-url. | t3://localhost:7001
trans-timeout-seconds | The maximum duration for an EJB's container-initiated transactions, after which the transaction is rolled back. See Configuring Transaction Management Strategy for an MDB. | 30 seconds

Table 7-3 weblogic-application.xml Elements for MDBs

Element | Description | Default
--- | --- | ---
start-mdbs-with-application | Controls then MDBs start processing messages. With default setting of true, an MDB starts processing message as soon as it is deployed, even if WebLogic Server has not completed booting. This can cause an MDB application to access uninitialized services or applications during boot up and fail. Set to false to defer message processing until after WebLogic Server opens its listen port. | true

Table 7-4 Key J2EE Deployment Elements for MDBs

Element | Description | Allowable Values
--- | --- | ---
acknowledge-mode | Specifies JMS message acknowledgment semantics for the `onMessage` method of a message-driven bean that uses bean managed transaction demarcation. | AUTO_ACKNOWLEDGE DUPS_OK_ACKNOWLEDGE
destination-type | Specifies the type of the JMS destination—the Java interface expected to be implemented by the destination. | javax.jms.Queue javax.jms.Topic
subscription-durability | Specifies whether a JMS topic subscription is intended to be durable or nondurable. | Durable NonDurable
transaction-type | Specifies an enterprise bean's transaction management type. Note: If transaction-type is set to Container, trans-attribute must be set to Required. | Bean Container
trans-attribute | Specifies how the container must manage the transaction boundaries when delegating a method invocation to an enterprise bean's business method. Set to `Required` for container-managed transactions. For more information, see Configuring Transaction Management Strategy for an MDB. | NotSupported Support Required RequiresNew Mandatory Never