BEA Logo BEA WebLogic Enterprise Release 5.0

  Corporate Info  |  News  |  Solutions  |  Products  |  Partners  |  Services  |  Events  |  Download  |  How To Buy

 

   WLE Doc Home   |   Transactions & Related Topics   |   Previous   |   Next   |   Contents   |   Index

Introducing Transactions

This topic includes the following sections:

Overview of Transactions in WLE Applications

This topic includes the following sections:

ACID Properties of Transactions

One of the most fundamental features of the WebLogic Enterprise (WLE) system is transaction management. Transactions are a means to guarantee that database transactions are completed accurately and that they take on all the ACID properties (atomicity, consistency, isolation, and durability) of a high-performance transaction. WLE protects the integrity of your transactions by providing a complete infrastructure for ensuring that database updates are done accurately, even across a variety of Resource Managers. If any one of the operations fails, the entire set of operations is rolled back.

Supported Programming Models

WLE supports transactions in two different programming models:

Supported API Models

WLE supports two transaction API models:

Support for Business Transactions

OTS, JTS, and JTA each provide the following support for your business transactions:

Distributed Transactions and the Two-Phase Commit Protocol

WLE supports distributed transactions and the two-phase commit protocol for enterprise applications. A distributed transaction is a transaction that updates multiple Resource Managers (such as databases) in a coordinated manner. The two-phase commit protocol (2PC) is a method of coordinating a single transaction across one or more Resource Managers. It guarantees data integrity by ensuring that transactional updates are committed in all of the participating databases, or are fully rolled back out of all the databases, reverting to the state prior to the start of the transaction.

When to Use Transactions

Transactions are appropriate in the situations described in the following list. Each situation describes a transaction model supported by the WLE system.

What Happens During a Transaction

This topic includes the following sections:

Transactions in WLE CORBA Applications

Figure 1-1 illustrates how transactions work in a WLE CORBA application.

Figure 1-1 How Transactions Work in a WLE CORBA Application

For CORBA applications, a basic transaction works in the following way:

  1. The client application uses the Bootstrap object to return an object reference to the TransactionCurrent object for the WLE domain.

  2. A client application begins a transaction using the Tobj::TransactionCurrent::begin() operation, and issues a request to the CORBA interface through the TP Framework. All operations on the CORBA interface execute within the scope of a transaction.

  3. The Tobj::TransactionCurrent:commit() operation causes the TP Framework to call the Transaction Manager to complete the transaction.

  4. The Transaction Manager is responsible for coordinating with the Resource Managers to update the database.

Transactions in WLE EJB Applications

Figure 1-2 illustrates how transactions work in a WLE EJB application.

Figure 1-2 How Transactions Work in a WLE EJB Application

WLE supports two types of transactions in WLE EJB applications:

The sequence of transaction events differs between container-managed and bean-managed transactions.

Container-Managed Transactions

For EJB applications with container-managed transactions, a basic transaction works in the following way:

  1. In the EJB's deployment descriptor, the Bean Provider or Application Assembler specifies the transaction type (transaction-type element) for container-managed demarcation (Container ).

  2. In the EJB's deployment descriptor, the Bean Provider or Application Assembler specifies the default transaction attribute (trans-attribute element) for the EJB, which is one of the following settings: NotSupported , Required , Supports , RequiresNew , Mandatory , or Never . For a detailed description of these settings, see Section 11.6.2 in Sun Microsystem's Enterprise JavaBeans Specification 1.1 (Public Release 2 dated October 18, 1999).

  3. Optionally, in the EJB's deployment descriptor, the Bean Provider or Application Assembler specifies the trans-attribute for one or more methods.

  4. When a client application invokes a method in the EJB, the EJB Container checks the trans-attribute setting in the deployment descriptor for that method. If no setting is specified for the method, the EJB uses the default trans-attribute setting for that EJB.

  5. The EJB Container takes the appropriate action depending on the applicable trans-attribute setting.

  6. During invocation of the business method, if it is determined that a rollback is required, the business method calls the EJBContext.setRollbackOnly method, which notifies the EJB Container that the transaction is to be rolled back at the end of the method invocation.

    Note: Calling the EJBContext.SetRollbackOnly method is allowed only for methods that have a meaningful transaction context.

  7. At the end of the method execution and before the result is sent to the client, the EJB Container completes the transaction, either by committing the transaction or rolling it back (if the EJBContext.SetRollbackOnly method was called).

Bean-Managed Transactions

For EJB applications with bean-managed transaction demarcations, a basic transaction works in the following way:

  1. In the EJB's deployment descriptor, the Bean Provider or Application Assembler specifies the transaction type (transaction-type element) for container-managed demarcation (Bean ).

  2. The client application uses JNDI to obtain an object reference to the UserTransaction object for the WLE domain.

  3. The client application begins a transaction using the UserTransaction.begin method, and issues a request to the EJB through the EJB Container. All operations on the EJB execute within the scope of a transaction.

  4. The UserTransaction.commit method causes the EJB Container to call the Transaction Manager to complete the transaction.

  5. The Transaction Manager is responsible for coordinating with the Resource Managers to update any databases.

Transactions in WLE RMI Applications

Figure 1-3 illustrates how transactions work in a WLE RMI application.

Figure 1-3 How Transactions Work in a WLE RMI Application

For RMI client and server applications, a basic transaction works in the following way:

  1. The application uses JNDI to return an object reference to the UserTransaction object for the WLE domain.

    Obtaining the object reference begins a conversational state between the application and that object. The conversational state continues until the transaction is completed (committed or rolled back). Once instantiated, RMI objects remain active in memory until they are released (typically during server shutdown). For the duration of the transaction, the WLE infrastructure does not perform any deactivation or activation.

  2. The client application begins a transaction using the UserTransaction.begin method, and issues a request to the server application. All operations on the server application execute within the scope of a transaction.

  3. The UserTransaction.commit method causes WLE to call the Transaction Manager to complete the transaction.

  4. The Transaction Manager is responsible for coordinating with the Resource Managers to update any databases.

Transactions Sample Code

This topic includes the following sections:

Transactions Sample CORBA Application

In the Transactions sample CORBA application, the operation of registering for courses is executed within the scope of a transaction. The transaction model used in the Transactions sample application is a combination of the conversational model and the model in which a single client invocation makes multiple individual operations on a database.

Workflow for the Transactions Sample Application

The Transactions sample application works in the following way:

  1. Students submit a list of courses for which they want to be registered.

  2. For each course in the list, the server application checks whether:

  3. One of the following occurs:

Figure 1-4 illustrates how the Transactions sample application works.

Figure 1-4 Transactions Sample Application

The Transactions sample application shows two ways in which a transaction can be rolled back:

Development Steps

This topic describes the following development steps for writing a WLE application that contains transaction processing code:

The Transactions sample application is used to demonstrate these development steps. The source files for the Transactions sample application are located in the \samples\corba\university directory of the WLE software. For information about building and running the Transactions sample application, see Transactions Sample CORBA C++ XA Application.

The XA Bankapp sample application demonstrates how to use transactions in Java WLE applications. The source files for the XA Bankapp sample application are located in the \samples\corba\bankapp_java\XA directory of the WLE software. For information about building and running the XA Bankapp sample application, see Transactions Sample CORBA Java/C++ XA Application.

Step 1: Writing the OMG IDL

You need to specify interfaces involved in transactions in Object Management Group (OMG) Interface Definition Language (IDL) just as you would any other CORBA interface. You must also specify any user exceptions that might occur from using the interface.

For the Transactions sample application, you would define in OMG IDL the Registrar interface and the register_for_courses() operation. The register_for_courses() operation has a parameter, NotRegisteredList , which returns to the client application the list of courses for which registration failed. If the value of NotRegisteredList is empty, then the client application commits the transaction. You also need to define the TooManyCredits user exception.

Listing 1-1 includes the OMG IDL for the Transactions sample application.

Listing 1-1 OMG IDL for the Transactions Sample Application


#pragma prefix "beasys.com"
module UniversityT

{
typedef unsigned long CourseNumber;
typedef sequence<CourseNumber> CourseNumberList;

struct CourseSynopsis
{
CourseNumber course_number;
string title;
};
typedef sequence<CourseSynopsis> CourseSynopsisList;

interface CourseSynopsisEnumerator
{
//Returns a list of length 0 if there are no more entries
CourseSynopsisList get_next_n(
in unsigned long number_to_get, // 0 = return all
out unsigned long number_remaining
);

void destroy();
};
typedef unsigned short Days;
const Days MONDAY = 1;
const Days TUESDAY = 2;
const Days WEDNESDAY = 4;
const Days THURSDAY = 8;
const Days FRIDAY = 16;

//Classes restricted to same time block on all scheduled days,
//starting on the hour

struct ClassSchedule
{
Days class_days; // bitmask of days
unsigned short start_hour; // whole hours in military time
unsigned short duration; // minutes
};

struct CourseDetails
{
CourseNumber course_number;
double cost;
unsigned short number_of_credits;
ClassSchedule class_schedule;
unsigned short number_of_seats;
string title;
string professor;
string description;
};
typedef sequence<CourseDetails> CourseDetailsList;
typedef unsigned long StudentId;

struct StudentDetails
{
StudentId student_id;
string name;
CourseDetailsList registered_courses;
};

enum NotRegisteredReason
{
AlreadyRegistered,
NoSuchCourse
};

struct NotRegistered
{
CourseNumber course_number;
NotRegisteredReason not_registered_reason;
};
typedef sequence<NotRegistered> NotRegisteredList;

exception TooManyCredits
{
unsigned short maximum_credits;
};

//The Registrar interface is the main interface that allows
//students to access the database.
interface Registrar
{
CourseSynopsisList
get_courses_synopsis(
in string search_criteria,
in unsigned long number_to_get,
out unsigned long number_remaining,
out CourseSynopsisEnumerator rest
);

CourseDetailsList get_courses_details(in CourseNumberList
courses);
StudentDetails get_student_details(in StudentId student);
NotRegisteredList register_for_courses(
in StudentId student,
in CourseNumberList courses
) raises (
TooManyCredits
);

};

// The RegistrarFactory interface finds Registrar interfaces.

interface RegistrarFactory
{
Registrar find_registrar(
);
};

Step 2: Defining Transaction Policies for the Interfaces

Transaction policies are used on a per-interface basis. During design, it is decided which interfaces within a WLE application will handle transactions. Table 1-1 describes the CORBA transaction policies:

Table 1-1 CORBA Transaction Policies  

Transaction Policy

Description

always

The interface must always be part of a transaction. If the interface is not part of a transaction, a transaction will be automatically started by the TP Framework.

ignore

The interface is not transactional. However, requests made to this interface within a scope of a transaction are allowed. The AUTOTRAN parameter, specified in the UBBCONFIG file for this interface, is ignored.

never

The interface is not transactional. Objects created for this interface can never be involved in a transaction. The WLE system generates an exception (INVALID_TRANSACTION ) if an interface with this policy is involved in a transaction.

optional

The interface may be transactional. Objects can be involved in a transaction if the request is transactional. This transaction policy is the default.

During development, you decide which interfaces will execute in a transaction by assigning transaction policies in the following ways:

In the Transactions sample application, the transaction policy of the Registrar interface is set to always .

Step 3: Writing the Server Application

When using transactions in server applications, you need to write methods that implement the interface's operations. In the Transactions sample application, you would write a method implementation for the register_for_courses() operation.

If your WLE application uses a database, you need to include in the server application code that opens and closes an XA Resource Manager. These operations are included in the Server::initialize() and Server::release() operations of the Server object. Listing 1-2 shows the portion of the code for the Server object in the Transactions sample application that opens and closes the XA Resource Manager.

Note: For a complete example of a C++ server application that implements transactions, see Transactions Sample CORBA C++ XA Application. For an example of a Java server application that implements transactions, see Transactions Sample CORBA Java/C++ XA Application.

Listing 1-2 C++ Server Object in Transactions Sample Application


CORBA::Boolean Server::initialize(int argc, char* argv[])
{
TRACE_METHOD("Server::initialize");
try {
open_database();
begin_transactional();
register_fact();
return CORBA_TRUE;
}
catch (CORBA::Exception& e) {
LOG("CORBA exception : " <<e);
}
catch (SamplesDBException& e) {
LOG("Can't connect to database");
}
catch (...) {
LOG("Unexpected database error : " <<e);
}
catch (...) {
LOG("Unexpected exception");
}
cleanup();
return CORBA_FALSE;
}

void Server::release()
{
TRACE_METHOD("Server::release");
cleanup();
}

static void cleanup()
{
unregister_factory();
end_transactional();
close_database();
}
//Utilities to manage transaction resource manager

CORBA::Boolean s_became_transactional = CORBA_FALSE;
static void begin_transactional()
{
TP::open_xa_rm();
s_became_transactional = CORBA_TRUE;
}
static void end_transactional()
{
if(!s_became_transactional){
return//cleanup not necessary
}
try {
TP::close_xa_rm ();
}
catch (CORBA::Exception& e) {
LOG("CORBA Exception : " << e);
}
catch (...) {
LOG("unexpected exception");
}

s_became_transactional = CORBA_FALSE;
}

Step 4: Writing the Client Application

The client application needs code that performs the following tasks:

  1. Obtains a reference to the TransactionCurrent object from the Bootstrap object.

  2. Begins a transaction by invoking the Tobj::TransactionCurrent::begin() operation on the TransactionCurrent object.

  3. Invokes operations on the object. In the Transactions sample application, the client application invokes the register_for_courses() operation on the Registrar object, passing a list of courses.

Listing 1-3 illustrates the portion of the CORBA C++ client applications in the Transactions sample application that illustrates the development steps for transactions.

For an example of a CORBA Java client application that uses transactions, see Transactions Sample CORBA Java/C++ XA Application. For an example of using transactions in an ActiveX client application, see Transactions in CORBA Client Applications.

Listing 1-3 Transactions Code for CORBA C++ Client Applications


CORBA::Object_var var_transaction_current_oref =
Bootstrap.resolve_initial_references("TransactionCurrent");
CosTransactions::Current_var transaction_current_oref=
CosTransactions::Current::_narrow(var_transaction_current_oref.in());
//Begin the transaction
var_transaction_current_oref->begin();
try {
//Perform the operation inside the transaction
pointer_Registar_ref->register_for_courses(student_id, course_number_list);
...
//If operation executes with no errors, commit the transaction:
CORBA::Boolean report_heuristics = CORBA_TRUE;
var_transaction_current_ref->commit(report_heuristics);
}
catch (...) {
//If the operation has problems executing, rollback the
//transaction. Then throw the original exception again.
//If the rollback fails,ignore the exception and throw the
//original exception again.
try {
var_transaction_current_ref->rollback();
}
catch (...) {
TP::userlog("rollback failed");
}
throw;
}

Step 5: Creating a Configuration File

You need to add the following information to the configuration file for a transactional WLE application:

Listing 1-4 includes the portions of the configuration file that define this information for the Transactions sample application.

Listing 1-4 Configuration File for Transactions Sample Application


*RESOURCES
IPCKEY 55432
DOMAINID university
MASTER SITE1
MODEL SHM
LDBAL N
SECURITY APP_PW

*MACHINES
BLOTTO
LMID = SITE1
APPDIR = C:\TRANSACTION_SAMPLE
TUXCONFIG=C:\TRANSACTION_SAMPLE\tuxconfig
TLOGDEVICE=C:\APP_DIR\TLOG
TLOGNAME=TLOG
TUXDIR="C:\WLEdir"
MAXWSCLIENTS=10

*GROUPS
SYS_GRP
LMID = SITE1
GRPNO = 1
ORA_GRP
LMID = SITE1
GRPNO = 2

OPENINFO = "ORACLE_XA:Oracle_XA+SqlNet=ORCL+Acc=P
/scott/tiger+SesTm=100+LogDir=.+MaxCur=5"
CLOSEINFO = ""
TMSNAME = "TMS_ORA"
TMSCOUNT = 2

*SERVERS
DEFAULT:
RESTART = Y
MAXGEN = 5

TMSYSEVT
SRVGRP = SYS_GRP
SRVID = 1

TMFFNAME
SRVGRP = SYS_GRP
SRVID = 2
CLOPT = "-A -- -N -M"

TMFFNAME
SRVGRP = SYS_GRP
SRVID = 3
CLOPT = "-A -- -N"

TMFFNAME
SRVGRP = SYS_GRP
SRVID = 4
CLOPT = "-A -- -F"

TMIFRSVR
SRVGRP = SYS_GRP
SRVID = 5

UNIVT_SERVER
SRVGRP = ORA_GRP
SRVID = 1
RESTART = N

ISL
SRVGRP = SYS_GRP
SRVID = 6
CLOPT = -A -- -n //MACHINENAME:2500

*SERVICES

For information about the transaction log and defining parameters in the Configuration file, see Administering Transactions.

Transactions Sample EJB Code

This topic provides a walkthrough of sample code fragments from a class in an EJB application. This topic includes the following sections:

The code fragments demonstrate using the UserTransaction object for bean-managed transaction demarcation. The deployment descriptor for this bean specifies the transaction type (transaction-type element) for transaction demarcation (Bean ).

Note: These code fragments do not derive from any of the sample applications that ship with WLE. They merely illustrate the use of the UserTransaction object within an EJB application.

Importing Packages

Listing 1-5 shows importing the necessary packages for transactions, including:

Initializing the UserTransaction Object

Listing 1-6 shows initializing an instance of the UserTransaction object to null.

Listing 1-6 Initializing the UserTransaction Object


UserTransaction tx = null;

Using JNDI to Return an Object Reference to the UserTransaction Object

Listing 1-7 shows searching the JNDI tree to return an object reference to the UserTransaction object for the appropriate WLE domain.

Listing 1-7 Performing a JDNI Lookup


try {
Context ctx = getInitialContext();
tx = (UserTransaction)ctx.lookup("java:comp/UserTransaction");

Starting a Transaction

Listing 1-8 shows starting a transaction by calling the javax.transaction.UserTransaction.begin method. Database operations that occur after this method invocation and prior to completing the transaction exist within the scope of this transaction.

Listing 1-8 Starting a Transaction


tx.begin();

Completing a Transaction

Listing 1-9 shows completing the transaction depending on whether an exception was thrown during any of the database operations that were attempted within the scope of this transaction:

Transactions Sample RMI Code

This topic provides a walkthrough of sample code fragments from a class in an RMI application. This topic includes the following sections:

The code fragments demonstrate using the UserTransaction object for RMI transactions.

Note: These code fragments do not derive from any of the sample applications that ship with WLE. They merely illustrate the use of the UserTransaction object within an RMI application.

Importing Packages

Listing 1-10 shows importing the necessary packages, including the following packages used to handle transactions:

Initializing the UserTransaction Object

Listing 1-11 shows initializing an instance of the UserTransaction object to null.

Listing 1-11 Initializing the UserTransaction Object


UserTransaction tx = null;

Using JDNI to Return an Object Reference to the UserTransaction Object

Listing 1-12 shows searching the JNDI tree to return an object reference to the UserTransaction object for the appropriate WLE domain.

Note: Obtaining the object reference begins a conversational state between the application and that object. The conversational state continues until the transaction is completed (committed or rolled back). Once instantiated, RMI objects remain active in memory until they are released (typically during server shutdown). For the duration of the transaction, the WLE infrastructure does not perform any deactivation or activation.

Listing 1-12 Performing a JDNI Lookup


try {
Context ctx = getInitialContext();
tx = (UserTransaction)ctx.lookup("java:comp/UserTransaction");

Starting a Transaction

Listing 1-13 shows starting a transaction by calling the javax.transaction.UserTransaction.begin method. Database operations that occur after this method invocation and prior to completing the transaction exist within the scope of this transaction.

Listing 1-13 Starting a Transaction


tx.begin();

Completing a Transaction

Listing 1-14 shows completing the transaction depending on whether an exception was thrown during any of the database operations that were attempted within the scope of this transaction: