bea.com | products | dev2dev | support | askBEA

Download Docs | Site Map | Glossary
Search

Programming WebLogic JMS

Using Transactions with WebLogic JMS

The following sections describe how to use transactions with WebLogic JMS:

- Overview of Transactions

- Using JMS Transacted Sessions

- Using JTA User Transactions

- Asynchronous Messaging Within JTA User Transactions Using Message Driven Beans

- Example: JMS and EJB in a JTA User Transaction

Note: For more information about the JMS classes described in this section, access the latest JMS Specification and Javadoc supplied on the Sun Microsystems' Java Web site at the following location: http://java.sun.com/products/jms/docs.html

Overview of Transactions

A transaction enables an application to coordinate a group of messages for production and consumption, treating messages sent or received as an atomic unit.

When an application commits a transaction, all of the messages it received within the transaction are removed from the messaging system and the messages it sent within the transaction are actually delivered. If the application rolls back the transaction, the messages it received within the transaction are returned to the messaging system and messages it sent are discarded.

When a topic subscriber rolls back a received message, the message is redelivered to that subscriber. When a queue receiver rolls back a received message, the message is redelivered to the queue, not the consumer, so that another consumer on that queue may receive the message.

For example, when shopping online, you select items and store them in an online shopping cart. Each ordered item is stored as part of the transaction, but your credit card is not charged until you confirm the order by checking out. At any time, you can cancel your order and empty your cart, rolling back all orders within the current transaction.

There are three ways to use transactions with JMS:

- If you are using only JMS in your transactions, you can create a JMS transacted session.

- If you are mixing other operations, such as EJB, with JMS operations, you should use a Java Transaction API (JTA) user transaction in a non-transacted JMS session.

- Use message driven beans.

To enable multiple JMS servers in the same JTA user transaction, or to combine JMS operations with non-JMS operations (such as EJB), the two-phase commit license is required. For more information, see Using JTA User Transactions.

The following sections explain how to use a JMS transacted session and JTA user transaction.

Note: When using transactions, it is recommended that you define a session exception listener to handle any problems that occur before a transaction is committed or rolled back, as described in Defining a Session Exception Listener.

If the acknowledge() method is called within a transaction, it is ignored. If the recover() method is called within a transaction, a JMSException is thrown.

Using JMS Transacted Sessions

A JMS transacted session supports transactions that are located within the session. A JMS transacted session's transaction will not have any effects outside of the session. For example, rolling back a session will roll back all sends and receives on that session, but will not roll back any database updates. JTA user transactions are ignored by JMS transacted sessions.

Transactions in JMS transacted sessions are started implicitly, after the first occurrence of a send or receive operation, and chained together—whenever you commit or roll back a transaction, another transaction automatically begins.

Before using a JMS transacted session, the system administrator should adjust the connection factory (Transaction Timeout) and/or session pool (Transaction) attributes, as necessary for the application development environment, as described in Managing JMS in the Administration Guide.

The following figure illustrates the steps required to set up and use a JMS transacted session.

Figure 5-1 Setting Up and Using a JMS Transacted Session

Step 1: Set Up JMS Application, Creating Transacted Session

Set up the JMS application as described in Setting Up a JMS Application, however, when creating sessions, as described in Step 3: Create a Session Using the Connection, specify that the session is to be transacted by setting the transacted boolean value to true.

For example, the following methods illustrate how to create a transacted session for the PTP and Pub/sub messaging models, respectively:

>        qsession = qcon.createQueueSession(
>          true,
>          Session.AUTO_ACKNOWLEDGE
>        );

>        tsession = tcon.createTopicSession(
>          true,
>          Session.AUTO_ACKNOWLEDGE
>        );

Once defined, you can determine whether or not a session is transacted using the following session method:

>        public boolean getTransacted(
>        ) throws JMSException

Note: The acknowledge value is ignored for transacted sessions.

Step 2: Perform Desired Operations

Perform the desired operations assoicated with the current transaction.

Step 3: Commit or Roll Back the JMS Transacted Session

Once you have performed the desired operations, execute one of the following methods to commit or roll back the transaction.

To commit the transaction, execute the following method:

>        public void commit(
>        ) throws JMSException

The commit() method commits all messages sent or received during the current transaction. Sent messages are made visible, while received messages are removed from the messaging system.

To roll back the transaction, execute the following method:

>        public void rollback(
>        ) throws JMSException

The rollback() method cancels any messages sent during the current transaction and returns any messages received to the messaging system.

If either the commit() or rollback() methods are issued outside of a JMS transacted session, a IllegalStateException is thrown.

Using JTA User Transactions

The Java Transaction API (JTA) supports transactions across multiple data resources. JTA is implemented as part of WebLogic Server and provides a standard Java interface for implementing transaction management.

You program your JTA user transaction applications using the javax.transaction.UserTransaction object to begin, commit, and roll back the transactions. When mixing JMS and EJB within a JTA user transaction, you can also start the transaction from the EJB, as described in "Transactions in EJB Applications" in Programming WebLogic JTA.

You can start a JTA user transaction after a transacted session has been started; however, the JTA transaction will be ignored by the session and vice versa.

WebLogic Server supports the two-phase commit protocol (2PC), enabling an application to coordinate a single JTA transaction across two or more resource managers. It guarantees data integrity by ensuring that transactional updates are committed in all of the participating resource managers, or are fully rolled back out of all the resource managers, reverting to the state prior to the start of the transaction.

Note: A separate 2PC transaction license is required to support this protocol. For transaction migration considerations related to 2PC, see Porting WebLogic JMS Applications.

Before using a JTA transacted session, the system administrator must configure the connection factories to support JTA user transactions by selecting the User Transactions Enabled check box, as described in "JMS Connection Factories" in the Administration Console Online Help.

The following figure illustrates the steps required to set up and use a JTA user transaction.

Figure 5-2 Setting Up and Using a JTA User Transaction

Step 1: Set Up JMS Application, Creating Non-Transacted Session

Set up the JMS application as described in Setting Up a JMS Application, however, when creating sessions, as described in Step 3: Create a Session Using the Connection, specify that the session is to be non-transacted by setting the transacted boolean value to false.

For example, the following methods illustrate how to create a non-transacted session for the PTP and Pub/sub messaging models, respectively.

>        qsession = qcon.createQueueSession(
>          false,
>          Session.AUTO_ACKNOWLEDGE
>        );

>        tsession = tcon.createTopicSession(
>          false,
>          Session.AUTO_ACKNOWLEDGE
>        );

Note: When a user transaction is active, the acknowledge mode is ignored.

Step 2: Look Up User Transaction in JNDI

The application uses JNDI to return an object reference to the UserTransaction object for the WebLogic Server domain.

You can look up the UserTransaction object by establishing a JNDI context (context) and executing the following code, for example:

>     UserTransaction xact = ctx.lookup("javax.transaction.UserTransaction");

Step 3: Start the JTA User Transaction

Start the JTA user transaction using the UserTransaction.begin() method. For example:

>     xact.begin();

Step 4: Perform Desired Operations

Perform the desired operations associated with the current transaction.

Step 5: Commit or Roll Back the JTA User Transaction

Once you have performed the desired operations, execute one of the following commit() or rollback() methods on the UserTransaction object to commit or roll back the JTA user transaction.

To commit the transaction, execute the following method:

>        xact.commit();

The commit() method causes WebLogic Server to call the Transaction Manager to complete the transaction, and commit all operations performed during the current transaction. The Transaction Manager is responsible for coordinating with the resource managers to update any databases.

To roll back the transaction, execute the following method:

>        xact.rollback();

The rollback() method causes WebLogic Server to call the Transaction Manager to cancel the transaction, and roll back all operations performed during the current transactions.

Once you call the commit() or rollback() method, you can optionally start another transaction by calling xact.begin().

Asynchronous Messaging Within JTA User Transactions Using Message Driven Beans

Because JMS cannot determine which, if any, transaction to use for an asynchronously delivered message, JMS asynchronous message delivery is not supported within JTA user transactions.

However, message driven beans provide an alternative approach. A message driven bean can automatically begin a user transaction just prior to message delivery.

For information on using message driven beans to simulate asynchronous message delivery, see "Designing Message-Driven Beans" in Programming WebLogic EJB.

Example: JMS and EJB in a JTA User Transaction

The following example shows how to set up an application for mixed EJB and JMS operations in a JTA user transaction by looking up a javax.transaction.UserTransaction using JNDI, and beginning and then committing a JTA user transaction. In order for this example to run, the User Transactions Enabled check box must be selected when the system administrator configures the connection factory.

Note: In addition to this simple JTA User Transaction example, refer to the example provided with WebLogic JTA, located in the WL_HOME\samples\server\src\examples\jta\jmsjdcb directory, where where WL_HOME is the top-level directory of your WebLogic Platform installation.

Import the appropriate packages, including the javax.transaction.UserTransaction package.

>     import java.io.*;
>     import java.util.*;
>     import javax.transaction.UserTransaction;
>     import javax.naming.*;
>     import javax.jms.*;

Define the required variables, including the JTA user transaction variable.

>     public final static String JTA_USER_XACT=
>     	"javax.transaction.UserTransaction";
>     	.
>     	.
>     	.

Step 1

Set up the JMS application, creating a non-transacted session. For more information on setting up the JMS application, refer to Setting Up a JMS Application.

>     //JMS application setup steps including, for example:

>       qsession = qcon.createQueueSession(false,
>     		    Session.CLIENT_ACKNOWLEDGE);

Step 2

Look up the UserTransaction using JNDI.

>     UserTransaction xact = (UserTransaction)
>                    ctx.lookup(JTA_USER_XACT);

Step 3

Start the JTA user transaction.

>     xact.begin();

Step 4

Perform the desired operations.

>     // Perform some JMS and EJB operations here.

Step 5

Commit the JTA user transaction.

>     xact.commit()