Oracle8i Enterprise JavaBeans Developer's Guide and Reference Release 3 (8.1.7) Part Number A83725-01 |
Library | Service | Contents | Index

## Transaction Overview

Transactions manage changes to multiple databases within a single application as a unit of work. That is, if you have an application that manages data within one or more databases, you can ensure that all changes in all databases are committed at the same time if they are managed within a transaction.

Transactions are described in terms of ACID properties, which are as follows:

- Atomic: all changes to the database made in a transaction are rolled back if any change fails.

- Consistent: the effects of a transaction take the database from one consistent state to another consistent state.

- Isolated: the intermediate steps in a transaction are not visible to other users of the database.

- Durable: when a transaction is completed (committed or rolled back), its effects persist in the database.

The JTA implementation, specified by Sun Microsystems, relies heavily on the JDBC 2.0 specification and XA architecture. The result is a complex requirement on applications in order to ensure that the transaction is managed completely across all databases. Sun Microsystems's specifies Java Transaction API (JTA) 1.0.1 and JDBC 2.0 on `http://www.javasoft.com`.

You should be aware of the following when using JTA within the Oracle8i environment:

- Global and Local Transactions

- Demarcating Transactions

- Transaction Context Propagation

- Two-Phase Commit

- Enlisting Resources

- JTA Limitations

### Global and Local Transactions

Whenever your application connected to a database using JDBC or a SQL server, you were creating a transaction. However, the transaction involved only the single database and all updates made to the database were committed at the end of these changes. This is referred to as a local transaction.

A global transaction involves a complicated set of management objects--objects that track all of the objects and databases involved in the transaction. These global transaction objects--`TransactionManager` and `Transaction`--track all objects and resources involved in the global transaction. At the end of the transaction, the `TransactionManager` and `Transaction` objects ensure that all database changes are atomically committed at the same time.

### Demarcating Transactions

A transaction is said to be demarcated, which means that each transaction has a definite start and stop point. For example, in an interactive tool such as SQL*Plus, each SQL DML statement implicitly begins a new transaction, if it is not already part of a transaction. A transaction ends when a SQL COMMIT or ROLLBACK statement is issued.

The important designation for a transaction depends on the originator of the transaction and whether explicitly or implicitly demarcated:

- Transaction originator--In a distributed object application, transactions are demarcated differently if the originator is the client or the server. Where the transaction originates defines the transaction as client-side demarcated or server-side demarcated. See "JTA Client-Side Demarcation" and "JTA Server-Side Demarcation" for more information.

- Explicit or implicit demarcation

  - Explicit demarcation means that either the client or bean-managed transactional bean programmatically demarcates the transaction by executing the appropriate `begin` or `commit` methods. Explicit demarcation is discussed further in both "JTA Client-Side Demarcation" and "JTA Server-Side Demarcation".

  - Implicit demarcation is specified within the deployment descriptor for container-managed transactional beans. The container begins and ends the transaction depending on the configuration for the bean within the deployment descriptor. See "JTA Server-Side Demarcation" for more information on implicit demarcation.

    Note: The originating client or object that starts the transaction must also end the transaction with a commit or rollback. However, the originator can end the transaction in a different method than the originating method. For example, if the client begins the transaction, calls out to a server object, the client must end the transaction after the invoked method returns. The invoked server object cannot end the transaction.

### Container or Bean Managed Transactions

Enterprise JavaBeans can specify whether the bean demarcates and manages any transactions within itself or whether the container should demarcate and manage the transaction.

#### Container-Managed Transactional

The bean specifies itself as container-managed transactional; it does not have any transactional implementation within its methods. All transactional logic is executed by the container based on the transactional attribute specified in the EJB deployment descriptor. See the following for more information:

- "Defining Transactions" describes the EJB deployment descriptor specification for container-managed transactions.

- "Propagating the Transactional Context to Container-Managed Transactional Beans" describes what the container performs depending on the deployment descriptor specified transactional attribute.

#### Bean-Managed Transactional

If the bean specifies itself as bean-managed transactional, it has the following responsibility:

- All global transactions are started within itself. It cannot accept a transactional context from any other object--client or server. Thus, a bean-managed transactional bean is not involved in any other object's global transaction. If the invoking object is involved in a transaction, that transaction is suspended while the bean-managed transactional bean is executing. The invoking object's transaction is resumed when the bean-managed transactional bean returns.

- If the bean wants another object involved in the global transaction, it must invoke a container-managed bean with a transactional attribute that accepts propagated transaction contexts.

- The bean can request resources to be automatically enlisted in the same manner as detailed in "Enlisting Resources".

### Transaction Context Propagation

When you begin a transaction within either a client or a server instance, JTA denotes the originator in the transaction manager. As the transaction involves more objects and resources, the transaction manager tracks all of these objects and resources in the transaction and manages the transaction for these entities.

When an object calls another object, in order for the invoked object to be included in the transaction, JTA propagates the transaction context to the invoked object. Propagation of the transaction context is necessary for including the invoked object into the global transaction.

As shown in Figure 7-1, if the client begins a global transaction, calls a server object in the database, the transaction context is propagated to the server object. If the server object supports transactions, this object is attached to the transaction manager as involved in the global transaction. If this server object invokes another server object, within the same or a remote database, the transaction context is propagated to this object as well. This ensures that all objects that are supposed to be involved in the global transaction are tracked by the transaction manager.

Note: Since all server objects are loaded within a database, JTA automatically enlists the database as a resource included in the global transaction along with the server object.

#### Figure 7-1 Connection to an Object over IIOP

#### Propagating the Transactional Context to Container-Managed Transactional Beans

The definition of the transaction attribute within the EJB deployment descriptor for container-managed transactional beans determines whether the global transaction context is propagated to the server object. The following table lists each transaction attribute and the behavior that occurs for each server object type and for any resources.

##### Table 7-1 Effect of Transactional Attributes for Container-Managed Transactional Beans

Deployment Transaction Attribute | Client Transaction Demarcation | Behavior for Target Server Object or Resource (Database)
--- | --- | ---
`NotSupported` | Does not start transaction | No transaction started
Starts transaction | Invoker's transaction is suspended while the bean executes, resumed when control returns to the invoker.
`Required` | Does not start transaction | A new transaction is started
Starts transaction | Invoker's transaction context is propagated. Server object and the local resource joins the transaction.
`Supports` | Does not start transaction | No transaction started
Starts transaction | Invoker's transaction context is propagated. Server object and the local resource joins the transaction.
`RequiresNew` | Does not start transaction | A new transaction is started
Starts transaction | Invoker's transaction is suspended. A new transaction is started and committed before returning to the invoker. The invoker's transaction is resumed when control is returned to it.
`Mandatory` | Does not start transaction | Error is returned. This object requires a transactional context.
Starts transaction | Invoker's transaction context is propagated. Server object and the local resource joins the transaction.
`Never` | Does not start transaction | No transaction is started
Starts transaction | An error is returned. This object cannot be called from any object--client or server--that is involved in a transaction.

### Enlisting Resources

Each resource, including databases, that you want managed in the global transaction must be enlisted. The Oracle8i JTA implementation automatically enlists all databases if you open a JDBC connection to the database within the context of a global transaction. The Oracle8i JDBC Developer's Guide contains more information on how to open a JDBC connection to a database within a transaction.

JTA automatically enlists a database resource when one of the following occurs:

#### Enlisting the Local Database

The following JDBC methods are used within a local transaction for accessing the local database. In order to ensure that the statements are included within a global transaction, execute these methods and subsequent SQL statements after the global transaction has started.

##### Table 7-2 JDBC Methods Used For Enlisting Databases

Retrieval Method | Description
--- | ---
`OracleDriver(). defaultConnection()` | Pre-JDBC 2.0 method for retrieving the local connection. If using the #`sqlj` macro for updating your database tables, note that this macro invokes the `defaultConnection` method for you.
`DriverManager.getConnection ("jdbc:oracle:kprb:")` | Pre-JDBC 2.0 method for retrieving the local connection.
`DataSource.getConnection ("jdbc:oracle:kprb:")` | JDBC 2.0 method for retrieving connections to the local databases.

Note: You should use either the JDBC 2.0 method or the pre-2.0 JDBC methods for retrieving connections to databases. You must not mix both methods within the same bean.

An example for each of these methods of automatic enlistment are detailed in "Enlisting Resources on the Server-side".

#### Enlisting a Remote Database

An object--client or server object--can only enlist a database within the global transaction through JDBC 2.0 methods within the `DataSource` object. The `getConnection` method must be invoked after the `begin` method of the `UserTransaction` object.

If your transaction involves more than one database, you must specify an Oracle8i database as the two-phase commit engine. See "Configuring Two-Phase Commit Engine" for more information.

### Two-Phase Commit

One of the primary advantages for a global transaction is the number of objects and database resources managed as a single unit within the transaction. If your global transaction involves more than one database resource, you must specify a two-phase commit engine, which is an Oracle8i database designated to manage the changes to all databases within the transaction. The two-phase commit engine is responsible for ensuring that when the transaction ends, all changes to all databases are either totally committed or fully rolled back.

On the other hand, if your global transaction has multiple server objects, but only a single database resource, you do not need to specify a two-phase commit engine. The two-phase commit engine is required only to synchronize the changes for multiple databases. If you have only a single database, single-phase commit can be performed by the transaction manager.

Note: Your two-phase commit engine can be any Oracle8i database. It can be the database where your server object exists, or even a database that is not involved in the transaction at all. See "Configuring Two-Phase Commit Engine" for a full explanation of the two-phase commit engine setup.

Figure 7-2 shows three databases enlisted in a global transaction and another database that is designated as the two-phase commit engine. All databases, including the local database, are automatically enlisted when a JDBC connection is opened after the global transaction starts. See "Enlisting Resources" for more information on database enlistment.

When the global transaction ends, the two-phase commit engine ensures that all changes made to the databases A, B, and the local are committed or rolled back simultaneously.

#### Figure 7-2 Two-Phase Commit for Global Transactions

### JTA Summary

The following sections summarize the details for demarcating the transaction and enlisting the database in the transaction. These details are explained and demonstrated in the rest of the chapter. However, these tables provide a reference point for you.

##### Table 7-3 Environment Setup For Transactional Object Retrieval

Source | Qualifiers | Environment Setup
--- | --- | ---
Setup includes authentication information, namespace URL, and OracleDriver registration.
Client | retrieve remote object or remote database connection. | Always
Server | use in-session activation; retrieving a local object or local database connection | Never
retrieve remote object or remote database connection | Always

##### Table 7-4 Differences Between Using JDBC 2.0 DataSource or Pre-2.0 JDBC Drivers

| JDBC 2.0 DataSource | Pre-2.0 JDBC Drivers: OracleDriver or DriverManager
--- | --- | ---
Binding Differences | You must bind the `DataSource` into the namespace with the `bindds` command. | No binding of any JDBC objects is required.
Code Differences You perform a JNDI lookup, as follows: Client | Provide the following environment setup: the environment `Hashtable` contains authentication information and namespace URL, and register the `OracleDriver`. Retrieve the `DataSource` object through a JNDI lookup that contains the "`jdbc_access://`" prefix. | Cannot be used in the client.
Server | Do one of the following: Retrieve the `DataSource` object using in-session activation. Environment setup and "`jdbc_access://`" prefix is not required. Lookup a database through an environment variable that was previously specified in the deployment descriptor. This uses the "`java:comp/env`" prefix. | The pre-2.0 JDBC drivers--`OracleDriver` and `DriverManager`--can only be used within a server object. Retrieval of JDBC connections is the same as in previous releases.

##### Table 7-5 Differences Between Container and Bean-Managed Transactions

|  | Container-Managed Transaction | Bean-Managed Transaction
--- | --- | --- | ---
Single-Phase Commit | Deployment Descriptor | Define that this is container-managed in the `<transaction-type>` element. Define the type of container management attribute, one of the values described in Table 7-1, within the `<container-transaction>` element in the XML deployment descriptor. | Define that this is bean-managed in the `<transaction-type>` element.
Binding | No binding required for `UserTransaction`. The `UserTransaction` object is created for you. If using a `DataSource` object in the transaction, bind it using the `bindds` command. However, you do not need any database links. | No binding required for `UserTransaction`. The `UserTransaction` object is created for you. If using a `DataSource` object in the transaction, bind it using the `bindds` command. However, you do not need any database links.
Runtime | Do not retrieve the `UserTransaction`. The container manages the `UserTransaction` for you. If using the `DataSource` object to manage SQL DML statements within the transaction, retrieve the `DataSource`. | Retrieve the `UserTransaction` either through the EJB 1.0 `getUserTransaction` method of `SessionCtx` or the EJB 1.1 method of a JNDI `lookup` with the "`java:comp/ UserTransaction`" string. Your runtime is responsible for starting and terminating the transaction. If using the `DataSource` object to manage SQL DML statements within the transaction, retrieve the `DataSource`.
Two-Phase Commit | Deployment Descriptor | In addition to the single-phase requirements, you must also add the JNDI bound name for the `UserTransaction` object in the `<transaction-manager>` element in the Oracle-specific deployment descriptor. | Same requirements as the container-managed transaction.
Binding | You must bind a `UserTransaction` object with the fully-qualified database address of the two-phase commit engine and its username and password. The user that was bound within the `UserTransaction` is the one that must have the privilege to commit the transaction. Thus, make sure that this user has the "`FORCE ANY TRANSACTION`" privilege. You must bind `DataSource` objects for each database involved in the transaction with a database link from the two-phase commit engine to itself. | You must bind a `UserTransaction` object with the fully-qualified database address of the two-phase commit engine and its username and password. You must bind `DataSource` objects for each database involved in the transaction with a database link from the two-phase commit engine to itself.
Runtime | Do not retrieve the `UserTransaction`. The container manages the `UserTransaction` for you. Retrieve the `DataSource`. | Retrieve the `UserTransaction` either through the EJB 1.0 `getUserTransaction` method of `SessionCtx` or the EJB 1.1 method of a JNDI `lookup` with the "`java:comp/ UserTransaction`" string. Your runtime is responsible for starting and terminating the transaction. If using the `DataSource` object to manage SQL DML statements within the transaction, retrieve the `DataSource`.

### JTA Limitations

The following are the portions of the JTA specification that Oracle8i does not support.

#### Nested Transactions

Nested transactions are not supported in this release. If you attempt to begin a new transaction before committing or rolling back any existing transaction, the transaction service throws a `NotSupportedException` exception.

#### Interoperability

The transaction services supplied with this release do not interoperate with other JTA implementations.

| Copyright © 1996-2000, Oracle Corporation. All Rights Reserved. |
Library | Service | Contents | Index