An Overview of Message-Driven Bean Transactions


A transaction in JMS cannot include both producing and consuming messages as one logical unit of work, so both processes need to be treated within their own transactional contexts. The reason for this transactional separation is that a JMS client's (JMS Producer) transaction context does not flow with a JMS message, which implies that transactions initiated from a JMS client cannot be propagated to the message consumer.

If a transaction is started from a JMS Producer, the JMS message is not immediately propagated to a JMS destination (a queue or topic). Instead, the message is buffered in memory or stored in the JMS server's persistent storage device (a JDBC database or file). Only if the transaction commits will messages in the buffer be sent to the target JMS destination as part of transaction commit. However, if the JMS producer's transaction is rolled back, the JMS message is flushed from the buffer, and the message is not sent to the target JMS destination.

From a JMS Consumer's perspective, such as an MDB, if a transaction commits, the processed JMS message is removed from the JMS destination. However, if the transaction rolls back, the JMS message stays in the JMS destination and is redelivered as follows :

  • In a publish/subscribe message domain using a JMS topic, the message is redelivered to the same subscriber of the message.

    Note

    A consumer for a topic is referred to as a subscriber .


  • In a point-to-point (PTP) message domain using a JMS queue, the message is redelivered to the queue so that another consumer can process the message.

Specifying an MDB's Transaction Demarcation Type

When designing an MDB to use transactions, you must decide whether the bean will demarcate transactions programmatically via the onMessage() method (Bean-Managed Transaction, or BMT, demarcation) or whether the EJB container will perform transaction demarcation (Container-Managed Transaction, or CMT, demarcation).

You specify the transaction demarcation type of an MDB via the <transaction-type> element in the ejb-jar.xml deployment descriptor, for example:

  • <transaction-type>Bean</transaction-type> ” BMT demarcation

  • <transaction-type>Container</transaction-type> ” CMT demarcation

Note

The <transaction-type> element specifies how the EJB container must manage transactions for the onMessage() method on the arrival of a JMS message.

The onMessage() method is called in the scope of a transaction determined by the <transaction-type> element.


Container-Managed Transactions

With CMT demarcation, the EJB container demarcates transactions based on instructions in the ejb-jar.xml deployment descriptor. These instructions, called transaction attributes (as shown in Listing 22.6), tell the container whether it should run an MDB's onMessage() method in a new transaction started by the container or run the method without any transactions.

Listing 22.6 A Segment of ejb-jar.xml Showing Transaction Attributes for the onMessage() Method Using CMT
 <ejb-jar>   ...  <assembly-descriptor>     ...     <container-transaction>       <description>Transactions required for this method.</description>       <method>         <ejb-name>myMDB</ejb-name>         <method-name>onMessage</method-name>       </method>  <trans-attribute>  NotSupported  or  Required  </trans-attribute>  </container-transaction>     ...  </assembly-descriptor>   ... </ejb-jar> 

As shown in Listing 22.6, these are the only transaction attributes that are applicable to MDBs with CMT demarcations:

  • NotSupported ” The container calls the onMessage() method with an unspecified transaction context, which implies the method cannot be used to initiate transactions.

  • Required ” The EJB container automatically starts a new transaction before dequeuing the JMS message and before calling the onMessage() method. Therefore, the EJB container calls onMessage() with a valid transaction context and a message receipt from the JMS destination. The container attempts to commit the transaction after the onMessage() method has completed. For MDBs that use CMT, the container automatically acknowledges a message receipt to the WebLogic JMS Server after the transaction commits.

Avoiding Poison Messages with Container-Managed MDBs

If the onMessage() method does not successfully complete or the container rolls back the transaction, the container does not acknowledge a message receipt; the message remains in its associated JMS destination and is delivered again to the MDB. When a message continuously gets redelivered to a container-managed MDB only to be rolled back, the message is referred to as a poison message . Poison messages can have a negative impact on WebLogic JMS Server's performance. They also consume MDB resources from the free pool, so they should removed from the JMS destination when they're detected . WebLogic JMS Server has built-in support for detecting message redelivery attempts and for redirecting a message to an error destination when redelivery attempts for the message reach a specific limit. You can configure WebLogic JMS Server to manage poison messages via the Administration Console, as shown in Figure 22.12.

Figure 22.12. Manage poison messages via the Administration Console.

graphics/22fig12.jpg

Bean-Managed Transactions

When an MDB uses BMT demarcation, you must use the EJBContext.getUserTransaction() callback to obtain a reference to the javax.transaction.UserTransaction object. After you have an instance of javax.transaction.UserTransaction , you can mark the beginning of a transaction with the begin() method, and end the transaction with the commit() or rollback() method. If the transaction commits, a message acknowledgement is sent to WebLogic JMS Server based on the value the <acknowledge-mode> element specifies in the ejb-jar.xml deployment descriptor: Auto-acknowledge or Dups-ok-acknowledge . The skeleton code for an onMessage() method using BMT is shown in Listing 22.7.

Listing 22.7 Skeleton Code for the onMessage() Method Showing How to Use BMT
 public void onMessage(Message msg) {     try {     // get the UserTranaction from the EJB context     javax.transaction.UserTransaction mdbtx = mdb_context.getUserTransaction();     // start the transaction       mdbtx.begin();       do some processing...       if (OK Condition)       {         // commit the transaction         mdbtx.commit();       }       else       {         // roll back transaction         mdbx.rollback();       }     } } 


BEA WebLogic Platform 7
BEA WebLogic Platform 7
ISBN: 0789727129
EAN: 2147483647
Year: 2003
Pages: 360

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net