6 Programming and Configuring MDBs: Details

Examine the steps to program and configure MDBs.

The sections supplement the instructions in Programming and Configuring MDBs: Main Steps

Note:

This chapter uses a pre-EJB 3.0 deployment descriptor to illustrate basic MDB configuration. If you plan to use EJB 3.2 annotations, see also Deployment Elements and Annotations for MDBs. and Using EJB 3.2 Compliant MDBs, for the equivalent settings.

This chapter includes the following sections:

Configuring Destination Type

To configure the type of destination to which the MDB listens, set the destination-type element in the message-driven-destination element of ejb-jar.xml or by using an annotation.

Configuring Transaction Management Strategy for an MDB

Learn how to configure an MDB for managing its own transactions or deferring transaction management to the container.

To configure container-level transaction management using descriptor elements:

  • Set the transaction-type element in the message-driven element in the ejb-jar.xml file to Container.

  • Set the trans-attribute element in the container-transaction element in ejb-jar.xml to Required.

    Note:

    If transaction-type is set to Container, and trans-attribute is not set, the default transaction-attribute values are applied: required (for EJB 3.2 MDBs) and NotSupported (for MDBs prior to EJB 3.0). Oracle 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 element 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 container-level transaction management using EJB annotations:

  import javax.ejb.TransactionAttribute;
  import javax.ejb.TransactionAttributeType;
  ...
  @TransactionAttribute(value = TransactionAttributeType.REQUIRED)
  public void onMessage(Message msg) {
  ...

To configure bean-level transaction management using descriptor elements:

See Session in Developing JMS Applications for Oracle WebLogic Server.

Configuring MDBs for Destinations

Learn how to configure local and remote destination for the MDBs. Oracle WebLogic Server MDBs support WebLogic JMS destinations and foreign (non-Oracle) 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 Oracle WebLogic Server cluster. An MDB and a JMS destination on server instances in the same Oracle WebLogic Server cluster are local to one another even if they are on separate machines, because the server instances in a Oracle WebLogic Server cluster each have a copy of the same cluster-wide JNDI tree.

Destinations that run under a non-Oracle 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 Oracle WebLogic Server MDB—unless the foreign JMS objects are configured with mappings to appear in the MDB's JNDI context. This approach is discussed in Whether to Use Foreign JMS Server Mappings.

The nature of a destination—local versus remote and WebLogic JMS versus non-Oracle—governs the configuration alternatives available, and dictates to some extent how you configure these key elements in the message-destination-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 Oracle WebLogic Server foreign JMS server mappings. These mappings allow you to create a "symbolic link" between a JMS object in a third-party JNDI provider or in a different Oracle WebLogic Server cluster or domain, and an object in the local WebLogic JNDI tree.

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

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

Whether to Use Foreign JMS Server Mappings

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

Note:

The Foreign JMS Server mapping feature is not the same as the Foreign JNDI mapping feature. MDBs generally require that you use the Foreign JMS Server feature when mapping JMS resources into JNDI. The Foreign JNDI feature is meant for non-JMS resource types.
  • The use of mappings is recommended if you use a foreign JMS provider or a remote WebLogic JMS provider. For more information on JMS mapping classes, see "Simplified Access to Remote or Foreign JMS Providers" in Enhanced Support for Using WebLogic JMS with EJBs and Servlets in Developing JMS Applications for Oracle WebLogic Server.

  • If you use a mapping for either the connection factory or the destination, you must create and use mappings for each of these objects.

Whether or not you use mappings determines how you configure the initial-context-factory and destination-jndi-name.

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 mappings, specify provider-url.

    • You do use mappings, do not specify provider-url. The URL is implicitly encoded in the mapping.

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 mappings, specify the initial context factory used by the JMS provider.

    • you do use mappings, 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 mappings, specify the name of the destination, as bound in the foreign provider's JNDI tree.

    • You do use mappings, 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 Oracle 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 Configure connection factories in Oracle WebLogic Server 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 mappings, specify the name of the connection factory used by the JMS provider, as bound in the remote JNDI tree.

    • You do use mappings, specify the Foreign Connection Factory you set up in your local JNDI tree that corresponds to 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 mappings are included.

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

Figure 6-1 A. Destination on a Local WebLogic JMS Server

Description of Figure 6-1 follows
Description of "Figure 6-1 A. Destination on a Local WebLogic JMS Server"

Figure 6-2 B. Destination On a Remote WebLogic JMS Server—No Mappings

Description of Figure 6-2 follows
Description of "Figure 6-2 B. Destination On a Remote WebLogic JMS Server—No Mappings"

Figure 6-3 C. Destination on Foreign JMS Server—No Mappings

Description of Figure 6-3 follows
Description of "Figure 6-3 C. Destination on Foreign JMS Server—No Mappings"

Figure 6-4 D. Destination on a Remote Oracle WebLogic Server or Foreign JMS Server—With Mappings

Description of Figure 6-4 follows
Description of "Figure 6-4 D. Destination on a Remote Oracle WebLogic Server or Foreign JMS Server—With Mappings"

Table 6-1 Common Configuration Scenarios

Scenario If destination is on... Mappings 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 mappings 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 mappings 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

Mappings 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 Message Handling Behaviors

Examine the guidelines for behaviors related to message delivery:

This section includes the following topics:

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.

When using WebLogic JMS destinations, Oracle recommends using the Unit-of-Order feature if strict ordering is required. This feature enforces ordering under all circumstances without requiring modification of the MDB, enables concurrent processing of sub-orderings that exist within the same destinations, and can be enabled via configuration or programmatically as appropriate. See Using Message Unit-of-Order in Developing JMS Applications for Oracle WebLogic Server.

If you are not using WebLogic destinations with unit-of-order 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 6-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. Foreign vendors have different names for the equivalent setting. This setting controls the number of messages that a vendor may push to a consumer before the consumer completes processing of its current message.

See Ordered Redelivery of Messages in Developing JMS Applications for Oracle WebLogic Server.

See the Java documentation on the Interface MessageListenerjavax.jms.MessageListener.onMessage()—for more information, at http://download.oracle.com/javaee/1.2.1/api/javax/jms/MessageListener.html.

Preventing and Handling Duplicate Messages

A JMS vendor expects an MDB to acknowledge received messages. If the MDB receives the message, but fails to send an acknowledgement, the JMS vendor 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, 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 6-5 illustrates this scenario.

Figure 6-5 Server Crash Between Completion of onMessage() and Container Delivery Acknowledgement

Description of Figure 6-5 follows
Description of "Figure 6-5 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 recreated, which incurs a performance penalty. If you want to avoid the overhead of a destroy and recreate, while still throwing a runtime exception, you can use a WebLogic extension. Throw an instance of a weblogic.ejb.NonDestructiveRuntimeException, for example,

throw new weblogic.ejb.NonDestructiveRuntimeException("force redelivery");

You may want to configure a 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 that do not use the Unit-of-Order feature, 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 Developing JMS Applications for Oracle WebLogic Server.

Using the Message-Driven Bean Context

Oracle WebLogic Server calls setMessageDrivenContext() to associate the MDB instance with a container context. Alternatively, EJB 3.2 MDB applications can specify an annotation that injects the MDB 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.

Configuring Suspension of Message Delivery During JMS Resource Outages

To configure how an MDB behaves when the EJB container detects a JMS resource outage such as an MDB throwing the same exception ten times in succession.

You can configure:

  • An MDB to suspend the JMS connection and thereby stop receiving additional messages when the EJB container detects a JMS resource outage. If you choose this configuration option, you can specify:

    • The initial number of seconds the MDB should wait before it first resumes receiving messages.

    • The maximum number of seconds the MDB should wait before it resumes receiving messages.

  • An MDB to not suspend the JMS connection when the EJB container detects a JMS resource outage.

When a JMS connection is suspended, message delivery is suspended for all JMS sessions associated with the connection. By default, when it detects a JMS resource outage, the EJB container suspends an MDB's JMS connection for init-suspend-seconds.

Manually Suspending and Resuming Message Delivery

Administrators can use the WebLogic Server Administration Console to manually suspend and resume message delivery to deployed MDBs.

See Suspend and resume MDB JMS connections in Oracle WebLogic Server Administration Console Online Help.

Configuring the Number of Seconds to Suspend a JMS Connection

You can suspend a JMS connection during a resource outage, which can be defined as an MDB throwing the same exception 10 times in succession.

To suspend an MDB's JMS connection, configure the following elements in the weblogic-ejb-jar.xm file:

  • init-suspend-seconds—the initial amount of time, in seconds, to suspend a JMS connection when the EJB container detects a JMS resource outage. The default value is 5.

  • max-suspend-seconds—the maximum amount of time, in seconds, to suspended a JMS connection when the EJB container detects a JMS resource outage. The default value is 60.

How the EJB Container Determines How Long to Suspend a JMS Connection

The EJB container uses the following algorithm, based on the init-suspend-seconds and max-suspend-seconds, to determine the amount of time a JMS connection is suspended.

When the EJB container detects a JMS resource outage:

  1. The MDB's JMS connection is suspended for the amount of time specified by init-suspend-seconds.
  2. The connection is checked. If the resource is available, go to Step 12.
  3. If the value of init-suspend-seconds is greater than or equal to max-suspend-seconds, go to Step 9.
  4. The amount of time used to suspend the JMS connection, represented by Xseconds, is calculated by multiplying the time of the previous suspension by 2.
  5. The MDB's JMS connection is suspended for the amount of time specified by Xseconds.
  6. The connection is checked. If the resource is available, go to Step 12.
  7. If the value of init-suspend-seconds is greater than or equal to max-suspend-seconds, go to Step 9.
  8. Go to Step 4.
  9. The MDB's JMS connection is suspended for the amount of time specified by max-suspend-seconds.
  10. Check the connection. If the resource is available, go to Step 12.
  11. Go to Step 9.
  12. Continue processing.

Turning Off Suspension of a JMS Connection

If you do not want an MDB's JMS connection to be suspended when the EJB container detects a resource outage, set the value of max-suspend-seconds to 0. When the value of max-suspend-seconds is 0, the value of init-suspend-seconds is ignored.

Configuring a Security Identity for a Message-Driven Bean

When a MDB receives messages from a JMS queue or topic, the EJB container uses a Credential Mapping provider and a credential map to validate the security credentials to establish the JMS connection and to execute the onMessage() method. 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, Groups, and Security Roles in Securing Resources Using Roles and Policies for Oracle WebLogic Server. Assign the user the username and password that the non-Oracle 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. To create the security-identity, you must also define the security-role inside the assembly-descriptor element in ejb-jar.xml.
    <assembly-descriptor>
        <security-role>
            <role-name>jmsrole</role-name>
        </security-role>
        ....
    </assembly-descriptor>
    
  4. In the weblogic-ejb-jar.xml deployment descriptor, map the run-as identity to the user defined in Step 2, as follows:
    http://docs.oracle.com/middleware/1213/wls/WLACH/taskhelp/ejb/CreateEJBComponentCredentialMappings.html

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

  5. If the JMS provider is not WebLogic JMS, configure the credential mapper as described in Create EJB component credential mappings in Oracle WebLogic Server Administration Console Online Help.

    Note:

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

Using MDBs With Cross Domain Security

Learn how to configure cross domain security for MDBs.

You should consider the following guidelines when implementing MDBs:

  • If your MDBs must handle transactional messages, you must correctly configure either Cross Domain Security or Security Interop Mode for all participating domains.

    Keep all the domains used by your process symmetric with respect to Cross Domain Security configuration and Security Interop Mode. Because both settings are set at the domain level, it is possible for a domain to be in a mixed mode, meaning the domain has both Cross Domain Security and Security Interop Mode set. See Configuring Secure Inter-Domain and Intra-Domain Transaction Communication in Developing JTA Applications for Oracle WebLogic Server.

  • You must configure Cross Domain Security in cases where an MDB listens to a distributed destination in a different domain.

  • MDBs handling non-transactional messages do not require you to configure Cross Domain Security. However, you must configure Cross Domain Security for all the domains with which your process communicates, if Cross Domain Security is configured on one domain and the membership of the distributed destination that the MDB listens to in any domain changes. You must configure Cross Domain Security for cases where an MDB listens to a distributed destination that is in a different domain.

    A best practice is to keep all the domains used by your process symmetric with respect to Cross Domain Security configuration— that is, all domains use Cross Domain Security (or are on the appropriate exception lists) or none of the domains have Cross Domain Security configured. See Configuring Cross-Domain Security in Administering Security for Oracle WebLogic Server.

Configuring EJBs to Use Logical Message Destinations

You can declare logical message destinations in an EJB's deployment descriptor and map the logical message destinations to actual message destinations such as JMS queues or topics, or MDBs.

Note:

Logical destinations and application-scoped destinations are not commonly used and are for advanced users only. For most users, Oracle recommends using the methods discussed in Configuring MDBs for Destinations.

After you declare logical message destinations, you can then create message destination references that are linked to the logical message destinations. EJBs use the logical message destination name to perform a JNDI lookup and access the actual message destination. Logical JMS message destinations can be defined for individual MDBs or entire applications.

For information on how unresolved and unavailable message destinations are handled, see EJBs and Message Destination References in Developing Enterprise JavaBeans, Version 2.1, for Oracle WebLogic Server.

Configuring Logical JMS Message Destinations for Individual MDBs

You can configure logical JMS message destinations for individual MDBs.

To configure an MDB to use a logical message destination to link to an actual message destination:

  1. Declare the message destination in the message-destination-descriptor element in weblogic-ejb-jar.xml.
  2. Declare message destination references in the following elements in ejb-jar.xml:
    • message-destination-ref

    • message-destination-ref-name—the environment name used in the enterprise bean code for the message destination, relative to java:comp/env. For example, <message-destination-ref>jms/StockQueue</message-destination-ref>.

    • message-destination-type—the expected type of the referenced destination. For example, <message-destination-type>javax.jms.Queue</message-destination-type>.

    • message-destination-usage—specifies whether messages are consumed from the destination, produced for the destination, or both. For example, <message-destination-usage>Produces<message-destination-usage>.

    • message-destination-link—links the message destination reference to the actual message destination. This value must match the destination defined in message-destination-name in the weblogic-ejb-jar.xml file.

Configuring Application-Scoped Logical JMS Message Destinations

In this release of Oracle WebLogic Server, you can configure resources for applications. Resources that are configured for entire applications are called application-scoped resources. This section describes application-scoped logical JMS destinations for an EJB application. For additional information on application-scoped resources, such as JMS and JDBC, see Developing JMS Applications for Oracle WebLogic Server and Developing JDBC Applications for Oracle WebLogic Server.

Application-scoped resources, such as logical JMS message destinations, for EJBs apply to all MDBs in the application. You can override application-scoped JMS for specific MDBs by configuring the MDBs to use logical message destinations to link to actual message destinations, as described in Configuring Logical JMS Message Destinations for Individual MDBs.

To configure application-scoped JMS for EJBs:

  1. Declare the message destination in the message-destination-descriptor element in weblogic-ejb-jar.xml.
  2. Declare message destination references in the following elements in ejb-jar.xml:
  • message-driven

    • message-destination-type—the expected type of the referenced destination. For example, <message-destination-type>javax.jms.Queue</message-destination-type>.

    • message-destination-usage—specifies whether messages are consumed from the destination, produced for the destination, or both. For example, <message-destination-usage>Produces<message-destination-usage>.

    • message-destination-link—links the message destination reference to the actual message destination. For example, <message-destination-link>ExpenseProcessingQueue<message-destination-link>. This value must match the destination defined in message-destination-name in the weblogic-ejb-jar.xml file.

  • message-destination

    • message-destination-name—the name of the message destination. For example, <message-destination-name>ExpenseProcessingQueue<message-destination-name>. This value must match the destination defined in message-destination-name in weblogic-ejb-jar.xml.