When a transaction is created, it is associated with the thread that created it. As long as the transaction is associated with the thread, no other transaction can be created for that thread.

Sometimes, however, it is helpful to use multiple transactions in a single set of actions. For example, suppose a request performs some database operations, and in the middle of those operations, it needs to generate an ID for a database row that it is about to insert. It generates the ID by incrementing a persistent value that it stores in a separate database table. The request continues to do some more database operations, then ends.

All of this can be done in a single transaction. However, there is a potential problem with placing the ID generation within that transaction. After the transaction accesses the row used to generate the ID, all other transactions are locked out of that row until the original transaction ends. If generating IDs is a central activity, the ID generation can end up being a bottleneck. If the transaction takes a long time to complete, the bottleneck can become a serious performance problem.

This problem can be avoided by placing the ID generation in its own transaction, so that the row is locked for as short a time as possible. But if the operations before and after the ID generation must all be in the same transaction, breaking up the operations into three separate transactions (before ID generation, ID generation, and after ID generation) is not an option.

The solution is to use the JTA’s mechanism for suspending and resuming transactions. Suspending a transaction dissociates the transaction from its thread, leaving the thread without a current transaction. The transaction still exists and keeps track of the resources it has used so far, but any further work done by the thread does not use that transaction.

After the transaction is suspended, the thread can create a transaction. Any further work done by the thread, such as the generation of an ID, occurs in that new transaction.

The new transaction can end after the ID has been generated, thereby committing the changes made to the ID counter. After ending this transaction, the thread again has no current transaction. The previously suspended transaction can now be resumed, which means that the transaction is re-associated with the original thread. The request can then continue using the same transaction and resources that it was using before the ID generator was used.

The steps are as follows:

An application server can suspend and resume transactions through calls to the TransactionManager object; individual applications should not perform these operations directly. Instead, applications should use J2EE transaction demarcation facilities (described in the next section), and let the application server manage the underlying mechanics.