|
|
This topic includes the following sections:
This topic includes the following sections:
Overview of Transactions in WLE Applications
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.
WLE supports transactions in two different programming models:
ACID Properties of Transactions
Supported Programming Models
WLE supports two transaction API models:
Supported API Models
WLE provides a C++ interface to the OTS and a Java interface to the OTS and the JTS. The JTS is the Sun Microsystems, Inc. Java interface for transaction services, and is based on the OTS. The OTS and the JTS are accessed through the org.omg.CosTransactions.Current environmental object. For information about using the TransactionCurrent environmental object, see the C++ Bootstrap Object Programming Reference or the Java Bootstrap Object Programming Reference.
Only the application-level demarcation interface (javax.transaction.UserTransaction ) is supported. For information about JTA, see the following sources:
OTS, JTS, and JTA each provide the following support for your business transactions:
Support for Business Transactions
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.
Transactions are appropriate in the situations described in the following list. Each situation describes a transaction model supported by the WLE system.
Distributed Transactions and the Two-Phase Commit Protocol
When to Use Transactions
For example, consider a travel agent application. The client application needs to arrange for a journey to a distant location; for example, from Strasbourg, France, to Alice Springs, Australia. Such a journey would inevitably require multiple individual flight reservations. The client application works by reserving each individual segment of the journey in sequential order; for example, Strasbourg to Paris, Paris to New York, New York to Los Angeles. However, if any individual flight reservation cannot be made, the client application needs a way to cancel all the flight reservations made up to that point.
For example, consider an Internet-based online shopping cart application. Users of the client application browse through an online catalog and make multiple purchase selections. When the users are done choosing all the items they want to buy, they proceed to check out and enter their credit card information to make the purchase. If the credit card check fails, the shopping application needs a way to cancel all the pending purchase selections in the shopping cart, or roll back any purchase transactions made during the conversation.
For example, consider a banking application. The client invokes the transfer operation on a teller object. The transfer operation requires the teller object to make the following invocations on the bank database:
If the credit invocation on the bank database fails, the banking application needs a way to roll back the previous debit invocation.
This topic includes the following sections:
What Happens During a Transaction
Figure 1-1 illustrates how transactions work in a WLE CORBA application.
For CORBA applications, a basic transaction works in the following way:
Transactions in WLE CORBA Applications
Figure 1-1 How Transactions Work in a WLE CORBA Application
Figure 1-2 illustrates 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.
For EJB applications with container-managed transactions, a basic transaction works in the following way:
Container-Managed Transactions
Note: Calling the EJBContext.SetRollbackOnly method is allowed only for methods that have a meaningful transaction context.
For EJB applications with bean-managed transaction demarcations, a basic transaction works in the following way:
Figure 1-3 illustrates how transactions work in a WLE RMI application.
For RMI client and server applications, a basic transaction works in the following way:
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.
This topic includes the following sections:
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.
The Transactions sample application works in the following way:
Transactions Sample CORBA Application
Workflow for the Transactions Sample Application
Figure 1-4 illustrates how the Transactions sample application works.
The Transactions sample application shows two ways in which a transaction can be rolled back:
Thus, the Transactions sample application also shows how to implement user-defined CORBA exceptions. For example, if the student tries to register for a course that would exceed the maximum number of courses for which the student can register, the server application returns the TooManyCredits exception. When the client application receives this exception, the client application rolls back the transaction automatically.
Note: For information about how transactions are implemented in Java WLE applications, see Transactions Sample CORBA Java/C++ XA Application.
This topic describes the following development steps for writing a WLE application that contains transaction processing code:
Development Steps
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.
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" { //Classes restricted to same time block on all scheduled days, struct ClassSchedule struct CourseDetails struct StudentDetails enum NotRegisteredReason struct NotRegistered exception TooManyCredits //The Registrar interface is the main interface that allows CourseDetailsList get_courses_details(in CourseNumberList }; // The RegistrarFactory interface finds Registrar interfaces. interface RegistrarFactory 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:
Step 1: Writing the OMG IDL
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;
//starting on the hour
{
Days class_days; // bitmask of days
unsigned short start_hour; // whole hours in military time
unsigned short duration; // minutes
};
{
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;
{
StudentId student_id;
string name;
CourseDetailsList registered_courses;
};
{
AlreadyRegistered,
NoSuchCourse
};
{
CourseNumber course_number;
NotRegisteredReason not_registered_reason;
};
typedef sequence<NotRegistered> NotRegisteredList;
{
unsigned short maximum_credits;
};
//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
);
courses);
StudentDetails get_student_details(in StudentId student);
NotRegisteredList register_for_courses(
in StudentId student,
in CourseNumberList courses
) raises (
TooManyCredits
);
{
Registrar find_registrar(
);
}; Step 2: Defining Transaction Policies for the Interfaces
Transaction Policy |
Description |
---|---|
In the Transactions sample application, the transaction policy of the Registrar
interface is set to always
.
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[]) static void cleanup() s_became_transactional = CORBA_FALSE; The client application needs code that performs the following tasks:
Step 3: Writing the Server Application
{
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();
}
{
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");
}
} Step 4: Writing the Client Application
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;
}
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 *MACHINES *GROUPS OPENINFO = "ORACLE_XA:Oracle_XA+SqlNet=ORCL+Acc=P *SERVERS TMFFNAME TMFFNAME TMFFNAME TMIFRSVR ISL *SERVICES For information about the transaction log and defining parameters in the Configuration file, see Administering Transactions.
This topic provides a walkthrough of sample code fragments from a class in an EJB application. This topic includes the following sections:
IPCKEY 55432
DOMAINID university
MASTER SITE1
MODEL SHM
LDBAL N
SECURITY APP_PW
BLOTTO
LMID = SITE1
APPDIR = C:\TRANSACTION_SAMPLE
TUXCONFIG=C:\TRANSACTION_SAMPLE\tuxconfig
TLOGDEVICE=C:\APP_DIR\TLOG
TLOGNAME=TLOG
TUXDIR="C:\WLEdir"
MAXWSCLIENTS=10
SYS_GRP
LMID = SITE1
GRPNO = 1
ORA_GRP
LMID = SITE1
GRPNO = 2
/scott/tiger+SesTm=100+LogDir=.+MaxCur=5"
CLOSEINFO = ""
TMSNAME = "TMS_ORA"
TMSCOUNT = 2
DEFAULT:
RESTART = Y
MAXGEN = 5
TMSYSEVT
SRVGRP = SYS_GRP
SRVID = 1
SRVGRP = SYS_GRP
SRVID = 2
CLOPT = "-A -- -N -M"
SRVGRP = SYS_GRP
SRVID = 3
CLOPT = "-A -- -N"
SRVGRP = SYS_GRP
SRVID = 4
CLOPT = "-A -- -F"
SRVGRP = SYS_GRP
SRVID = 5
UNIVT_SERVER
SRVGRP = ORA_GRP
SRVID = 1
RESTART = N
SRVGRP = SYS_GRP
SRVID = 6
CLOPT = -A -- -n //MACHINENAME:2500 Transactions Sample EJB Code
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.
Listing 1-5 shows importing the necessary packages for transactions, including:
Importing Packages
Listing 1-5 Importing Packages
import javax.naming.*;
import javax.transaction.UserTransaction;
import javax.transaction.SystemException;
import javax.transaction.HeuristicMixedException
import javax.transaction.HeuristicRollbackException
import javax.transaction.NotSupportedException
import javax.transaction.RollbackException
import javax.transaction.IllegalStateException
import javax.transaction.SecurityException
Listing 1-6 shows initializing an instance of the UserTransaction
object to null.
Listing 1-6
Initializing the UserTransaction
Object
UserTransaction tx = null; 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 { 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(); 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:
Initializing the UserTransaction Object
Using JNDI to Return an Object Reference to the UserTransaction Object
Context ctx = getInitialContext();
tx = (UserTransaction)ctx.lookup("java:comp/UserTransaction"); Starting a Transaction
Completing a Transaction
Listing 1-9 Completing a Transaction
if(gotException){
try{
tx.rollback();
}catch(Exception e){}
}
elseif{
tx.commit();
}
This topic provides a walkthrough of sample code fragments from a class in an RMI application. This topic includes the following sections:
Transactions Sample RMI Code
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.
Listing 1-10 shows importing the necessary packages, including the following packages used to handle transactions:
Importing Packages
Listing 1-10 Importing Packages
import javax.naming.*;
import java.rmi.*;
import javax.transaction.UserTransaction;
import javax.transaction.SystemException;
import javax.transaction.HeuristicMixedException
import javax.transaction.HeuristicRollbackException
import javax.transaction.NotSupportedException
import javax.transaction.RollbackException
import javax.transaction.IllegalStateException
import javax.transaction.SecurityException
Listing 1-11 shows initializing an instance of the UserTransaction
object to null.
Listing 1-11
Initializing the UserTransaction
Object
UserTransaction tx = null; 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 { 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(); 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:
Initializing the UserTransaction Object
Using JDNI to Return an Object Reference to the UserTransaction Object
Context ctx = getInitialContext();
tx = (UserTransaction)ctx.lookup("java:comp/UserTransaction"); Starting a Transaction
Completing a Transaction
Listing 1-14 Completing a Transaction
if(gotException){
try{
tx.rollback();
}catch(Exception e){}
}
elseif{
tx.commit();
}
|
Copyright © 1999 BEA Systems, Inc. All rights reserved.
|