Providing support for transactions

Benefits of EAServer’s transaction support

EAServer components that you develop in PowerBuilder can participate in EAServer transactions. An EAServer transaction is a transaction whose boundaries and outcome are determined by EAServer. You can mark components to indicate that they will provide transaction support. When a component provides transaction support, EAServer ensures that the component’s database operations execute as part of a transaction.

Multiple EAServer components can participate in a single EAServer transaction; EAServer ensures that database changes performed by the participating components are all committed or rolled back. By defining components to use EAServer transactions, you can ensure that all work performed by components that participate in a transaction occurs as intended.

Indicating how the component will support transactions

Each EAServer component has a transaction attribute that indicates how the component participates in EAServer transactions. When you develop an EAServer component in PowerBuilder, you can specify the transaction attribute in the wizards. Table 23-4 lists the options.

Table 23-4: Transaction attribute options

Transaction type

Description

Not supported

The component never executes as part of a transaction. If the component is activated by another component that is executing within a transaction, the new instance’s work is performed outside the existing transaction.

Supports Transaction

The component can execute in the context of an EAServer transaction, but a transaction is not required to execute the component’s methods. If the component is instantiated directly by a client, EAServer does not begin a transaction. If component A is instantiated by component B and component B is executing within a transaction, component A executes in the same transaction.

Requires Transaction

The component always executes in a transaction. When the component is instantiated directly by a client, a new transaction begins. If component A is activated by component B and B is executing within a transaction, A executes within the same transaction; if B is not executing in a transaction, A executes in a new transaction.

Requires New Transaction

Whenever the component is instantiated, a new transaction begins. If component A is activated by component B, and B is executing within a transaction, then A begins a new transaction that is unaffected by the outcome of B’s transaction; if B is not executing in a transaction, A executes in a new transaction.

Mandatory

Methods can be invoked only by a client that has an outstanding transaction. Calling this component when there is no outstanding transaction generates a runtime error.

OTS Style

The component can manage transactions. It can inherit a client’s transaction. If called without a transaction, the component can explicitly begin, commit, and roll back transactions using an instance of the CORBACurrent context service object.

Never

Methods cannot be invoked when there is an outstanding transaction. Calling this component when there is an outstanding transaction generates a runtime error.

Using the transaction service context object

Component methods can call EAServer’s transaction state primitives to influence whether EAServer commits or aborts the current transaction. To give you access to EAServer’s transaction state primitives, PowerBuilder provides a transaction service context object called TransactionServer.

If you plan to use the TransactionServer context object, you should set the UseContextObject DBParm parameter to Yes.

For transactional components, setting UseContextObject to Yes tells PowerBuilder that you will be using the methods of the TransactionServer object rather than COMMIT and ROLLBACK to indicate whether the component has completed its work for the current transaction. If your scripts contain COMMIT and ROLLBACK statements, they will generate a runtime error. Setting UseContextObject to No causes COMMIT and ROLLBACK statements to call the EAServer transaction service’s CommitWork and AbortWork methods. You should only use this setting if you want to retain legacy code and you do not want to use the TransactionServer object.

For components that do not need to be in a transaction, the UseContextObject setting is ignored and PowerBuilder drivers handle COMMIT and ROLLBACK statements.

To use the transaction context service, declare a variable of type TransactionServer and call the GetContextService function to create an instance of the service.

Example In the Activate (or Constructor) event for a component, you can call GetContextService to instantiate the TransactionServer service:

// Instance variable:
// TransactionServer ts

Integer li_rc
li_rc = this.GetContextService("TransactionServer", &
   ts)
IF li_rc <> 1 THEN
   // handle the error
END IF

In one of the component methods, you can then update the database and call SetComplete if the update succeeds or SetAbort if it fails:

//Instance variable:
//DataStore ids_datastore
long ll_rv
...
...
ll_rv = ids_datastore.Update()
IF ll_rv = 1 THEN
   ts.SetComplete()
ELSE
   ts.SetAbort()
END IF

The TransactionServer interface provides the methods in Table 23-5 to allow you to access EAServer’s transaction primitives.

Table 23-5: TransactionServer methods

Method

Description

DisableCommit

Indicates that the current transaction cannot be committed because the component’s work has not been completed. The instance remains active after the current method returns.

EnableCommit

Indicates that the component should not be deactivated after the current method invocation; allows the current transaction to be committed if the component instance is deactivated.

IsInTransaction

Determines whether the current method is executing in a transaction.

IsTransactionAborted

Determines whether the current transaction has been aborted.

SetAbort

Indicates that the component cannot complete its work for the current transaction and that the transaction should be rolled back. The component instance will be deactivated when the method returns.

SetComplete

Indicates that the component has completed its work in the current transaction and that, as far as it is concerned, the transaction can be committed and the component instance can be deactivated.

Automatic Demarcation/ Deactivation

If you want a component to be automatically deactivated after each method invocation, you can enable Automatic Demarcation/Deactivation for the component. This sets the component’s tx_vote property to FALSE. When Automatic Demarcation/Deactivation is enabled, you do not need to make explicit calls to SetComplete to cause deactivation because SetComplete is assumed by default. To roll back the transaction, you can call SetAbort.

If you do not want the component to be automatically deactivated after each method invocation, disable the Automatic Demarcation/Deactivation setting for the component. This sets the component’s tx_vote property to TRUE. When you disable Automatic Demarcation/Deactivation, EAServer waits for notification before completing transactions; therefore, be sure to deactivate programmatically by making an explicit call to SetComplete (or SetAbort).

COMMIT and ROLLBACK

You have the option to disable the TransactionServer context object and use the COMMIT and ROLLBACK statements instead to specify the EAServer transaction state for a component. This capability is provided to allow you to migrate PowerBuilder 6 objects to EAServer without modifying the code. To disable the TransactionServer context object, set the UseContextObject DBParm parameter to No. When you do this, COMMIT is equivalent to SetComplete and ROLLBACK is equivalent to SetAbort.

NoteCOMMIT and ROLLBACK in nontransactional components In nontransactional components that disable the TransactionServer context object, COMMIT does not invoke SetComplete and ROLLBACK does not invoke SetAbort. For example, if you specify Not Supported as the transaction type, disable Automatic Demarcation/Deactivation (set tx_vote to TRUE), and set the UseContextObject parameter to No, the PowerBuilder virtual machine does not issue a SetComplete when you execute a COMMIT (or a SetAbort when you execute a ROLLBACK). In this case, EAServer never releases the component because it is waiting for a call to SetComplete or SetAbort.

If you disable Automatic Demarcation/Deactivation for a component that performs no database access whatsoever, then you must use the TransactionServer object to call SetComplete (or SetAbort) to deactivate the component. Otherwise, the component will never be deactivated.

Transaction handling and runtime errors

You can control the behavior of EAServer when an internal exception occurs in the PBVM or a PowerBuilder component raises a runtime exception. To do so, set the PBOnFatalError or PBRollbackOnRTError environment variables in a batch file or as a system environment variable on the server on which the component runs.

Table 23-6: Environment variables for handling exceptions

Variable

Description

PBOnFatalError

Specifies whether EAServer should continue, shut down, or restart when an internal exception occurs in the PBVM. The default behavior is that EAServer shuts down. An unhandled internal exception raised by a PowerBuilder component running in EAServer can cause the PBVM to become unstable, resulting in unpredictable behavior.

Values are:

  • continueEAServer continues to run, and the CORBA_TRANSACTION_ROLLEDBACK exception is thrown

  • restartEAServer restarts automatically

  • shutdownEAServer shuts down automatically (default)

PBRollbackOnRTError

Specifies how a transaction is handled when a runtime exception is raised by a PowerBuilder component running in EAServer. By default, the transaction is rolled back and the exception is thrown back to the client.

Values are:

  • n, no, or false – the transaction is committed before the exception is thrown back to the client

  • y, yes, or true – the transaction is rolled back before the exception is thrown back to the client (default)

Transactions and the component lifecycle

EAServer’s transaction model and the component lifecycle are tightly integrated. Component instances that participate in a transaction are never deactivated until the transaction ends or until the component indicates that its contribution to the transaction is over (its work is done and ready for commit or its work must be rolled back). An instance’s time in the active state corresponds exactly to the beginning and end of its participation in a transaction.

For more information, see the EAServer documentation.