These sections describe how to integrate transactions into an Oracle Tuxedo server application. Before you begin, you should read Chapter 1, “Introducing Transactions.”
•
• You can assign transactional policies to an object’s interface so that when the object is invoked, the Oracle Tuxedo system can start a transaction automatically for that object, if a transaction has not already been started, and commit or roll back the transaction when the method invocation is complete. You use transactional policies on objects in conjunction with an XA resource manager and database when you want to delegate all the transaction commit and rollback responsibilities to that resource manager.
• 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 rollback_only() 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 rollback_only() 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 vetoes the current transaction, the transaction is committed.
Note: If a server application manages an object that you want to be able to participate in a transaction, the Server object for that application must invoke the TP::open_xa_rm() and TP::close_xa_rm() operations. For more information about database connections, see “Opening an XA Resource Manager” on page 3‑7.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.Assign the always transactional policy to an object’s interface when:
•
•
Note: Database cursors cannot span transactions. However, in C++, the CourseSynopsisEnumerator object in the Oracle Tuxedo 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.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.
•
• When the transaction policy is optional, if the AUTOTRAN parameter is enabled in the application’s UBBCONFIG file, the implementation is transactional. Servers containing transactional objects must be configured within a group associated with an XA-compliant resource manager.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.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. Oracle Tuxedo CORBA 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.
•
• 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. Oracle Tuxedo CORBA 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.
•
• For information about how to create an Implementation Configuration File and specify policies on objects, see “Step 4: Define the in-memory behavior of objects” in “Steps for Creating an Oracle Tuxedo CORBA Server Application” in the CORBA Programming Reference.The Transaction Manager Server (TMS) handles object state data automatically. For an example, the University sample C++ application in the drive:\TUX8\samples\corba\university\transactions directory uses the Oracle TMS as an example of a relational database management service (RDBMS).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.If your Server object’s Server::initialize() operation opens an XA resource manager, you must include the following invocation in the Server::release() operation: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, Oracle Tuxedo CORBA 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_ABORTED. If the variable is DR_TRANS_COMMITTING, the object can invoke its database write operations. If the variable is DR_TRANS_ABORTED, the object skips its write operations.Assigning the transaction activation policy to an object may be appropriate in the following situations:
• If Oracle Tuxedo CORBA passes the reason DR_TRANS_COMMITTING, the object can, if necessary, invoke rollback_only() on the TransactionCurrent object. Note that if you do make an invocation to rollback_only() from within the Tobj_ServantBase::deactivate_object() operation, then deactivate_object() is not invoked again.
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 deactivate_object() 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 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 “Opening an XA Resource Manager” on page 3‑7 and “Closing an XA Resource Manager” on page 3‑8.For example, the Transactions sample C++ 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 Oracle Tuxedo CORBA client/server application, using the TooManyCredits exception as an example.
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:
2. In the definition of the operations that throw the exception, include the exception. The following example shows the OMG IDL statements for the register_for_courses() operation on the Registrar interface:
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:
• 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.In implementing this design, the Transactions sample application shows one model of the use of transactions, which were described in “Integrating Transactions in an Oracle Tuxedo Client and Server Application” on page 3‑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 register_for_courses() operation performs multiple checks of the University database. If any one of those checks fail, the transaction can be rolled back.Because the Registrar object is being used for database transactions, a good design choice for this object is to make it transactional (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.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:
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:
The University sample applications use an Oracle Transaction Manager Server (TMS). To use the Oracle database, you must include specific Oracle-provided files in the server application build process. For more information about building, configuring, and running the Transactions sample application, see The Transaction Sample Application in the Oracle Tuxedo online documentation. For more information about the configurable settings in the UBBCONFIG file, see “Modifying the UBBCONFIG File to Accommodate Transactions” on page 5‑2.