Sun GlassFish Enterprise Server v3 Application Development Guide

Chapter 15 Using the Transaction Service

The Java EE platform provides several abstractions that simplify development of dependable transaction processing for applications. This chapter discusses Java EE transactions and transaction support in the Sun GlassFishTM Enterprise Server.

This chapter contains the following sections:

For more information about the JavaTM Transaction API (JTA) and Java Transaction Service (JTS), see Chapter 21, Administering Transactions, in Sun GlassFish Enterprise Server v3 Administration Guide and the following sites: http://java.sun.com/products/jta/ and http://java.sun.com/products/jts/.

You might also want to read Chapter 27, Transactions, in The Java EE 6 Tutorial, Volume I.

Transaction Resource Managers

There are three types of transaction resource managers:

For details about how transaction resource managers, the transaction service, and applications interact, see Chapter 21, Administering Transactions, in Sun GlassFish Enterprise Server v3 Administration Guide.

Transaction Scope

A local transaction involves only one non-XA resource and requires that all participating application components execute within one process. Local transaction optimization is specific to the resource manager and is transparent to the Java EE application.

In the Enterprise Server, a JDBC resource is non-XA if it meets either of the following criteria:

A transaction remains local if the following conditions remain true:

Transactions that involve multiple resources or multiple participant processes are distributed or global transactions. A global transaction can involve one non-XA resource if last agent optimization is enabled. Otherwise, all resourced must be XA. The use-last-agent-optimization property is set to true by default. For details about how to set this property, see Configuring the Transaction Service.

If only one XA resource is used in a transaction, one-phase commit occurs, otherwise the transaction is coordinated with a two-phase commit protocol.

A two-phase commit protocol between the transaction manager and all the resources enlisted for a transaction ensures that either all the resource managers commit the transaction or they all abort. When the application requests the commitment of a transaction, the transaction manager issues a PREPARE_TO_COMMIT request to all the resource managers involved. Each of these resources can in turn send a reply indicating whether it is ready for commit (PREPARED) or not (NO). Only when all the resource managers are ready for a commit does the transaction manager issue a commit request (COMMIT) to all the resource managers. Otherwise, the transaction manager issues a rollback request (ABORT) and the transaction is rolled back.

Configuring the Transaction Service

You can configure the transaction service in the Enterprise Server in the following ways:

Changing keypoint-interval, retry-timeout-in-seconds, or timeout-in-seconds does not require a server restart. Changing other attributes or properties requires a server restart.

The Transaction Manager, the Transaction Synchronization Registry, and UserTransaction

To access a UserTransaction instance, you can either look it up using the java:comp/UserTransaction JNDI name or inject it using the @Resource annotation.

If you need to access the javax.transaction.TransactionManager implementation, you can look up the Enterprise Server implementation of this interface using the JNDI name java:appserver/TransactionManager. If possible, you should use the javax.transaction.TransactionSynchronizationRegistry interface instead, for portability. You can look up the implementation of this interface by using the JNDI name java:comp/TransactionSynchronizationRegistry. For details, see the Javadoc page for Interface TransactionSynchronizationRegistry and Java Specification Request (JSR) 907.

Accessing a DataSource using the Synchronization.beforeCompletion() method requires setting Allow Non Component Callers to true. The default is false. For more information about non-component callers, see Allowing Non-Component Callers.

Transaction Logging

The transaction service writes transactional activity into transaction logs so that transactions can be recovered. You can control transaction logging in these ways:

Storing Transaction Logs in a Database

For multi-core machines, logging transactions to a database may be more efficient.

To log transactions to a database, follow these steps:

  1. Create a JDBC connection Pool, and set the non-transactional-connections attribute to true.

  2. Create a JDBC resource that uses the connection pool and note the JNDI name of the JDBC resource.

  3. Create a table named txn_log_table with the schema shown in Table 15–1.

  4. Add the db-logging-resource property to the transaction service. For example:


    asadmin set server-config.transaction-service.property.db-logging-resource="jdbc/TxnDS"

    The property's value should be the JNDI name of the JDBC resource configured previously.

  5. To disable file synchronization, use the following asadmin create-jvm-options command:


    asadmin create-jvm-options -Dcom.sun.appserv.transaction.nofdsync
  6. Restart the server.

For information about JDBC connection pools and resources, see Chapter 14, Using the JDBC API for Database Access. For more information about the asadmin create-jvm-options command, see the Sun GlassFish Enterprise Server v3 Reference Manual.

Table 15–1 Schema for txn_log_table

Column Name 

JDBC Type 

LOCALTID

BIGINT

SERVERNAME

VARCHAR(n)

GTRID

VARBINARY

The size of the SERVERNAME column should be at least the length of the Enterprise Server host name plus 10 characters.

The size of the GTRID column should be at least 64 bytes.

To define the SQL used by the transaction manager when it is storing its transaction logs in the database, use the following flags:

-Dcom.sun.jts.dblogging.insertquery=sql statement
-Dcom.sun.jts.dblogging.deletequery=sql statement

The default statements are as follows:

-Dcom.sun.jts.dblogging.insertquery=insert into txn_log_table values ( ?, ? , ? )
-Dcom.sun.jts.dblogging.deletequery=delete from txn_log_table where localtid = ? and servername = ?

To set one of these flags using the asadmin create-jvm-options command, you must quote the statement. For example:

create-jvm-options '-Dcom.sun.jts.dblogging.deletequery=delete from txn_log_table where gtrid = ?'

You can also set JVM options in the Administration Console. Select the Application Server component and the JVM Settings tab. These flags and their statements must also be quoted in the Administration Console. For example:

'-Dcom.sun.jts.dblogging.deletequery=delete from txn_log_table where gtrid = ?'

Recovery Workarounds and Limitations

The Enterprise Server provides workarounds for some known issues with transaction recovery implementations.


Note –

These workarounds do not imply support for any particular JDBC driver.


Oracle Thin Driver

In the Oracle thin driver, the XAResource.recover method repeatedly returns the same set of in-doubt Xids regardless of the input flag. According to the XA specifications, the Transaction Manager initially calls this method with TMSTARTSCAN and then with TMNOFLAGS repeatedly until no Xids are returned. The XAResource.commit method also has some issues.

To disable the Enterprise Server workaround, set the oracle-xa-recovery-workaround property value to false. For details about how to set this property, see Configuring the Transaction Service. This workaround is used unless explicitly disabled.

Manual Transaction Recovery Limitation

Manual transaction recovery cannot recover transactions after a server crash. Manual operations are intended for cases when a resource dies unexpectedly while the server is running. In case of a server crash, only start-up recovery can recover in-doubt transactions.