Defining transactional semantics

StepsTo define how a component participates in transactions, you must:

  1. Choose a transaction coordinator. The transaction coordinator manages the flow of transactions that involve more than one connection. “Transaction coordinators” describes the available options.

  2. Specify the component’s transaction attribute. Each component has a transaction attribute that determines whether instances of the component participate in transactions. “Transactional component attribute” describes the attribute settings and their meanings.

  3. Code methods to call the EJB Server transaction state primitives. Each method should call the appropriate transaction state primitive to reflect the state of the work that the component has contributed to the transaction. “Using transaction state primitives” describes the state primitives in detail.

  4. Specify a transaction timeout period if needed. By default, transactions are never timed out. You can configure a finite timeout period in the Adaptive Server plug-in. See “Transaction Timeout property” for more information.

Transaction coordinators

All components installed in one EJB Server share the same transaction coordinator.

Choices for transaction coordinator include:

The default coordinator is the “Shared Connection” coordinator. To view or change the coordinator, use the Server Properties dialog box in the Adaptive Server plug-in.

Transactional component attribute

Components in EJB Server have a transaction attribute that indicates how a component participates in transactions. You can view and change a component’s transaction attribute using the Adaptive Server plug-in; the attribute is displayed on the Transactions tab in the Component Properties window. The attribute has the following values:

The following table lists design scenarios and the transaction attributes that apply to each.

Table 5-1: Deciding on a transaction attribute

Design scenario

Applicable transaction attributes

Your component interacts with the database, and its methods may be called by another component as part of a larger transaction. Multiple updates are issued before calling completeWork, or an update depends on the results of queries that were issued since the last call to completeWork.

Requires Transaction or Requires New Transaction

Updates from your component are performed by a single database update, the update logic is independent of any other query issued by the method, and you call completeWork in each method that issues an update. In other words, your component’s updates are already atomic.

Supports Transaction

Your component’s methods make intercomponent method calls, and the work done by called components must be included in one transaction.

Requires Transaction or Requires New Transaction

Methods in the component interact with more than one database, and updates to different databases must be grouped in the same transaction (this also requires a transaction coordinator that supports two-phase commit to those databases).

Requires Transaction or Requires New Transaction

Transactions begun by your component must not be affected by the outcome of transactions begun by other components that call your component.

Requires New Transaction

Work done by your component must never be done as part of a transaction.

Not Supported

For example, in the scenario illustrated in “A transaction involving multiple components”, the Enrollment component must be marked Requires Transaction or Requires New Transaction, since it calls methods in the Registrar and StudentBilling components, and the work performed by the called components must be grouped in a single transaction. Both Registrar and StudentBilling must be marked Supports Transaction or Requires Transaction so that their database updates can be grouped in the transaction begun by the Enrollment component.

Transaction Not Supported is useful when your component performs updates to a noncritical database. For example, consider a component whose sole function is to log usage statistics to the database. Since usage statistics are not mission-critical data, you can choose Not Supported as the component’s transaction attribute to ensure that the logging updates do not incur the overhead of using two-phase commit.

Determining when transactions begin

After a base client instantiates a transactional component, the first method invocation begins an EJB Server transaction. This instance is said to be the root instance of the transaction. If the root instance invokes methods in other transactional components, those components join the existing transaction.

The outcome of the transaction is determined by how the participating components call the transaction state primitives discussed in “Using transaction state primitives”.

NoteUse the home interface for the called component. For transactions to occur with the intended semantics, you must perform intercomponent calls using the home interface. Do not invoke another component’s methods directly.

Using transaction state primitives

EJB Server provides transaction state primitives that methods can call to direct the outcome of the current transaction. Each component model provides an interface containing methods for these primitives.

These methods end a component’s participation in a transaction (both cause the current instance to be deactivated):

These methods are used to maintain state after the method returns (they delay deactivation of the component instance):

These primitives can be used to query the state of the transaction (if any) in which the method is executing:

Table 5-2 describes how the transaction primitives are invoked in Java components.

Table 5-2: Java transaction primitives

Transaction primitive

Java InstanceContext

method

completeWork

completeWork

rollbackWork

rollbackWork

continueWork

continueWork

disallowCommit

None. You can achieve the same effect by calling, and then raising an exception if deactivate is called before the next method invocation.

isInTransaction

inTransaction

isRollbackOnly

isRollbackOnly

Any participating component can roll back the transaction by calling the rollbackWork primitive; Java components can also cause a rollback by returning an unhandled exception. Only the action of the root component determines when EJB Server commits the transaction. The transaction is committed when the root component returns with a state of completeWork and no participating component has set a state of disallowCommit.

You can use the transaction state primitives in any component; the component does not have to be declared transactional. Calling completeWork or rollbackWork from methods causes early deactivation.

Transaction Timeout property

The root instance’s Transaction Timeout property specifies the maximum duration of an EJB Server transaction. The default timeout period is infinite. You can configure finite timeouts in the Adaptive Server plug-in, as described in “Resources tab component properties”.

A transaction begins when a base client activates a transactional component; this component is the root component of the transaction. The root component’s Transaction Timeout property determines the maximum duration of the transaction.

If the transaction is not committed or rolled back within the allotted time, it is automatically rolled back. In this case, the client receives the CORBA TRANSACTION_ROLLEDBACK exception when it tries another method invocation. The client’s object reference remains valid, and the transaction can be retried.

Transactions are never rolled back in the middle of a method invocation. If the timeout occurs during a method invocation, and the method does not commit the transaction, the transaction is rolled back when the invocation completes.