Most developers are familiar with the concept of a transaction. In its simplest definition, a transaction is a set of actions that is treated as an atomic unit; either all actions take place (the transaction commits), or none of them take place (the transaction rolls back).

A classic example is a transfer from one bank account to another. The transfer requires two separate actions. An amount is debited from one account, then credited to another account. It is unacceptable for one of these actions to take place without the other. If the system fails, both actions must be rolled back, even if the system failed in between the two actions. This means that both actions must take place within the same transaction.

Within an application server, transaction management is a complex task, because a single request might require several actions to be completed within the same transaction. A typical J2EE request can pass through many components—for example, servlets, JSPs, and EJBs. If the application is responsible for managing the transaction, it must ensure that the same transactional resource (typically a JDBC connection) is passed to all of those components. If more than one transactional resource is involved in the transaction, the problem becomes even more complex.

Fortunately, managing transactions is one of the primary tasks of an application server. The application server keeps track of transactions, remembering which transaction is associated with which request, and what transactional resources (such as JDBC or JMS connection) are involved. The application server takes care of committing those resources when the transaction ends.

As a result, transactional programming is much simpler for applications. Ideally, the application components do not need to be aware that transactions are used at all. When an application component needs to access a database, it just asks the application server for a JDBC connection, performs its work, then closes the connection. It is the application server’s responsibility to make sure that all components involved in a request get the same connection, even though each component is coded to open and close its own separate connection. The application server does this behind the scenes, by mapping threads to transactions and transactions to connections.

When the application has completed the set of operations, it can commit the transaction that it created. It is the application server’s responsibility to know which JDBC connections were used while that transaction was in place, and to commit those connections as a result.

Transactions are often associated with requests, but they can be associated with other sequences of actions performed in a single thread. For example, the Oracle ATG Web Commerce scheduler is used to notify components to perform some kind of action at specified times. When a component receives a notification, it can start a transaction, thus ensuring that its operations are treated as an a unit. When the component has completed its work, it can commit the transaction, thereby committing all of these operations.