Sybase Business Intelligence Solutions - Database Management, Data Warehousing Software, Mobile Enterprise Applications and Messaging
Sybase Brand Color Bar
delete

Search for    in all of Sybase.com
view all search results right arrow
  blank
 
 
 
 
 
 
 
 
 
 

 
 
CLICK TO EXPAND NAVIGATION
CLICK TO EXPAND NAVIGATION
 
 
 
 
Support > Technical Documents > Document Types > White Paper-Technical > Transaction Management in Enterprise Application S...

Transaction Management in Enterprise Application Server 3.0

This article, originally published in PowerTimes magazine, describes transaction management with Enterprise Application Server™ (EAServer) and shows how this affects component and application design.
 
RSS Feed
 
 
 

By: William B. Heys,
Senior Consultant, Whittman-Hart, Inc.

This article originally appeared in PowerTimes magazine.

Click here to download the pdf version of this document.

Introduction

Transaction management is one of the most important elements of good application architecture and design. In this article, I will describe transaction management with Enterprise Application Server™ (EAServer) and show how this will affect your component and application design.

Transaction Management Topics

  • Introducing Transactions

  • Transaction Management in Traditional Client/Server Applications

  • Transaction Management in Jaguar™

  • Component Transaction Properties

  • Transaction Server Object

  • Transaction State Primitives

  • Stateful vs. Stateless Components

  • Component Deactivation

  • Connection Management

  • Transaction Coordinators

  • Component Design

  • Summary

Introducing Transactions

A transaction is comprised of one or more SQL statements grouped together into an atomic unit of work that must succeed or fail as a whole. By grouping multiple SQL requests into a single unit of work, it is possible to ensure database consistency. Proper transaction management ensures that all databases updated by an application are always left in a consistent state.

Databases use transactions to implement isolation. All changes made by one user within a transaction should be isolated from changes made by other users running simultaneously.

Proper transaction design and management is necessary to maximize the concurrency of an application. Without proper transaction management, updates made by one user may cause long-duration locks to be placed on large numbers of rows in the database. Until these locks are released, other users will be unable to access or update these rows, and may even be put into extended wait periods. To increase concurrency, one must minimize the scope and duration of transactions, while at the same time being careful to maintain database consistency.

Article Outline

  1. Introduction & Introducing Transactions

  2. Transaction Management in Traditional Client/Server Applications & Transaction Management in Jaguar

  3. Component Transaction Properties & Transaction Server Object

  4. Transaction State Primitives & Stateful vs. Stateless Components

  5. Component Deactivation & Connection Management

  6. Transaction Coodination & Component Design

  7. Summary & About the Author

Transaction Management in Traditional Client/Server Applications

In traditional client/server two-tier applications, transaction management is the responsibility of the client application. When an application connects to the database, a new database transaction is started. The current transaction ends and a new transaction begins when the application sends a COMMIT or ROLLBACK request to the database.

To support transaction management, a database uses a combination of logging and locking. All changes made to a database are written to a log file. When a row is deleted, an image of the deleted row is written to the log. When a row is changed, an image of the row before changes are applied is written to the log. When a new row is inserted, the primary key of the new row is written to the log. 

All database updates made by an application remain in a pending state until the outcome of the transaction is known. To ensure proper isolation, the database places locks on updated rows (or pages). These locks prevent other applications from reading or updating a row while it is in an update pending state.

When a transaction is committed, all database changes made by the application since the start of the transaction are made permanent, and all update locks are released. The current transaction ends and a new transaction begins.

When a transaction is rolled back, all database changes made since the start of the transaction are removed from the database. Using the log, the database is returned to its state when the transaction was started, and all update locks are released. The current transaction ends and a new transaction begins.

Back to article outline.

Transaction Management in Jaguar

Responsibility for transaction management in Jaguar shifts from the client application to the Jaguar Transaction Manager. Jaguar changes how transactions are managed and controlled. Rather than being scripted, transaction management becomes a deployment-time component property. The Jaguar Transaction Manager allows you to group database updates performed by multiple components into a single atomic unit of work.

Components utilizing Jaguar's transaction management participate in implicit transactions. Rather than directly controlling the outcome of a transaction using COMMIT or ROLLBACK database commands, a component votes on the outcome of a transaction by invoking transaction state primitives. 

If a component does not participate in implicit transactions, it can explicitly manage its own transaction by issuing COMMIT and ROLLBACK database commands.

Back to article outline.

Component Transaction Properties

Jaguar components have a transaction support property governing how the component participates in Jaguar transactions. The transaction support property has one of the following values:

  • Transaction Not Supported

  • Supports Transaction

  • Requires Transaction

  • Requires New Transaction

Transactions currently running within an implicit Jaguar-managed transaction are characterized as transactional components. Components that are not currently running within an implicit transaction are non-transactional.

When a component specifies a transaction is not supported, it never runs in an implicit transaction managed by Jaguar, and must manage its own transactions explicitly. 

A component that supports a transaction may or may not participate in an implicit transaction. If the component is invoked by a transactional component, it will participate in the invoking component's transaction. If the component is invoked directly by the client or by another non-transactional component, it will not be part of a transaction.

A component that requires a transaction will always participate in an implicit transaction. If the component is invoked by a transactional component, it will participate in the invoking component's transaction. If the component is invoked directly by the client or by a non-transactional component, it will start a new transaction.

When a component requires a new transaction, it will always start a new transaction regardless of how it is invoked. If the component is invoked by another transactional component, the invoking component's transaction will be separate from the invoked component's transaction.

Back to article outline.

TransactionServer Object

PowerBuilder provides a special transaction service context object called TransactionServer. To use Jaguar's implicit transaction management, components must create a TransactionServer object.

First declare an instance variable of type TransactionServer:

Protected:
TransactionServer its_transactionserver

Next, create the TransactionServer object in the activate event of the component using the GetContextService function:

this.GetContextService &
        "TransactionServer", &
        its_transactionserver)

The TransactionServer object should be destroyed in the component's deactivate event. 

Back to article outline.

Transaction State Primitives

Components participate in implicit transaction management by invoking transaction state primitives, which are methods of the TransactionServer object. These primitives are:

  • CompleteWork

  • RollbackWork

  • ContinueWork

  • DisableCommit

  • InTransaction

  • IsRollbackOnly

Each of these transaction primitives has corresponding methods of the TransactionServer object. In PowerBuilder, these methods are:

  • SetComplete

  • SetAbort

  • EnableCommit

  • DisableCommit

  • IsInTransaction

  • IsTransactionAborted

Transaction state primitives serve two functions. First, they are used are used by a component in place of SQL COMMIT and ROLLBACK requests to vote on the success or failure of the transaction. Second, they indicate whether the component should be deactivated or remain bound to the client.

The first two state primitives, CompleteWork (SetComplete) and RollbackWork (SetAbort), vote on the success or failure of the transaction and cause the component to be deactivated. 

The second two state primitives, ContinueWork (EnableCommit) and DisableCommit (DisableCommit) are only used by a component to vote on the success or failure of the transaction but do not cause the component to be deactivated.

The last two state primitives allow a component to query the state of its transaction. To determine whether the current method is running within a transaction, it calls the InTransaction primitive (IsInTransaction). To determine whether the transaction has already been aborted, it invokes the IsRollbackOnly primitive (IsTransactionAborted).

Individual components can only vote for the success or failure of a transaction. The transaction does not end until the root component of the transaction is deactivated. At that time, the votes issued by participating components are counted. If any no vote is received, the transaction is aborted and databases changes are rolled back. If only yes votes are received, the transaction succeeds and database changes are committed.

Back to article outline.

Stateful vs. Stateless Components

A stateful component maintains information about a client across method invocations. Typically stateful components remain bound to a client and store state information in properties or instance variables. While bound to a particular client, a stateful component cannot be shared or used by any other client.

Stateless components are deactivated and unbound from a client following each method call. Because stateless components do not store information in properties or instance variables across method invocations, they can be released reused by other clients more quickly.

There are many disadvantages to stateful components. Stateful components have longer lifetimes and require more resources than stateless components. More instances of a stateful component must be created to support a given number of clients. 

Stateful components also tend to cause an increase of network traffic. A client may invoke several methods on the same component instance to change or retrieve information saved in its instance variables. For example, with a stateful component, a client may call one method to retrieve data from the database into a data store in the component. Without releasing the component, the client will subsequently invoke additional methods to bring this data from the data store back to the client. In order to make the component stateless, the data must be retrieved and returned in a single method invocation.

Applications built with stateless components will be more scalable than applications built with stateful components. Stateless components are better able to take advantage of server clusters, load balancing, and the automatic failover features of Jaguar.

Back to article outline.

Component Deactivation

Stateless components can support early deactivation. Such components are automatically deactivated when a method returns. To enable early deactivation a component must be stateless and must set the deployment-time property for automatic demarcation/deactivation to true.

A stateful component must tell Jaguar when it can be deactivated. If the component participated in implicit transactions, the component invokes transaction primitives SetComplete or SetAbort to cause deactivation. If a component must remain bound to a client, it alternatively invokes the transaction primitives EnableCommit or DisableCommit. Stateless components are also deactivated when a method returns after invoking the SetComplete or SetAbort methods.

Back to article outline.

Connection Management

Jaguar can maintain connection caches which are pools of database connections. Rather than physically connect and disconnect from a database, a component can request a connection from the connection manager. If a connection is available in the pool, it will be reused. Otherwise, a new physical connection is created.

When such a connection is released by a component, it is returned to the pool, but not physically disconnected from the database. The connection is now available for reuse.

Connection caching improves performance by reducing the total number of physical database connections. Connection caching is also necessary if you want Jaguar to manage transactions.

Back to article outline.

Transaction Coordinators

Jaguar supports two transaction coordinators. The default transaction coordinator is Jaguar's Shared Connection coordinator. With the Shared Connection coordinator, a component must use a database connection cache. By using a connection cache, Jaguar ensures all components participating in the same implicit transaction also use the same physical database connection.

Jaguar also supports Microsoft's Distributed Transaction Coordinator (DTC). The DTC supports transactions spanning multiple database connections using two-phase commit. In order to use DTC, you must be using Windows NT, ODBC, and a DTC-compliant database. At the current time, only Microsoft SQL Server is DTC-compliant.

In the future, Jaguar will support additional transaction coordinators. The Java Transaction Server (JTS) and the CORBA Object Transaction Server (OTS) will be supported. In addition, Jaguar will support Transarc Encina's two-phase commit process.

Back to article outline.

Component Design

When illustrating transaction management, almost everyone seems to use the ATM example. In this example, a customer wishes to transfer some money from one account to another. Let's say the customer wants to transfer $100.00 from his checking account to his savings account. The application probably needs a method to withdraw money from one account and another method to deposit money to the second account. A third method would create an audit trail of the transfer transaction.

An initial design might involve two classes. The first would be an account class with two methods, Withdraw () and Deposit (). The second would be a log class with one method, Log ().

If this was a two-tier client/server application, the application might instantiate two instances of the account class (one for the checking account and one for the savings account) and one instance of the log class. Pseudo code for this transaction might look something like this:

Integer ll_rc
 Decimal ld_amount
 Connect using SQLCA;
 ld_amount = 100.00
 li_rc = AccountFrom.Withdraw (ld_amount)
 IF li_rc > 0 THEN
  li_rc = AccountTo. Deposit (ld_amount)
 END IF
 IF li_rc > 0 THEN
  li_rc = Log.Log (AccountFrom.Nbr,  &
           AccountTo.Nbr, ld_amount)
 END IF
 IF li_rc > 0 THEN
   Commit Using SQLCA;
 ELSE
    Rollback Using SQLCA;
 END IF
 Disconnect Using SQLCA;

Next, we deploy these components to Jaguar. Since we want one transaction to encompass all three methods, Withdraw (), Deposit (), and Log (), we deploy both components with transaction support. Start by setting both components to Requires Transaction. What happens when the client application instantiates two account components and one log component? Each will start and run in its own transaction. Whenever a component is instantiated by the client, it cannot participate in the same transaction with other components instantiated by the client.

To solve this problem, create a third component for the customer. This component would have one method, Transfer. The customer component should be deployed to Jaguar with the Requires Transaction setting.

The client application instantiates only the customer component. The customer component becomes the root instance of a single Jaguar transaction. The customer component becomes like a container object and instantiates the two account components and the log component. Since the customer component is running in a transaction when it creates the account and log components, they run within the customer's transaction.

The client application calls the customer component's Transfer method, passing the transfer amount, and two account numbers. The transfer method, in turn, calls the Withdraw method for the first account and the Deposit method for the second account and finally the Log method for the log component. All three method invocations will be part of a single atomic transaction.

A benefit of implementing the Log method in its own component is flexibility in the design of the transaction. To separate the Log method from the transaction involving the Withdraw and Deposit methods, simply change the log component's transaction support from Requires Transaction to Requires New Transaction. The Withdraw and Deposit methods remain as part of one transaction while the log method becomes a second separate transaction.

Back to article outline.

Summary

With Enterprise Application Server components, transaction management is very different from traditional client/server applications. Because of these differences, you will want to design your components differently when you deploy them to Jaguar. Since transaction support is now set at the component level with a deployment-time property, rather than controlled in scripts, you will probably want to design smaller, simpler, more granular components.

Most of us probably were not aware of the benefits of stateless components when we designed business objects for two-tier client/server applications or Distributed PowerBuilder. Designs incorporating stateless components and connection caches can take advantage of instance pooling, early deactivation, and implicit transaction management resulting in more flexible, scaleable, higher performing applications.

About the Author

Bill Heys (CPD, CPI) is a Senior Consultant at Whittman-Hart, Inc. in Lexington, MA. Bill spoke at the Sybase TechWave conference in Orlando and will be speaking at the Swiss Sybase and PowerBuilder User Group meeting in Zurich on October 21. You may write Bill at bheys@whittman-hart.com.


 

DOCUMENT ATTRIBUTES
Last Revised: Jan 07, 2000
Product: EAServer, Jaguar CTS
Hardware Platform: Windows x86
Technical Topics: Application Deployment, Transaction Processing, Application Development
  
Business or Technical: Technical
Content Id: 1001908
Infotype: White Paper-Technical
 
 
 

 
© Copyright 2014, Sybase Inc. - v 7.6 Home / Contact Us / Help / Jobs / Legal / Privacy / Code of Ethics