Table of Contents Previous Next PDF


Integrating Transactions into a CORBA Server Application

Integrating Transactions into a CORBA Server Application
This chapter describes how to integrate transactions into a CORBA server application, using the Transactions University sample application as an example. The Transactions sample application encapsulates the process of a student registering for a set of courses. The Transactions sample application does not show all the possible ways to integrate transactions into a CORBA server application, but it does show two models of transactional behavior, showing the impact of transactional behavior on the application in general and on the durable state of objects in particular.
This topic includes the following sections:
This chapter also presents a section on user-defined exceptions. The Transactions sample application introduces a user-defined exception, which can be returned to the client application and that potentially causes a client-initiated transaction to be rolled back.
Overview of Transactions in the Oracle Tuxedo System
The Oracle Tuxedo system provides transactions as 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. That is, you have a requirement to perform multiple write operations on durable storage, and you must be guaranteed that the operations succeed; if any one of the operations fails, the entire set of operations is rolled back.
Transactions typically are appropriate in the situations described in the following list. Each situation encapsulates a transactional model supported by the Oracle Tuxedo system.
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 so far. For example, if the client application cannot book a flight from Los Angeles to Honolulu on a given date, the client application needs to cancel the flight reservations made up to that point.
For example, consider an Internet-based online shopping application. The user of the client application browses through an online catalog and makes multiple purchase selections. When the user is done choosing all the items he or she wants to buy, the user clicks on a button to make the purchase, where the user may enter credit card information. If the credit card check fails (for example, the user cannot provide valid credit card information), the shopping application needs a way to cancel all the pending purchase selections 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.
Designing and Implementing Transactions in a CORBA Server Application
This section explains how to design and implement transactions in a CORBA server application using the Transactions University sample application as an example. This section also describes how the Transactions sample application works, and discusses the design considerations for implementing transactions in it. For additional general information about transactions, see the section “Integrating Transactions in a CORBA Client and Server Application” on page -9.
The Transactions sample application uses transactions to encapsulate the task of a student registering for a set of courses. The transactional model used in this application is a combination of the conversational model and the model in which a single invocation makes multiple individual operations on a database, as described in the preceding section.
The Transactions sample application builds on the Security sample application by adding the following capabilities:
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.
The sections that follow explain:
How the Transactions University Sample Application Works
To implement the student registration process, the Transactions sample application does the following:
a.
Begins a transaction by invoking the Current::begin() operation on the TransactionCurrent object
b.
Invokes the register_for_courses() operation on the Registrar object, passing a list of courses
The register_for_courses() operation on the Registrar object processes the registration request by executing a loop that does the following iteratively for each course in the list:
a.
b.
The Registrar object checks for the following potential problems, which prevent the transaction from being committed:
As defined in the application’s OMG IDL, the register_for_courses() operation returns a parameter to the client application, NotRegisteredList, which contains a list of the courses for which the registration failed.
If the NotRegisteredList value is empty, the client application commits the transaction.
If the NotRegisteredList value contains any courses, the client application queries the student to indicate whether he or she wants to complete the registration process for the courses for which the registration succeeded. If the user chooses to complete the registration, the client application commits the transaction. If the user chooses to cancel the registration, the client application rolls back the transaction.
If the registration for a course has failed because the student exceeds the maximum number of credits he or she can take, the Registrar object returns a TooManyCredits exception to the client application, and the client application rolls back the entire transaction.
Transactional Model Used by the Transactions University Sample Application
The basic design rationale for the Transactions sample application is to handle course registrations in groups, as opposed to one at a time. This design helps to minimize the number of remote invocations on the Registrar object.
In implementing this design, the Transactions sample application shows one model of the use of transactions, which were described in the section “Overview of Transactions in the Oracle Tuxedo System” on page 6‑2. The model is as follows:
The client begins a transaction by invoking the begin() operation on the TransactionCurrent object, followed by making an invocation to the register_for_courses() operation on the Registrar object.
The Registrar object registers the student for the courses for which it can, and then returns a list of courses for which the registration process was unsuccessful. The client application can choose to commit the transaction or roll it back. The transaction encapsulates this conversation between the client and the server application.
The register_for_courses() operation performs multiple checks of the University database. If any one of those checks fail, the transaction can be rolled back.
Object State Considerations for the University Server Application
Because the Transactions University sample application is transactional, the University server application generally needs to consider the implications on object state, particularly in the event of a rollback. In cases where there is a rollback, the server application must ensure that all affected objects have their durable state restored to the proper state.
Because the Registrar object is being used for database transactions, a good design choice for this object is to make it transactional; that is, assign the always transaction policy to this object’s interface. If a transaction has not already been scoped when this object is invoked, the Oracle Tuxedo system will start a transaction automatically.
By making the Registrar object automatically transactional, all database write operations performed by this object will always be done within the scope of a transaction, regardless of whether the client application starts one. Since the server application uses an XA resource manager, and since the object is guaranteed to be in a transaction when the object writes to a database, the object does not have any rollback or commit responsibilities because the XA resource manager takes responsibility for these database operations on behalf of the object.
The RegistrarFactory object, however, can be excluded from transactions because this object does not manage data that is used during the course of a transaction. By excluding this object from transactions, you minimize the processing overhead implied by transactions.
Object Policies Defined for the Registrar Object
To make the Registrar object transactional, the ICF file specifies the always transaction policy for the Registrar interface. Therefore, in the Transaction sample application, the ICF file specifies the following object policies for the Registrar interface:
 
Object Policies Defined for the RegistrarFactory Object
To exclude the RegistrarFactory object from transactions, the ICF file specifies the ignore transaction policy for the Registrar interface. Therefore, in the Transaction sample application, the ICF file specifies the following object policies for the RegistrarFactory interface:
 
Using an XA Resource Manager in the Transactions Sample Application
The Transactions sample application uses the Oracle Transaction Manager Server (TMS), which handles object state data automatically. Using any XA resource manager imposes specific requirements on how different objects managed by the server application may read and write data to that database, including the following:
Some XA resource managers (for example, Oracle) require that all database operations be scoped within a transaction. This means that the CourseSynopsisEnumerator object needs to be scoped within a transaction because this object reads from a database.
This characteristic of XA resource managers actually makes the design problems associated with handling object state data in the event of a rollback much simpler. Transactional objects can always delegate the commit and rollback responsibilities to the XA resource manager, which greatly simplifies the task of implementing a server application.
Configuration Requirements for the Transactions Sample Application
The University sample applications use an Oracle transaction manager server (TMS). To use an Oracle database, you must include specific Oracle-provided files in the server application build process.
For details about building, configuring, and running the Transactions sample application, see the Guide to the CORBA University Sample Applications. This online document also contains the UBBCONFIG files for each sample application and explains the entries in that file.
Integrating Transactions in a CORBA Client and Server Application
The Oracle Tuxedo system supports transactions in the following ways:
Objects involved in a transaction can force a transaction to be rolled back. That is, after an object has been invoked within the scope of a transaction, the object can invoke the rollback_only() operation on the TransactionCurrent object to mark the transaction for rollback only. This prevents the current transaction from being committed. An object may need to mark a transaction for rollback if an entity, typically a database, is otherwise at risk of being updated with corrupt or inaccurate data.
When an object is polled, the object may veto the current transaction by invoking the rollback_only() operation on the TransactionCurrent object. In addition, if the current transaction is to be rolled back, objects have an opportunity to skip any writes to a database. If no object vetos the current transaction, the transaction is committed.
The following sections explain how you can use object activation policies and transaction policies to get the transactional behavior you want in your objects. Note that these policies apply to an interface and, therefore, to all operations on all objects implementing that interface.
Note:
Making an Object Automatically Transactional
The Oracle Tuxedo system provides the always transactional policy, which you can define on an object’s interface to have the Oracle Tuxedo system start a transaction automatically when that object is invoked and a transaction has not already been scoped. When an invocation on that object is completed, the Oracle Tuxedo system commits or rolls back the transaction automatically. Neither the server application, nor the object implementation, needs to invoke the TransactionCurrent object in this situation; the Oracle Tuxedo system automatically invokes the TransactionCurrent object on behalf of the server application.
Assigning the always transactional policy to an object’s interface is appropriate when:
If you want an object to be automatically transactional, assign the following policies to that object’s interface in the Implementation Configuration File (ICF file):
 
process, method, or transaction
Note:
Database cursors cannot span transactions. The CourseSynopsisEnumerator object in the CORBA University sample applications uses a database cursor to find matching course synopses from the University database. Because database cursors cannot span transactions, the activate_object() operation on the CourseSynopsisEnumerator object reads all matching course synopses into memory. Note that the cursor is managed by an iterator class and is thus not visible to the CourseSynopsisEnumerator object.
Enabling an Object to Participate in a Transaction
If you want an object to be able to be invoked within the scope of a transaction, you can assign the optional transaction policies to that object’s interface. The optional transaction policy may be appropriate for an object that does not perform any database write operations, but that you want to have the ability to be invoked during a transaction.
You can use the following policies, when specified in the ICF file for that object’s interface, to make an object optionally transactional:
 
process, method, or transaction
If the object does perform database write operations, and you want the object to be able to participate in a transaction, assigning the always transactional policy is generally a better choice. However, if you prefer, you can use the optional policy and encapsulate any write operations within invocations on the TransactionCurrent object. That is, within your operations that write data, scope a transaction around the write statements by invoking the TransactionCurrent object to, respectively, begin and commit or roll back the transaction, if the object is not already scoped within a transaction. This ensures that any database write operations are handled transactionally. This also introduces a performance efficiency: if the object is not invoked within the scope of a transaction, all the database read operations are nontransactional, and therefore more streamlined.
Note:
Preventing an Object from Being Invoked While a Transaction Is Scoped
In many cases, it may be critical to exclude an object from a transaction. If such an object is invoked during a transaction, the object returns an exception, which may cause the transaction to be rolled back. The Oracle Tuxedo system provides the never transaction policy, which you can assign to an object’s interface to specifically prevent that object from being invoked within the course of a transaction, even if the current transaction is suspended.
This transaction policy is appropriate for objects that write durable state to disk that cannot be rolled back; for example, for an object that writes data to a disk that is not managed by an XA resource manager. Having this capability in your client/server application is crucial if the client application does not or cannot know if some of its invocations are causing a transaction to be scoped. Therefore, if a transaction is scoped, and an object with this policy is invoked, the transaction can be rolled back.
To prevent an object from being invoked while a transaction is scoped, assign the following policies to that object’s interface in the ICF file:
 
process or method
Excluding an Object from an Ongoing Transaction
In some cases, it may be appropriate to permit an object to be invoked during the course of a transaction but also keep that object from being a part of the transaction. If such an object is invoked during a transaction, the transaction is automatically suspended. After the invocation on the object is completed, the transaction is automatically resumed. The Oracle Tuxedo system provides the ignore transaction policy for this purpose.
The ignore transaction policy may be appropriate for an object such as a factory that typically does not write data to disk. By excluding the factory from the transaction, the factory can be available to other client invocations during the course of a transaction. In addition, using this policy can introduce an efficiency into your server application because it minimizes the overhead of invoking objects transactionally.
To prevent any transaction from being propagated to an object, assign the following policies to that object’s interface in the ICF file:
 
process or method
Assigning Policies
For information about how to create an ICF file and specify policies on objects, see the section “Step 4: Define the In-memory Behavior of Objects” on page 2‑13.
Opening an XA Resource Manager
If an object’s interface has the always or optional transaction policy, you must invoke the TP::open_xa_rm() operation in the Server::initialize() operation in the Server object. The resource manager is opened using the information provided in the OPENINFO parameter, which is in the GROUPS section of the UBBCONFIG file. Note that the default version of the Server::initialize() operation automatically opens the resource manager.
If you have an object that does not write data to disk and that participates in a transaction—the object typically has the optional transaction policy—you still need to include an invocation to the TP::open_xa_rm() operation. In that invocation, specify the NULL resource manager.
Closing an XA Resource Manager
If your Server object’s Server::initialize() operation opens an XA resource manager, you must include the following invocation in the Server::release() operation:
TP::close_xa_rm();
Transactions and Object State Management
If you need transactions in your CORBA client and server application, you can integrate transactions with object state management in a few different ways. In general, the Oracle Tuxedo system can automatically scope the transaction for the duration of an operation invocation without requiring you to make any changes to your application’s logic or the way in which the object writes durable state to disk.
The following sections address some key points regarding transactions an object state management.
Delegating Object State Management to an XA Resource Manager
Using an XA resource manager, such as Oracle which is used in the CORBA University sample applications, generally simplifies the design problems associated with handling object state data in the event of a rollback. Transactional objects can always delegate the commit and rollback responsibilities to the XA resource manager, which greatly eases the task of implementing a server application. This means that process- or method-bound objects involved in a transaction can write to a database during transactions, and can depend on the resource manager to undo any data written to the database in the event of a transaction rollback.
Waiting Until Transaction Work Is Complete Before Writing to the Database
The transaction activation policy is a good choice for objects that maintain state in memory that you do not want written, or that cannot be written, to disk until the transaction work is complete. When you assign the transaction activation policy to an object, the object:
When the transaction work is complete, the Oracle Tuxedo system invokes each transaction-bound object’s Tobj_ServantBase::deactivate_object() operation, passing a reason code that can be either DR_TRANS_COMMITTING or DR_TRANS_ABORT. If the variable is DR_TRANS_COMMITTING, the object can invoke its database write operations. If the variable is DR_TRANS_ABORT, the object skips its write operations.
Assigning the transaction activation policy to an object may be appropriate in the following situations:
This introduces a performance efficiency because it reduces the number of database write operations that may need to be rolled back.
If the Oracle Tuxedo system passes the reason DR_TRANS_COMMITTING, the object can, if necessary, invoke the rollback_only() operation on the TransactionCurrent object. Note that if you do make an invocation to the rollback_only() operation from within the Tobj_ServantBase::deactivate_object() operation, the Tobj_ServantBase::deactivate_object() operation is not invoked again.
To give an object the ability to wait until the transaction is committing before writing to a database, assign the following policies to that object’s interface in the ICF file:
 
always or optional
Note:
Transaction-bound objects cannot start a transaction or invoke other objects from inside the Tobj_ServantBase::deactivate_object() operation. The only valid invocations transaction-bound objects can make inside the Tobj_ServantBase::deactivate_object() operation are write operations to the database.
Also, if you have an object that is involved in a transaction, the Server object that manages that object must include invocations to open and close, respectively, the XA resource manager, even if the object does not write any data to disk. (If you have a transactional object that does not write data to disk, you specify the NULL resource manager.) For more information about opening and closing an XA resource manager, see the sections “Opening an XA Resource Manager” on page 6‑13 and “Closing an XA Resource Manager” on page 6‑13.
Notes on Using Transactions in the Oracle Tuxedo System
Note the following about integrating transactions into your CORBA client/server applications:
You cannot start a new transaction if an existing transaction is already active. You may start a new transaction if you first suspend the existing one; however, the object that suspends the transaction is the only object that can subsequently resume the transaction.
A transactional object cannot call a second object, which in turn calls the first object.
CORBA::OBJ_ADAPTER
If a client that is in a transaction attempts to invoke an operation on an object that is currently in a different transaction, the client application receives the following error message:
CORBA::INVALID_TRANSACTION
For transaction-bound objects, you might consider doing all state handling in the Tobj_ServantBase::deactivate_object() operation. This makes it easier for the object to handle its state properly, since the outcome of the transaction is known at the time that the Tobj_ServantBase::deactivate_object() operation is invoked.
Assign the optional transaction policy.
If the object is invoked outside a transaction, the object does not incur the overhead of scoping a transaction for reading data. This way, regardless of whether the object is invoked within a transaction, all the object’s write operations are handled transactionally.
If an object with the always transaction policy is involved in a transaction that is started by the Oracle Tuxedo system, and not the client application, note the following:
If an exception is raised inside an operation on that object, the client application receives an OBJ_ADAPTER exception. In this situation, the Oracle Tuxedo system automatically rolls back the transaction. However, the client application is completely unaware that a transaction has been scoped in the Oracle Tuxedo domain.
Note:
If the TP::deactivateEnable method is invoked during a transaction, the object is deactivated when the transaction ends. However, if any methods are invoked on the object between the time that the TP::deactivateEnable method is called and the time that the transaction is committed, the object is never deactivated.
User-defined Exceptions
The Transactions sample application includes an instance of a user-defined exception, TooManyCredits. This exception is thrown by the server application when the client application tries to register a student for a course, and the student has exceeded the maximum number of courses for which he or she can register. When the client application catches this exception, the client application rolls back the transaction that registers a student for a course. This section explains how you can define and implement user-defined exceptions in your CORBA client/server application, using the TooManyCredits exception as an example.
Including a user-defined exception in a CORBA client/server application involves the following steps:
1.
2.
3.
The sections that follow explain and give examples of the first two steps.
Defining the Exception
In the OMG IDL file for your client/server application:
1.
Define the exception and define the data sent with the exception. For example, the TooManyCredits exception is defined to pass a short integer representing the maximum number of credits for which a student can register. Therefore, the definition for the TooManyCredits exception contains the following OMG IDL statements:
exception TooManyCredits
{
unsigned short maximum_credits;
};
2.
NotRegisteredList register_for_courses(
in StudentId student,
in CourseNumberList courses)
raises (TooManyCredits);
Throwing the Exception
In the implementation of the operation that uses the exception, write the code that throws the exception, as in the following example.
if ( ... ) {
UniversityZ::TooManyCredits e;
e.maximum_credits = 18;
throw e;
}
 

Copyright © 1994, 2017, Oracle and/or its affiliates. All rights reserved.