Skip Headers
Oracle TopLink Developer's Guide
10g Release 3 (10.1.3)
B13593-01
  Go To Documentation Library
Home
Go To Product List
Solution Area
Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
Next
Next
 

Integrating the Unit of Work With an External Transaction Service

To support transactions managed by an application server's external transaction service, TopLink supports external connection pools and external transaction controller classes for supported servers. This lets you incorporate external transaction service support into your application, and use the unit of work with transactions managed externally by the server. For more information, see "Unit of Work Transaction Demarcation".

To integrate a unit of work with an external transaction service, you must enable the use of an:

After you configure external connection pool and external transaction controller support, you use a unit of work in your TopLink application as you would typically, with few exceptions. This section describes these exceptions as follows:

Acquiring a Unit of Work with an External Transaction Service

You use a unit of work to commit changes to a data source even when using an external transaction service. To ensure that only one unit of work is associated with a given transaction, use the getActiveUnitOfWork method to acquire a unit of work as shown in Example 102-15.


Note:

Although there are other ways to commit changes to a data source using an external transaction service, Oracle recommends using the getActiveUnitOfWork method.

The getActiveUnitOfWork method searches for an existing external transaction:

  • If there is an active external transaction and a unit of work is already associated with it, return this unit of work.

  • If there is an active external transaction with no associated unit of work, then acquire a new unit of work, associate it with the transaction, and return it.

  • If there is no active external transaction in progress, return null.

If TopLink returns a unit of work that is not null, use it exactly as you would typically: the only exception is that you do not call the commit method (see "Using a Unit of Work When an External Transaction Exists").

If TopLink returns a null unit of work, start an external transaction either explicitly through the UserTransaction interface, or by acquiring a new unit of work using the acquireUnitOfWork method on the client session (see "Using a Unit of Work When No External Transaction Exists").

Example 102-15 Using a Unit of Work With an External Transaction Service

// Read in any pet
Pet pet = (Pet)clientSession.readObject(Pet.class);
UnitOfWork uow = clientSession.getActiveUnitOfWork();
    if (uow == null) {
        uow = clientSession.acquireUnitOfWork(); // Start external transaction
    }
    Pet petClone = (Pet) uow.registerObject(pet);
    petClone.setName("Furry");
    uow.commit(); // Ask external transaction controller to commit
                  // Ignored if transaction not started by TopLink

Using a Unit of Work When an External Transaction Exists

When getActiveUnitOfWork returns a unit of work that is not null, you are associated with an existing external transaction. Use the unit of work as usual.

As the external transaction was not started by the unit of work, issuing a commit on it will not cause the external transaction to be committed. The unit of work will defer to the application or container that began the transaction. When the external transaction does get committed by the container, TopLink receives synchronization callbacks at key points during the commit transaction.

The unit of work sends the required SQL to the database when it receives the beforeCompletion callback.

The unit of work uses the Boolean argument received from the afterCompletion callback to determine if the commit was successful (true) or not (false).

If the commit transaction was successful, the unit of work merges changes to the session cache. If the commit transaction was unsuccessful, the unit of work discards the changes.

Figure 102-2 shows the life cycle of a unit of work when an external transaction exists.

Figure 102-2 Unit of Work When an External Transaction Exists

unit of work
Description of "Figure 102-2 Unit of Work When an External Transaction Exists"

Using a Unit of Work When No External Transaction Exists

When the getActiveUnitOfWork method returns a null unit of work, there is no existing external transaction. You must start a new external transaction.

Do this either by starting an external transaction explicitly using the UserTransaction interface, or by acquiring a new unit of work using the acquireUnitOfWork method on the server session.

Use the unit of work as usual.

Once the modifications to registered objects are complete, you must commit the transaction either explicitly through the UserTransaction interface or by calling the unit of work commit method.

The transaction synchronization callbacks are then invoked on, and the database updates and cache merge occur based upon those callbacks.

Figure 102-3 Unit of Work When No External Transaction Exists

Unit of work
Description of "Figure 102-3 Unit of Work When No External Transaction Exists"

Using the Unit of Work to Handle External Transaction Timeouts and Exceptions

This section describes two common problems with external transactions:

External Transaction Commit Timeouts

When an external transaction is committed, the external transaction service expects each transaction owner to commit its portion of the overall transaction within a finite amount of time. If any individual transaction exceeds this timeout interval, the external transaction service will fail the specific transaction and roll it back (or mark it rollback only).

If your transaction is large and its commit transaction may exceed the external transaction service timeout interval, use UnitOfWork method writeChanges to write changes to the data source before committing the external transaction. This will reduce the time it takes for your part of the global transaction to commit.

For more information about the UnitOfWork method writeChanges, including restrictions and warnings, see "Writing Changes Before Commit Time".

External Transaction Commit Exceptions

When you use the unit of work with an external transaction service, commit exceptions may not be thrown until long after your application thread calls its UnitOfWork method commit and returns. In this case, commit exceptions are thrown to the client of the container-managed transaction (CMT) call, forcing the client to handle this server-side failure.

You can use the UnitOfWork method writeChanges to write changes to the data source before the external transaction commits. This allows your application thread to catch and handle most exceptions that could be thrown at the time the external transaction service commits the global transaction.

For more information about the UnitOfWork method writeChanges, including restrictions and warnings, see "Writing Changes Before Commit Time".

For more information on handling unit of work exceptions in general, see "Handling Exceptions".