Default Transactional Behavior in WebLogic Workshop

Each time a method or callback in your web service is called, WebLogic Workshop begins an implicit transaction that is associated with that method or callback. If the method or callback returns successfully, without throwing an exception, the transaction is committed. If the method or callback fails, the transaction is rolled back, and none of the changes that have happened within the transactional context are committed. This topic explains basic transactional behavior in WebLogic Workshop.

The Transactional Context

Included within the transactional context are the start and finish methods of a conversation, changes to the state of an ongoing conversation, and calls to methods of the Database, Timer, EJB, and JMS controls. If a method fails at any point, operations performed by the method, changes to the conversation state, and operations performed by any of these controls will be rolled back to their original state. For example, if the web service method calls a method on a Database control to create a table, and the web service method fails subsequently on a different call, the database operation will be rolled back. If a call to a method that starts a conversation fails, the transaction rolls back and the conversation is not initiated. If a call to a method that ends a conversation fails, the transaction rolls back and the conversation is not completed.

Any operations performed by a Web Service control are not included in the transactional context of the web service method or callback. If the web service method fails following a successful call to a method or callback on a Web Service control, the operation performed by the Web Service control will not be rolled back.

If a method on a JCX control is message-buffered, the queue on that method is included in the transactional context of the web service method. That is, if a failure occurs after a call to a buffered method on the control, the method will never be called. This holds true for any control that is a JCX file. To ensure that a method participages in the transactional context, set the enable attribute of the method's @common:message-buffer annotation to true. Note that a buffered method must return void.

If an exception occurs in a web service method that participates in a conversation, the transaction is rolled back as expected, and the effect on the conversation state depends on whether the the exception is handled. If the exception is handled, the conversation state is updated; if not, the conversation state is not updated. Specifically, if an unhandled exception occurs in a method that starts a conversation, the conversation is never started; if an unhandled exception occurs in a method that continues or finishes a conversation, the conversation state is not updated.

To ensure that conversation state is updated whether or not the method succeeds, handle the exception without rethrowing it, as shown in the following example:

/**
 * @common:operation
 * @jws:conversation phase="finish"
 */
public void finish()
{
    try
    {
         bank.cancelAnalysis()
    }
    catch (ProxyException pe)
    {
        // Log the error, but don't rethrow.
    }
}

Whether a particular control used by your web service actually participates in the service’s transaction depends on how the resource exposed by the control is configured. For example, a database exposed by a Database control must be configured to use a transactional connection pool in order to participate in the web service’s transaction. Enterprise JavaBeans can support an existing transaction or be configured to create their own transaction rather than to participate in the web service’s transaction. When you’re building your service, you should take into account how the resources that you’re using are configured to participate in distributed transactions.

Some third-party controls can participate in transactions and interact with transactional resources; others cannot. Check with your control vendor if you need to understand how a third-party control behaves with respect to transactions.

Transactions and Connection Pools

WebLogic Workshop uses a built-in connection pool, cgPool, to track conversation state. If you create a Database control that uses a data source created on a different connection pool, you may get an error that stating that you already have a transactional context created in the first pool (the one that Workshop is using to track state), and you cannot use data sources from two different connection pools within the same transaction. You can solve this problem by using a transactional (XA) driver, but doing so may add unnecessary overhead to your application. Instead, you can share a single connection pool across multiple data sources.

To share a connection pool across multiple data sources, you can modify the properties of cgPool to point to your application database (the one on which the Database control is based). Alternately, you can create a new connection pool that points to your application database, and modify cgDataSource, which is the data source in cgPool that's used to manage WebLogic Workshop's internal state, to use your new connection pool. This ensures that WebLogic Workshop's internal state tracking and your application are using the same connection pool, and transactions will automatically be coordinated across the two. An application designed in this manner will run faster than one that uses an XA driver for the same task.

Handling Transaction Time-out

By default, the implicit transaction initiated by a web service times out after five minutes. If your web service performs a database operation that takes longer than five minutes, the transaction may time out before the operation is complete. One way to solve this problem is to use a data source that is not configured to be transactional. Another approach is to change the property that specifies the transaction timeout interval. The following code snippet shows how to set this property:

import javax.transaction.Transaction;
import weblogic.transaction.TxHelper;
import weblogic.transaction.internal.TransactionImpl;
...
Transaction tx = TxHelper.getTransaction();
if (tx instanceof TransactionImpl)
    {
    ((TransactionImpl)tx).setProperty(weblogic.transaction.internal.Constants.TX_TIMEOUT_SECS_PROPNAME,
                    new Integer(nSeconds));
    }

For more information, see the following topics on e-docs.bea.com:

Managing Transactions

Programming Weblogic JTA

Related Topics

Transaction Basics