Oracle8i Enterprise JavaBeans and CORBA Developer's Guide
Release 2 (8.1.6)

A81356-01

Library

Product

Contents

Index

Prev Next

5
Transaction Handling

This chapter covers transaction management for both CORBA and EJB applications. Transaction handling in the two distributed component development models has some fundamental similarities, but there are also some differences. For example, the application developer who is using EJBs can elect to have the EJB container manage all transactions in a way that is transparent to the client application and to the bean developer. The developer does not have to write any transaction code at all--the transactional properties of the application can be declared at bean deployment time. In this sense, EJBs are said to have declarative transactional capability.

The CORBA developer, on the other hand, must use the transactional APIs provided--usually a mapping of a subset of the OMG Object Transaction Service (OTS) API, such as the Java Transaction Service (JTS) that is supplied with Oracle8i JServer. The CORBA developer must code calls to a transaction service to enable transactional properties for distributed objects, where this is required.

But the EJB developer might require finer-grained control of the application's transactional properties than that offered by the declarative transactional capabilities built-in to the EJB container. In this case, the developer can use explicit calls to transaction API methods, either on the client side or in the bean implementations themselves.

This chapter discusses the following topics:

Transaction Overview

A transaction is a unit of work, usually associated with a database management system. Transactions are described in terms of the so-called ACID properties. A transaction is:

Most of the transactional features that are part of the Oracle8i database server are available to the CORBA or EJB distributed application developer.

Oracle8i JServer supports two transaction APIs for use in CORBA and EJB applications:

The JTS is a Java binding to the OMG Object Transaction Service (OTS). It is used for client-side demarcated transactions, and for transaction management in CORBA server objects.

The UserTransaction interface is used in EJBs, where the bean is running using the transaction attribute TX_BEAN_MANAGED.

Limitations

The implementations of JTS that is supplied for this Oracle8i release is intended mostly to support client-side transaction demarcation. As such it has some limitations that you should be aware of when designing your application.

No Distributed Transactions

This implementation of JTS does not manage distributed transactions. Transaction control distributed among multiple database servers, with support for the required two-phase commit protocol, will be available in an upcoming release of Oracle8i JServer.

Resources

The JTS transaction API supplied with Oracle8i JServer manages only one resource: an Oracle8i database session. A transaction cannot span multiple servers or multiple database sessions in a single service.

Transaction contexts are never propagated outside a server. If a server object calls out to another server, the transaction context is not carried along.

However, a transaction can involve one or many objects. The transaction can encompass one or many methods of these objects. The scope of a transaction is defined by a transaction context that is shared by the participating objects.

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 SubtransactionsUnavailable exception.

Timeouts

Methods of the JST that support transaction timeout, such as setTimeout(), do not work in this release. You can invoke them from your code, and no exception is thrown, but they have no effect.

Interoperability

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

Transaction Demarcation

A transaction is said to be demarcated. This simply means that it has a definite beginning and definite end 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.

In a distributed object application, transactions are often described as client-side demarcated (or sometimes just client demarcated), or server-side demarcated (equivalently server demarcated).

In client-side demarcation, a transactional client explicitly encloses one or more method invocations on a server object with demarcation methods that begin and end transactions. The begin and end demarcaters are method calls on the client-side transaction service. See "Client-Side Demarcation" for specific examples.

Server-side transaction demarcation implies that the server-side object begins and either commits or rolls back a transaction. Note that a transaction can span several objects, any one of which can suspend, resume, or end the transaction.

Transaction Context

The transaction context is a pseudo-object that is passed to the server object from the client, or from one server object to another, in the case where one server object is invoking methods on another, and hence acting as its client. The transaction context carries the state of the transaction.

After a client-side transaction service is initialized, and a begin transaction method is invoked, the transaction service implicitly creates a transaction context, and assigns a transaction ID number to the context. The client transaction service then propagates the transaction context to each participant in the transaction, that is, to each object that the client calls.

Propagation of the transaction context on each method invocation is normally transparent to the client program. The transaction context is maintained by the transaction service for each client. Transaction contexts are propagated transparently from the transaction initiator to the server object. On the client side, an interceptor is engaged to submit the transaction context on any method call to a server object. A server-side interceptor extracts the transaction context information, and makes it available to the server object.

As stated in "Limitations", a transaction context cannot span multiple sessions. Each new session connection requires a new transaction context.

Transaction Service Interfaces

Oracle8i supports a version of the JTS. The JTS is a Java mapping of the OMG Object Transaction Service (OTS). There are two classes that the application developer can use:

The section below describes the TransactionService interface. Because it is used with EJBs, the UserTransaction class is described in "AuroraUserTransaction".

TransactionService

Use the TransactionService to initialize a transaction context on the client. Include the AuroraTransactionService package in your Java client source with the following import statements:

import oracle.aurora.jts.client.AuroraTransactionService;
import javax.jts.*;
import oracle.aurora.jts.util.*;

These classes are included in the library file aurora_client.jar, which must be in the classpath when compiling and executing all source files that use the JTS.

There is only one method in this package that you can call:

public synchronized static void initialize(Context initialContext,
                                           String serviceName)

This method initializes the transaction context on a client. The parameters are:

serviceName

The complete service name. For example sess_iiop://localhost:2481:ORCL  

An example of using initialize() is:

Hashtable env = new Hashtable();
env.put(Context.URL_PKG_PREFIXES, "oracle.aurora.jndi");
env.put(Context.SECURITY_PRINCIPAL, "scott");
env.put(Context.SECURITY_CREDENTIALS, "tiger");
env.put(Context.SECURITY_AUTHENTICATION, ServiceCtx.NON_SSL_LOGIN);
Context initialContext = new InitialContext(env);
AuroraTransactionService.initialize
          (initialContext, "sess_iiop://localhost:2481:ORCL");

See also the complete example in "clientside".

Using The Java Transaction Service

The JTS package itself contains methods that a client-side or server-side object uses to begin transactions, commit or roll back a transaction, and perform utility functions such as setting the transaction timeout. The JTS methods should be used in CORBA or EJB clients, or in CORBA server objects. Developers implementing EJBs, and who need fine-grained transaction control within beans should use the UserTransaction interface in a bean-managed state. See "Transaction Management for EJBs" for more information.

To use the JTS methods, code the following import statements in your source:

import oracle.aurora.jts.util.TS;
import javax.jts.util.*;
import org.omg.CosTransactions.*;

The oracle.aurora.jts.util package is included in the library file aurora_client.jar, which must be in the classpath for all Java sources that use the JTS.

You use the static methods in the TS class to get the transaction service.

Java Transaction Service Methods

The JTS includes the following methods:

public static synchronized TransactionService getTS()

getTS() returns a transaction service object. Once a transaction service has been obtained, you can invoke the static method getCurrent() on it to return a Current pseudo-object, the transaction context. Then you can invoke methods to begin, suspend, resume, commit, or roll back the current transaction on the Current pseudo-object.

Here is an example that begins a new transaction on a client, starting with getting the JNDI initial context:

import oracle.aurora.jndi.sess_iiop.ServiceCtx;
import oracle.aurora.jts.client.AuroraTransactionService;
import javax.naming.Context;
import javax.naming.InitialContext;
import java.util.Hashtable;
...
Context ic = new InitialContext(env);
...
AuroraTransactionService.initialize(ic, serviceURL);
...
Employee employee = (Employee)ic.lookup (serviceURL + objectName);
EmployeeInfo info;
oracle.aurora.jts.util.TS.getTS().getCurrent().begin();

If there is no transaction service available, then getTS() throws a NoTransactionService exception.

Current Transaction Methods

The methods that you can call to control transactions on the current transaction context are the following:

public void begin()

Begins a new transaction.

Can throw these exceptions:

See the section "TransactionService" for information about initialization.


public Control suspend()

Suspends the current transaction in the session. Returns a Control transaction context pseudo-object. You must save this object reference for use in any subsequent resume() invocations. Invoke suspend() in this way:

org.omg.CosTransactions.Control c =
          oracle.aurora.jts.util.TS.getTS().getCurrent().suspend();

suspend() can throw these exceptions:

If suspend() is invoked outside of a transaction context, then a NoTransactionService exception is thrown. If suspend() is invoked before begin() has been invoked, or after a suspend(), the a exception is thrown.


public void resume(Control which)

Resumes a suspended transaction. Invoke this method after a suspend(), in order to resume the specified transaction context. The which parameter must be the transaction Control object that was returned by the previous matching suspend() invocation in the same session. For example:

org.omg.CosTransactions.Control c = 
             oracle.aurora.jts.util.TS.getTS().getCurrent().suspend();
...   // do some non-transactional work
oracle.aurora.jts.util.TS.getTS().getCurrent().resume(c);

resume() can throw:

Commits the current transaction. Set the report_heuristics parameter to false.

(The report_heuristics parameter is set to true for extra information on two-phase commits. Because this release of JServer does not support the two-phase commit protocol for distributed objects, use of the report_heuristics parameter is not meaningful. It is included for compatibility with future releases.)

commit() can throw:

The HeuristicMixed and HeuristicHazard exceptions are documented in the OTS specification. See "For More Information" for the location of the OTS specification.

If there is no active transaction, commit() throws a NoTransaction exception.


public void rollback()

Rolls back the effects of the current transaction.

Invoking rollback() has the effect of ending the transaction, so invoking any JTS method except begin() after a rollback() throws a NoTransaction exception.

If not in a transaction context, rollback() throws the NoTransaction exception.


public void rollback_only() throws NoTransaction {

rollback_only() modifies the transaction associated with the current thread so that the only possible outcome is to roll back the transaction. If not in a transaction context, rollback_only() throws the NoTransaction exception.


public void set_timeout(int seconds)

This method is not supported, and has no effect if invoked. The default timeout value is 60 seconds in all cases.


public Status get_status()

You can call get_status() at any time to discover the status of the current transaction. Possible return values are:

The complete set of status ints is defined in javax.transaction.Status.


public String get_transaction_name() {

Invoke get_transaction_name() to see the name of the transaction, returned as a String. If this method is invoked before a begin(), after a rollback(), or outside of a transaction context, it returns a null string.

CORBA Examples

This section shows some examples that use the JTS interface for CORBA client code and CORBA server objects. See "Transaction Examples" for a set of complete examples that you can run and modify.

Client-Side Demarcation

Follow these steps to use JTS methods in your CORBA client code:

For example:

import oracle.aurora.jndi.sess_iiop.ServiceCtx;
import oracle.aurora.jts.client.AuroraTransactionService;
import oracle.aurora.jts.util.TS;
import org.omg.CosTransactions.*;
// Include normal startup code...
// Initialize a transaction context...
AuroraTransactionService.initialize(ic, serviceURL);

// Begin a transaction...
oracle.aurora.jts.util.TS.getTS().getCurrent().begin();

// Call methods that involve SQL DML...
employee.updateEmployee(info);
...
// Commit (or roll back) the SQL statements...
oracle.aurora.jts.util.TS.getTS().getCurrent().commit(false);

For a complete example that uses these techniques for client-side transaction demarcation, see "clientside".

Server-Side JTS

Follow these steps to use JTS methods in your CORBA server object code:

You can also invoke other JTS methods, such as set_timeout(), from within a server object.

See the complete example at "serversideJTS" for a demonstration of CORBA server-side transaction demarcation.

Transactions in Multiple Sessions

See the complete example at "multiSessions" for an example that establishes multiple server sessions, each with its own transaction context.

Transaction Management for EJBs

The previous sections focused on general aspects of transaction management for distributed objects, and on transaction management for CORBA applications using the JTS.

An EJB application can also use JTS--on the client side only--to manage transactions. More typically an EJB application uses declarative transaction management, letting the EJB container provide the transaction control. You do this by specifying the appropriate value for the TransactionAttribute of the EJB deployment descriptor, either for the whole EJB, or on a method-by-method basis, where applicable.

For example, if the deployment descriptor for a bean declares that the bean has the transaction attribute TX_REQUIRES_NEW, then the bean container starts a transaction before each invocation of bean method, and attempts to commit the transaction when the method completes.

The following sections describe the values that you can set for the EJB transaction attribute.

Declarative Transactions

The bean deployer declares the transaction handling characteristics of a bean in the deployment descriptor. This is specified in the transaction attribute, which has six possible values:

The semantics of these attribute values are described in this section. See "Programming Restrictions" for more information about the EJB deployment descriptor itself.

TX_NOT_SUPPORTED

When TX_NOT_SUPPORTED is declared for the bean itself, it means that Oracle8i does not invoke transaction support for the bean methods. However, a method declaration in the deployment descriptor can over-ride this declaration. If the client is in a transaction (has established an active transaction context), then the bean container suspends transaction support during delegation of method calls on the bean, and resumes the transaction context when the method call completes.

The suspended transaction context is not propagated to other objects that are invoked from within the bean code.

A bean that is running under TX_NOT_SUPPORTED cannot perform any SQL operations. An exception is thrown by the EJB server if this is attempted.

TX_REQUIRED

If the client invokes a bean method with the TX_REQUIRED attribute, there are two possibilities:

The client had not started a transaction  

If the client has not established a transaction context, the bean starts a new transaction for each method call. The transaction is committed, if possible, after each call completes. The commit protocol is completed before the bean results are sent to the client.  

 

Oracle8i sends the transaction context for the transaction that it has established to other resources or EJBs that are invoked from the current bean.  

The client had started a transaction  

The bean container delegates calls to the bean methods using the client transaction context.  

The transaction context is passed to other Enterprise JavaBean objects that are invoked from the enterprise Bean object, as long as they are in the same session.

TX_SUPPORTS

If the client has established a transaction context, then the bean container uses that context. If the client has no established transaction context, then the EJB methods are invoked with no transaction support.

TX_REQUIRES_NEW

The container always invokes the bean methods with a new transaction. The container commits the transaction, if possible, before sending the method results to the client.

If the client has established a transaction content, the client transaction is suspended before the bean transaction is started, and is resumed when the bean transaction completes (at the end of each method call).

If the client has established a transaction context, the association is suspended before the new transaction is started and is resumed when the new transaction has completed.

The container-managed transaction context is passed to the resources or other EJB objects that the bean invokes.

An enterprise Bean that has the TX_REQUIRES_NEW transaction attribute is always invoked in the scope of a new transaction. The container starts a new transaction before delegating a method call to the enterprise Bean object, and attempts to commit the transaction when the method call on the enterprise Bean object has completed. The container performs the commit protocol before the method result is sent to the client.

The new transaction context is passed to the resources or other enterprise Bean objects that are invoked from the enterprise Bean object.

TX_MANDATORY

If an EJB method is invoked with the TX_MANADATORY attribute, the client transaction context is always used. If the client has not established a transaction context, the container throws the TransactionRequired exception to the client.

The client transaction context is propagated to the resources or other enterprise Bean objects that are invoked from the enterprise Bean object.

TX_BEAN_MANAGED

The bean-managed attribute value is the one that lets the bean get access to the transaction service on its own behalf. Session beans get access to the transaction service through the session context that is supplied to the bean at initialization, as a parameter in the setSessionContext() call. The SessionContext interface subclasses EJBContext.

The bean implementation must use the javax.jts.UserTransaction interface methods to manage transactions on its own. See "Using The Java Transaction Service" for a description of these methods.

The TX_BEAN_MANAGED attribute value cannot be mixed with other transaction attribute values. For example, if the bean-level descriptor, or one of the method-level descriptors, specifies TX_BEAN_MANAGED, then all method-level descriptors present must specify TX_BEAN_MANAGED. When using bean-managed transactions, the transaction boundaries span bean methods. You can begin a transaction in one method, and the transaction can be rolled back or committed in a separate method, called later.

The container makes the javax.jts.UserTransaction interface available to the enterprise Bean though the EJBContext.getUserTransaction() method, as illustrated in the following example.

import javax.jts.UserTransaction;
...
EJBContext ic = ...;
...
UserTransaction tx = ic.getUserTransaction();
tx.begin();
... // do work
tx.commit();

The container must manage transactions on a TX_BEAN_MANAGED Bean as follows.

When a client invokes a stateful TX_BEAN_MANAGED Bean, the container suspends any incoming transaction. The container allows the session instance to initiate a transaction using the javax.jts.UserTransaction interface. The instance becomes associated with the transaction and remains associated until the transaction terminates.

When a Bean-initiated transaction is associated with the instance, methods on the instances run under that transaction.

It is possible that a business method that initiated the transaction completes without committing or rolling back the transaction. The container must retain the association between the transaction and the instance across multiple client calls until the transaction terminates.

Table 5-1 Effect of declarative transaction attribute (Cont.)

Transaction Attribute Value   Client Transaction   Transaction of EJB Method  

TX_NOT_SUPPORTED  

none  

none  

 

T1  

none  

TX_REQUIRED  

none  

new transaction - T2  

 

T1  

T1  

TX_SUPPORTS  

none  

none  

 

T1  

T1  

TX_REQUIRES_NEW  

none  

new transaction - T2  

 

T1  

T2  

TX_MANDATORY  

none  

TransactionRequired exception thrown  

 

T1  

T1  

Session Synchronization Interface

An EJB can optionally implement the session synchronization interface, to be notified by the container of the transactional state of the bean. The following methods are specified in the javax.ejb.SessionSynchronization interface:

afterBegin

public abstract void afterBegin() throws RemoteException

The afterBegin() method notifies a session Bean instance that a new transaction has started, and that the subsequent methods on the instance are invoked in the context of the transaction.

A bean can use this method to read data from a database and cache the data in the bean's fields.

This method executes in the proper transaction context.

beforeCompletion

public abstract void beforeCompletion() throws RemoteException

The container calls the beforeCompletion() method to notify a session bean that a transaction is about to be committed. You can implement this method to, for example, write any cached data to the database.

afterCompletion

public abstract void afterCompletion(boolean committed) throws RemoteException

The container calls afterCompletion() to notify a session bean that a transaction commit protocol has completed. The parameter tells the bean whether the transaction has been committed or rolled back.

This method executes with no transaction context.

JDBC

If you are using JDBC calls in your bean to update a database, you should not also use JDBC to perform transaction services, by calling methods on the JDBC connection. Do not code JDBC calls on a connection, for example:

Connection conn = ...
...
conn.commit();  // DO NOT DO THIS!!

You also avoid doing direct SQL commits or rollbacks through JDBC. Code the bean to either handle transactions directly using the javax.jts.UserTransactions interface (if the TransactionAttribute value is TX_BEAN_MANAGED), or let the bean container manage the bean transactions.

AuroraUserTransaction

You use the UserTransaction interface to manage transactions in Enterprise JavaBeans. The UserTransaction interface is a higher-level interface than the raw JTS, although its functionality is almost identical. However, EJB developers must use the UserTransaction interface for EJB bean-managed transaction support. The UserTransaction interface is used only for bean-managed EJBs.

See "serversideJTS" for a complete example of bean-managed transaction control.

To incorporate UserTransaction methods in your bean implementation code, follow these steps:

Methods

public void begin()

begin() creates a new transaction and associates it with the current bean.

Throws IllegalStateException if you attempt to invoke it in the context of an existing transaction.

public void commit()

commit() commits the transaction results, and completes the transaction associated with the current bean. When the commit() method completes, the bean is no longer associated with a transaction.

commit() can throw any of the following exceptions:

Returns the status of the current transaction. See "Java Transaction Service Methods" for more information about the status values that can be returned.

public void resume() 

Resumes a suspended transaction.

public void rollback()

Rolls back the effects of the current transaction.

rollback() can throw the following exceptions:

The effect of a setRollbackOnly() invocation is that the only possible conclusion to the current transaction is a roll back operation. Any attempt to perform a commit() after setRollbackOnly() is invoked results in a exception.

setRollBackOnly() throws an IllegalStateException, if not in a transaction.

public void setTransactionTimeout(int arg1)

This method is implemented, but has no effect in this release. The timeout value is always 60 seconds.

Session Synchronization

An EJB can optionally implement the session synchronization interface, to be notified by the server of the state of the transaction. The following methods are specified in the javax.ejb.SessionSynchronization interface:

afterBegin

public abstract void afterBegin() throws RemoteException

The afterBegin() method notifies a session Bean instance that a new transaction has started, and that the subsequent methods on the instance are invoked in the context of the transaction.

A bean can use this method to read data from a database and cache the data in the bean's fields.

This method executes in the proper transaction context.

beforeCompletion

public abstract void beforeCompletion() throws RemoteException

The container calls the beforeCompletion() method to notify a session bean that a transaction is about to be committed. You can implement this method to, for example, write any cached data to the database.

afterCompletion

public abstract void afterCompletion(boolean committed) throws RemoteException

The container calls afterCompletion() to notify a session bean that a transaction commit protocol has completed. The parameter tells the bean whether the transaction has been committed or rolled back.

This method executes with no transaction context.

EJB Transaction Examples

This section shows a few abbreviated examples of transaction management for EJB applications. For a set of complete programs, see "Transaction Examples".

Client-Side Demarcated

If your EJB application requires client-side transaction demarcation, you use the JTS interface, as explained in "Using The Java Transaction Service". See the section "clientside" for a complete example of EJB client-side transaction demarcation.

Transaction Management in an EJB

Use the UserTransaction interface to set up a transaction context within an EJB. In the bean implementation, make sure to import the javax.jts.UserTransaction package. Unlike the TransactionService when used on the client side, you do not need to initialize the UserTransaction interface from within an EJB. The container does that for you.

Getting the Session Context

In the EJB, use the setSessionContext() session bean method to obtain the session context, and save it in an instance variable. For example, code this implementation of the setSessionContext() method:

public class XBean implements SessionBean {
  SessionCtx ctx;
  ...
  public void setSessionContext(SessionContext ctx) {
    this.ctx = ctx;
  }

You can then use the session context ctx to invoke UserTransaction methods.

Beginning a Transaction

Invoke the begin() method as follows:

ctx.getUserTransaction.begin();

to start a transaction.

Committing a Transaction

Invoke the commit() method as follows:

ctx.getUserTransaction().commit();

to end the transaction with a commit.

Other UserTransaction Methods

Invoke other methods of the UserTransaction interface in the same way that you do a begin() or a commit()--invoke them on a UserTransaction object of the session context.

See the section "serversideJTS" for a complete example that uses the UserTransaction interface in an EJB.

JDBC

If you are using JDBC calls in your CORBA server object or EJB to update a database, and you have an active transaction context, you should not also use JDBC to perform transaction services, by calling methods on the JDBC connection. Do not code JDBC transaction management methods. For example:

Connection conn = ...
...
conn.commit();  // DO NOT DO THIS!!

Doing so will cause a SQL exception to be thrown.

You must also avoid doing direct SQL commits or rollbacks through JDBC. Code the bean to either handle transactions directly using the javax.jts.UserTransactions interface (if the TransactionAttribute value is TX_BEAN_MANAGED), or let the bean container manage the bean transactions.

For More Information

Information on the Java Transaction Service is available at:

http://java.sun.com:/products/jts/index.html

The Sun JTA specification is available at:

http://java.sun.com/products/jts/index.html

The OTS specification is part of the CORBA services specification. Chapter 10 (individually downloadable) contains the OTS specification. Get it at:

http://www.omg.org/library/csindx.html




Prev

Next
Oracle
Copyright © 1999 Oracle Corporation.

All Rights Reserved.

Library

Product

Contents

Index