Previous Contents Index Next |
Sun Java System Application Server Standard and Enterprise Edition 7 2004Q2 Administration Guide

> ## Chapter 8
> Using Transaction Services

> Transactions are an integral part of business. A typical business transaction involves transfer of assets between two or more involved parties. Accurate records are usually stored in one or more databases. Because this information is critical for business operations, it must be valid, current, and reliable. Transaction processing can be difficult to a novice programmer. The J2EE platform provides several abstractions that simplify development of dependable transaction processing applications. In this chapter, we will discuss J2EE transactions and transaction support in Sun Java System Application Server.

> This chapter discusses Java Transactions in general, and the transaction support incorporated into Application Server in specific.

> This chapter includes the following topics:

> - What Is a Transaction?
> - Transactions in J2EE
> - Transactional Resource Managers
> - Local and Distributed Transactions
> - Container-Managed Transactions
> - Bean-Managed Transactions
> - Transaction Service Administration

> ##

> What Is a Transaction?

> To emulate a business transaction, a program may need to perform several steps. A financial program, for example, might transfer funds from a checking account to a savings account, by performing the steps listed in the following pseudocode:

> begin transaction

> debit checking account

> credit savings account

> update history log

> commit transaction

> In the preceding pseudocode, the begin and commit statements mark boundaries of the transaction. To complete this transaction, all the three steps complete must complete successfully. If all three steps don’t complete successfully, data integrity could be compromised.

> This guarantee is described as atomicity. A transaction can end in two ways: with a commit or a rollback. When a transaction commits, the modifications made by statements within the transaction boundaries are saved and made permanent. The changes are durable, that is they will survive future system failures. If any statement within a transaction fails, the transaction rolls back, undoing the effects of all statements executed so far in the transaction. In the pseudocode, for example, if a disk drive crashed during the credit step, the transaction would roll back and undo the data modifications made by the debit statement.

> Even if a transaction fails, data integrity would be intact because the transaction accounts still balance. This aspect of transactional behavior is known as transactional consistency.

> The transaction service also provides isolation, which means that phases in a transaction cannot be observed by other applications and threads, until the transaction is committed or rolled back. Once a transaction is committed, the committed transaction can be safely observed by applications and threads.

> ##

> Transactions in J2EE

> Transaction processing in J2EE involves the following five participants: Transaction Manager, Application Server, Resource Manager(s), Resource Adapter(s) and the User Application. Each of these entities contribute to reliable transaction processing, by implementing different APIs and functionalities, discussed below:

> - Transaction Manager provides the services and management function required to support transaction demarcation, transactional resource management, synchronization, and transaction context propagation.
> - The Application server provides the infrastructure required to support the application run-time environment which includes transaction state management.
> - Resource Manager (through a resource adapter) provides the application access to resources. The resource manager participates in distributed transactions by implementing a transaction resource interface used by the transaction manager to communicate transaction association, transaction completion and recovery work. An example of such a resource manager is a relational database server.
> - A Resource Adapter is a system level software library that is used by the application server or client to connect to a Resource Manager. A Resource Adapter is typically specific to Resource Manager. It is available as a library and is used within the address space of the client using it. An example of such a resource adapter is the JDBC driver.
> - A transactional User Application developed to operate in a J2EE application server environment, looks up transactional data sources, and optionally, the transaction manager, using JNDI. May use declarative transaction attribute settings for EJBs or explicit programmatic transaction demarcation.

> The term Resource Manager is often used interchangeably with Resource Adapter, as there is a close tie between the two entities.

> ##

> Transactional Resource Managers

> The following transactional resource managers are supported in J2EE transactions.

> - Databases
> - JMS Providers
> - J2EE Connectors

> ### Databases

> Databases are the most commonly encountered transactional resource managers in J2EE applications. JDBC is the API is used by J2EE components to access databases. Database resources are configured as JDBC resources. JDBC resources are managed by a resource managers, or JDBC Drivers. A JDBC driver may provide support for Local transactions or Global transactions, and in some cases for both local and global transactions.

> Application Server supports usage of JDBC and Transactions from various J2EE components. For more details on how JDBC resources are registered and configured, see About JDBC Resources. The Application Server is responsible for providing transaction continuity (that is, initiating a transaction and accessing the database from multiple application components). For example, a servlet may start a transaction, access a database, invoke an enterprise bean that accesses the same database as part of the same transaction, and finally, commit the transaction.

> ### JMS Providers

> JMS stands for Java Message Service. A JMS Provider is the J2EE term for the Message Broker Service. The JMS API provides reliable and transactional exchange of messages between applications. Support of transactional JMS data sources is a required capability in J2EE. JMS resources and JDBC resources can participate in the same transaction.

> Application Server comes integrated with Sun Java System Message Queue, a fully capable JMS provider and the corresponding transactional resource manager. In this manner, Application Server enables transactional JMS access from servlets, JSP pages and enterprise beans. It is also possible to use third party JMS Providers with Application Server. For more details, see Chapter 10, "Using the JMS Service."

> ### J2EE Connectors

> Application Server supports resource adapters that use XATransaction mode as transaction resource managers. The platform must enable transactional access to the resource adapter from servlets, JSP pages, and enterprise beans. It is possible to access the resource adapter from multiple application components within a single transaction. For example, a servlet may wish to start a transaction, access the resource adapter, invoke an enterprise bean that also accesses the resource adapter as part of the same transaction, and finally, commit the transaction.

> ##

> Local and Distributed Transactions

> A transaction that involves only one resource can be completed using local transactions. A local transaction also requires that all participating application components execute within one process. Transactions that involve more than one resource, or multiple participant processes become distributed or global transactions. Local transaction optimization uses the resource manager specific optimization and it is transparent to the J2EE application.

> The type of transaction is largely determined by the interfaces implemented of the involved resource managers. For example, a JDBC Data Source that implements javax.sql.DataSource interface can participate in Local transactions. A Data Source that implements javax.sql.XADataSource is capable of taking part in global transactions. Some JDBC resources implement both the interfaces, and when such a JDBC resource is registered with Application Server, it may be necessary to provide additional configuration information in the Application Server configuration to indicate the preferred capability for that resource.

> Local transactions are simpler and naturally more efficient than global transactions. Local transactions are inadequate when the data that needs to be transformed is spread across multiple data sources. Sometimes, it is not possible to predict how many data sources would need to be enlisted in a transaction. So global transactions are encountered quite frequently in the real world. Some performance enhancing optimizations are possible with global transactions.

> J2EE supports transactional applications comprising any combination of servlets or JSPs accessing multiple enterprise beans within a transaction. Each component may acquire one or more connections to access one or more transactional resource managers. In the following figure, the call tree starts from a servlet or JSP page accessing multiple enterprise beans, which in turn may access other enterprise beans. The components access resource managers via connections.

> Figure 8-1 J2EE Components Accessing Resources in a Transaction

> For example, an application may require that all the components in the above figure access resources as part of a single transaction. The application server provider must provide the transaction capabilities to support such a scenario.

> J2EE transactional management supports flat transactions. A flat transaction cannot have any child (nested) transactions.

> Transaction Recovery is an important aspect of distributed transactions. When a resource becomes unreachable during critical points, or if there are other unrecoverable errors, the status of the distributed transaction can be in question. Automatic and manual recovery of stranded/incomplete transactions is an important feature in Sun Java System Application Server. You can enable automatic transaction recovery by using the Administration interface. For more information on how to control transaction recovery, see Transaction Service Administration.

> Connections—used as a synonym here for resources—can be marked as either shareable or non-shareable. A J2EE application component that intends to use a connection in an un-shareable way must provide deployment information to that effect, to prevent the connection from being shared by the container. Examples of when this may be needed include situations with changed security attributes, isolation levels, character settings, and localization configuration.

> Containers must not attempt to share connections that are marked un-shareable. If a connection is not marked as unshareable, it must be transparent to the application whether the connection is actually shared or not.

> J2EE application components may use the optional deployment descriptor element res-sharing-scope to indicate whether a connection to a resource manager is shareable or unshareable. Containers should assume connections to be shareable if no deployment hint is provided. J2EE application components may cache connection objects and reuse them across multiple transactions. Containers that provide connection sharing should transparently switch such cached connection objects (at dispatch time) to point to an appropriate shared connection with the correct transaction scope.

> When designing an enterprise bean application, the developer must determine how the boundaries are specified.

> ##

> Container-Managed Transactions

> In an enterprise bean with container-managed transactions, the EJB container sets the boundaries of the transactions. You can use container-managed transactions with any type of enterprise bean: session, entity, or message-driven. Container-managed transactions simplify development because the enterprise bean code does not explicitly mark the transaction's boundaries. The code does not include statements that begin and end the transaction.

> Typically, the container begins a transaction immediately before an enterprise bean method starts. It commits the transaction just before the method exits. Each method can be associated with a single transaction. Nested or multiple transactions are not allowed within a method.

> Container-managed transactions do not require all methods to be associated with transactions. When deploying a bean, you specify which of the bean's methods are associated with transactions by setting the transaction attributes.

> This section covers the following topics:

> - Transaction Attributes
> - Setting Transaction Attributes
> - Rolling Back a Container-Managed Transaction
> - Synchronizing a Session Bean’s Instance Variables
> - Methods Not Allowed in Container-Managed Transactions

> ### Transaction Attributes

> A transaction attribute controls the scope of a transaction. The following figure illustrates why controlling the scope is important. In the diagram, method-A begins a transaction and then invokes method-B of Bean-2. When method-B executes, does it run within the scope of the transaction started by method-A or does it execute with a new transaction? The answer depends on the transaction attribute of method-B.

> Figure 8-2 Transaction Attributes

> A transaction attribute may have one of the following values:

> - Required
> - RequiresNew
> - Mandatory
> - NotSupported
> - Supports
> - Never

> #### Required

> If the client is running within a transaction and invokes the enterprise bean's method, the method executes within the client's transaction. If the client is not associated with a transaction, the container starts a new transaction before running the method.

> The Required attribute will work for most transactions. Therefore, you may want to use it as a default, at least in the early phases of development. Because transaction attributes are declarative, you can easily change them at a later time.

> #### RequiresNew

> If the client is running within a transaction and invokes the enterprise bean's method, the container takes the following steps:

> - Suspends the client's transaction
> - Starts a new transaction
> - Delegates the call to the method
> - Resumes the client's transaction after the method completes

> If the client is not associated with a transaction, the container starts a new transaction before running the method.

> You should use the RequiresNew attribute when you want to ensure that the method always runs within a new transaction.

> #### Mandatory

> If the client is running within a transaction and invokes the enterprise bean's method, the method executes within the client's transaction. If the client is not associated with a transaction, the container throws the TransactionRequiredException.

> Use the Mandatory attribute if the enterprise bean's method must use the transaction of the client.

> #### NotSupported

> If the client is running within a transaction and invokes the enterprise bean's method, the container suspends the client's transaction before invoking the method. After the method has completed, the container resumes the client's transaction.

> If the client is not associated with a transaction, the container does not start a new transaction before running the method.

> Use the NotSupported attribute for methods that don't need transactions. Because transactions involve overhead, this attribute may improve performance.

> #### Supports

> If the client is running within a transaction and invokes the enterprise bean's method, the method executes within the client's transaction. If the client is not associated with a transaction, the container does not start a new transaction before running the method.

> Because the transactional behavior of the method may vary, you should use the Supports attribute with caution.

> #### Never

> If the client is running within a transaction and invokes the enterprise bean’s method, the container throws a RemoteException. If the client is not associated with a transaction, the container does not start a new transaction before running the method.

> #### Attribute Summary

> The following table summarizes the effects of the transaction attributes. Both the T1 and T2 transactions are controlled by the container. A T1 transaction is associated with the client that calls a method in the enterprise bean. In most cases, the client is another enterprise bean. A T2 transaction is started by the container just before the method executes.

> In the last column of, the term “None” indicates that the business method does not execute within a transaction controlled by the container. However, the database calls in such a business method might be controlled by the transaction manager of the DBMS.

> Table 8-1 Transaction Attributes

> Transaction Attribute | Client’s Transaction | Business Method’s Transaction
> Required | None | T2
> T1 | T1
> RequiresNew | None | T2
> T1 | T2
> Mandatory | None | error
> T1 | T1
> NotSupported | None | None
> T1 | None
> Supports | None T1 | None T1

> ### Setting Transaction Attributes

> Because transaction attributes are stored in the deployment descriptor, they can be changed during several phases of J2EE application development: enterprise bean creation, application assembly, and deployment. However it is the responsibility of a developer to specify the attributes when creating the bean. The attributes should be modified only by an application developer who is assembling components into larger applications. The individual who deploys the J2EE application is not responsible for specifying the transaction attributes.

> You can specify the transaction attributes for the entire enterprise bean or for individual methods. If you’ve specified one attribute for a method and another for the bean, the attribute for the method takes precedence. When specifying attributes for individual methods, the requirements differ with the type of bean. Session beans need the attributes defined for business methods, but do not allow them for the create methods. Entity beans require transaction attributes for the business, create, remove, and finder methods. Message-driven beans require transaction attributes (either Required or NotSupported) for the onMessage method.

> ### Rolling Back a Container-Managed Transaction

> There are two ways to roll back a container-managed transaction. First, if a system exception is thrown, the container will automatically roll back the transaction. Second, by invoking the setRollbackOnly method of the EJBContext interface, the bean method instructs the container to roll back the transaction. If the bean throws an application exception, the rollback is not automatic, but may be initiated by a call to setRollbackOnly.

> In the following example, the transferToSaving method of the BankEJB example illustrates the setRollbackOnly method. If a negative checking balance occurs, transferToSaving invokes setRollBackOnly and throws an application exception (InsufficientBalanceException). The updateChecking and updateSaving methods update database tables. If the updates fail, these methods throw a SQLException and the transferToSaving method throws an EJBException. Because the EJBException is a system exception, it causes the container to automatically roll back the transaction. Here is the code for the transferToSaving method:

> public void transferToSaving(double amount) throws
> InsufficientBalanceException {
> checkingBalance -= amount;
> savingBalance += amount;

> if (checkingBalance < 0.00) {
> context.setRollbackOnly();

> throw new InsufficientBalanceException();
> }
> try {
> updateChecking(checkingBalance);

> updateSaving(savingBalance);
> } catch (SQLException ex) {
> throw new EJBException
> ("Transaction failed due to SQLException: "
> + ex.getMessage());
> }
> }

> When the container rolls back a transaction, it always undoes the changes to data made by SQL calls within the transaction. However, only in entity beans will the container undo changes made to instance variables. (It does so by automatically invoking the entity bean’s ejbLoad method, which loads the instance variables from the database.) When a rollback occurs, a session bean must explicitly reset any instance variables changed within the transaction. The easiest way to reset a session bean’s instance variables is by implementing the SessionSynchronization interface.

> You can also roll back a transaction by passing the transaction ID through the command line interface. For more details, please see Administering Transactions Using the Command-Line Interface.

> ### Synchronizing a Session Bean’s Instance Variables

> The SessionSynchronization interface, which is optional, allows you to synchronize the instance variables with their corresponding values in the database. The container invokes the SessionSynchronization methods—afterBegin, beforeCompletion, and afterCompletion—at each of the main stages of a transaction.

> The afterBegin method informs the instance that a new transaction has begun. The container invokes afterBegin before it invokes the first business method within a transaction. The afterBegin method is a good place to load the instance variables from the database. The BankBean class, for example, loads the checkingBalance and savingBalance variables in the afterBegin method:

> public void afterBegin() {
> System.out.println("afterBegin()");
> try {
> checkingBalance = selectChecking();
> savingBalance = selectSaving();
> } catch (SQLException ex) {
> throw new EJBException("afterBegin Exception: " +
> ex.getMessage());
> }
> }

> The container invokes the beforeCompletion method after the business method has finished, but just before the transaction commits. The beforeCompletion method is the last opportunity for the session bean to roll back the transaction (by calling setRollbackOnly). If it hasn’t already updated the database with the values of the instance variables, the session bean may do so in the beforeCompletion method.

> The afterCompletion method indicates that the transaction has completed. It has a single boolean parameter, whose value is true if the transaction was committed and false if it was rolled back. If a rollback occurred, the session bean can refresh its instance variables from the database in the afterCompletion method:

> public void afterCompletion(boolean committed) {
> System.out.println("afterCompletion: " + committed);
> if (committed == false) {
> try {
> checkingBalance = selectChecking();
> savingBalance = selectSaving();
> } catch (SQLException ex) {
> throw new EJBException("afterCompletion SQLException:
> " + ex.getMessage());
> }
> }
> }

> ### Methods Not Allowed in Container-Managed Transactions

> You should not invoke any method that might interfere with the transaction boundaries set by the container. The list of prohibited methods follows:

> - The commit, setAutoCommit, and rollback methods of java.sql.Connection
> - The getUserTransaction method of javax.ejb.EJBContext
> - Any method of javax.transaction.UserTransaction

> You may, however, use these methods to set boundaries in bean-managed transactions.

> ##

> Bean-Managed Transactions

> In a bean-managed transaction, the code in the session or message-driven bean explicitly marks the boundaries of the transaction. An entity bean cannot have bean-managed transactions; it must use container-managed transactions instead. Although beans with container-managed transactions require less coding, they have one limitation: When a method is executing, it can be associated with either a single transaction or no transaction at all. If this limitation will make coding your bean difficult, you should consider using bean-managed transactions.

> The following pseudocode illustrates the kind of fine-grained control you can obtain with bean-managed transactions. By checking various conditions, the pseudocode decides whether to start or stop different transactions within the business method.

> begin transaction
> ...
> update table-a
> ...
> if (condition-x)
> commit transaction
> else if (condition-y)
> update table-b
> commit transaction
> else
> rollback transaction
> begin transaction
> update table-c
> commit transaction

> ##

> Transaction Service Administration

> You can administer transaction by using the Administration interface, or by using the Command Line Interface.

> This section covers the following topics:

> - Administering Transactions Using the Administration Interface
> - Administering Transactions Using the Command-Line Interface

> ### Administering Transactions Using the Administration Interface

> Using the Administration interface, you can enable monitoring, set log levels, and specify advanced options for your transactions.

> You can control instance-wide transaction service attributes, such as recovery policy and time-outs. The properties and configuration that you specify here are stored in the server.xml file.

> To configure transaction service options, perform the following tasks:

> 1. In the left pane of the Administration interface, open the Application Server instance tree, whose transaction configuration you want to modify.
> 2. Select Transaction Service from the list of J2EE services that are displayed.
> 3. To enable monitoring for your transactions, mark the Monitoring Enabled checkbox. The following table lists the features of Java Transaction services that can be monitored:

> Table 8-2 Monitorable Attributes of Java Transaction Services

> Property | Type | Description
> transactionsCompleted | int | Number of transactions completed since monitoring is enabled
> transactionsRolledBack | int | Number of transactions rolled back since monitoring is enabled
> transactionsRecovered | int | Number of transactions recovered since monitoring is enabled
> transactionsInFlight | int | Number of transactions presently being processed
> timeStamp | long | In milliseconds, recording the time at which the statistic was produced. This will be whatever that is reported by System.getCurrentTimeInMillis()

> 4. Select the log level you want to set for your transactions, from the Log Level drop-down list. For a more information on log levels and how they are incorporated, see Chapter 5, "Using Logging."
> 5. Mark the checkbox against Recover on Restart to automatically recover failed transactions at server restart. When a resource becomes unreachable during critical points in the transaction Commit protocol, transactions may not complete and remain in transaction log file. If this check box has been marked, the server attempts to recover stranded transaction upon server restart. If the involved resources remain unreachable, this may delay server restart. This checkbox is not marked by default.
> 6. For enterprise beans with container-managed transactions, you can control the transaction timeout interval by setting the value of the Transaction Timeout (secs) property.

> If the value of this property is set to 0, your transaction does not time out.

> In the Transaction Timeout (secs) field, specify the transaction timeout interval. If a transaction is not completed within the specified time, the transaction will be rolled back. If the value set for this attribute is 0, the transaction does not time out.

> 7. In the Transaction Log Location field, specify the absolute path to the directory in which you want to store your log files. You need to restart your server for the new transaction log directory to be effective.
> 8. From the Heuristic Decision drop-down box, select the heuristic decision that you want to apply to your transactions. Select Commit or Rollback from the options indicated, to specify how the Application Server should determine the outcome of an in-doubt transaction during recovery, if the outcome cannot be determined unambiguously. If the Heuristic Decision is set to Rollback, it rolls back the transaction. In some cases, it may be acceptable to commit such a transaction.
> 9. In the Keypoint Interval (transactions) field, specify the number of transactions between keypoint operations in the log. Keypoint operations reduce the size of the transaction log file by removing entries for completed transactions and compressing the file. A larger value for this attribute results in a larger transaction log file, but fewer keypoint operations mean a potentially better performance. A smaller value (for example, 100) results in smaller log files, but slightly reduced performance due to the greater frequency of keypoint operations.

> ### Administering Transactions Using the Command-Line Interface

> You can administer and monitor database transactions using the Command Line Interface (CLI), as explained in the following sections:

> - Listing In-Flight Transactions
> - Managing Transactions
> - Freezing the Transaction Service
> - Monitoring Transactions

> These sections explain how to use the Command Line Interface to manage and monitor transactions.

> #### Listing In-Flight Transactions

> The following command should be used to get the in-flight transaction data (assuming that you are in multimode and have already set the user name and password):

> - asadmin> get --monitor <instanceName>.transaction-service.inflight-tx

> The multi-line output will look like this:-

> Transaction Id State Elapsed Time (ms)

> txnid1 Prepared 20

> txnid2 Active 100

> txnid3 Active 120

> ... ... ...

> #### Managing Transactions

> In the example given in Listing In-Flight Transactions, let us assume that you want to rollback transactions with the transaction Ids: txn-ids, txnid2, and txnid3. A sample command to rollback chosen transactions, would look like the following example:

> asadmin> set --monitor <instanceName>.transaction-service.rollback-list=txnid2,txnid3

> #### Freezing the Transaction Service

> To freeze the transaction service, run the following command:

> asadmin> set --monitor <instanceName>.transaction-service.freeze=true

> When the transaction service is frozen the transaction manager in the application server, will suspend all in-flight transactions. Freezing is not recommended on a production deployment system.

> To unfreeze the transaction service, run the following command:

> asadmin> set --monitor <instanceName>.transaction-service.freeze=false

> When the transaction service is set in motion again, the system continues where it left off. If a live system was left in frozen state for too long, some database connections may time out, resulting in rolled back transactions.

> #### Monitoring Transactions

> To get the monitoring data of transactions, including in-flight transaction data, run the following command:

> asadmin> get --monitor <instanceName>.transaction-service.*

> If there are no active transactions when you run this command, you will get the following output:

> total-tx-completed = 5

> total-tx-rolledback = 2

> total-tx-inflight = 0

> isFrozen = false

> tx-inflight = No active transactions found.

> If there are active transactions, when you run this command, you will get the following output:

> total-tx-completed = 5

> total-tx-rolledback = 2

> total-tx-inflight = 2

> isFrozen = false

> tx-inflight =

> Transaction Id State Elapsed Time(ms)

> txnid1 Prepared 500

> txnid2 Active 360

> Previous Contents Index Next

> Copyright 2004 Sun Microsystems, Inc. All rights reserved.