Client- and component-demarcated transactions

Client applications and EAServer components marked as OTS style or Bean Managed can create, control, and obtain information about EAServer transactions using functions of the CORBACurrent context service object. The CORBACurrent object provides most of the methods defined for the CORBA Current interface.

Two-phase commit

Components in a client- or component-demarcated transaction must be running on a server that is using the OTS/XA transaction coordinator. This transaction coordinator supports the two-phase commit protocol, which uses detailed records from all participants to protect against system failures. In the prepare phase, the transaction coordinator obtains a guarantee from every participant in the transaction that it can be committed and writes a prepare record to the log. In the commit phase, the coordinator notifies all participants, resources are released, the transaction is committed, and a commit record is written to the log.

Components using two-phase commit must connect to a database using a PowerBuilder database interface that is XA-compliant.

An OTS/XA transaction coordinator uses XA resources instead of connection caches to manage transactions. For more information about creating and managing XA resources, see the EAServer documentation.

Creating components that can manage transactions

To create an EAServer component that can manage transactions, check the OTS Style box in the EAServer Project wizard or the Project painter. You can also select OTS Style on the Transaction tab of the property sheet for the component in EAServer Manager or Bean Managed in the Management Console after you have deployed the component.

Initializing the CORBACurrent object

Before you can invoke the functions of the CORBACurrent context service object, you need to create an instance of the object using the GetContextService function, and then initialize it using the Init function.

For transactions managed by a component, call the Init function with no arguments:

GetContextService("CORBACurrent", myCorbCurr)
myCorbCurr.Init()

For client-demarcated transactions, you must call the Init function with an argument: either an instance of the Connection object with which you have already established a connection, or a URL that identifies a valid EAServer host.

Because the Connection object is more portable, using it is the preferred technique.

myCorbCurr.Init( myconnect )
// OR
myCorbCurr.Init( "iiop://localhost:2000")

Beginning and ending transactions

You begin a client- or component-demarcated transaction by calling the BeginTransaction function and end it by calling CommitTransaction or RollbackTransaction. Components you instantiate to participate in the transaction must support transactions.

Example 3

// Instance variables:
// CORBACurrent corbcurr
// Connection myconnect


int li_rc
long ll_rc
boolean lb_rc, lb_success

ll_rc = myconnect.CreateInstance(mycomponent)
li_rc = this.GetContextService("CORBACurrent", &	
		corbcurr)
IF li_rc <> 1 THEN
		// handle error
		RETURN
END IF

li_rc = corbcurr.Init( myconnect )
IF li_rc <> 0 THEN
		// handle error
		RETURN
END IF

lb_rc = corbcurr.BeginTransaction()
// perform some processing on the server and
// test for success
...
IF lb_success THEN
		corbcurr.CommitTransaction()
ELSE
		corbcurr.RollbackTransaction()
END IF

NoteNo nested transactions You cannot begin a second transaction until the first transaction has been committed or rolled back.

If a component is marked as OTS style, EAServer does not start a transaction when the component is instantiated. EAServer expects the component to start a transaction by calling the BeginTransaction function on an instance of a CORBACurrent object.

NoteDo not call SetComplete A component should not begin a transaction and then call SetComplete before committing or rolling back the transaction. The transaction will be orphaned until it either times out or is picked up by another transaction.

Getting information about the transaction

CORBACurrent provides two functions for obtaining information about the transaction: GetStatus and GetTransactionName. GetStatus returns an Integer that indicates whether the transaction is active, has been marked for rollback, is in the prepare phase or commit phase, or has been committed or rolled back. GetTransactionName returns a String that identifies the current transaction. It is intended for use in debugging.

Suspending and resuming a transaction

A calling thread can suspend a transaction while the thread performs some non-transactional processing and then resume it. SuspendTransaction returns a handle to the transaction that can be passed to the ResumeTransaction function. ResumeTransaction can be called from a different thread in the same execution context. In this example, the transaction is reassociated with the same thread:

Example 4

long ll_rc
unsignedlong ll_handle
...
ll_rc = corbcurr.BeginTransaction()
// do some transactional work
ll_handle = corbcurr.SuspendTransaction()
// do some non-transactional work
corbcurr.ResumeTransaction(ll_handle)
// do some more transactional work

Setting a timeout period for transactions

A calling thread can specify a timeout period after which a transaction will be rolled back. This example sets the timeout period to three minutes (180 seconds):

Example 5

integer li_rc


li_rc = this.GetContextService("CORBACurrent", &
		corbcurr)
IF li_rc <> 1 THEN
		// handle error and return
END IF
li_rc = corbcurr.Init()
IF li_rc <> 1 THEN
		// handle error and return
END IF
corbcurr.SetTimeout(180)
corbcurr.BeginTransaction()