JTA and Transaction Attributes
Dear reader,
In this blog article I have discussed about JTA (Java Transaction API) and Transaction Attributes.
The Contents are taken from below site but edited for my reading purpose:
http://www.java-tips.org/java-ee-tips/enterprise-java-beans/introduction-to-the-java-transactio.html
A transaction is a series of operations that must be performed atomically. In other words, each operation
in the transaction series must succeed for the entire transaction to be successful. If any operation in the
transaction does not succeed, the entire transaction fails. At that point, any operations which have succeeded
must be "rolled back" so that the end state matches with what was in place when the transaction started.
For example, let's say you want to transfer $50 from a savings account (account number: 12345-1) to a checking
account (account number 12345-2). The steps in this transaction can be stated in "pseudo code" as follows:
BOUNDARY: START TRANSACTION A
SUBTRACT 50 DOLLARS FROM SAVINGS ACCOUNT 12345-1
ADD 50 DOLLARS TO THE CHECKING ACCOUNT 12345-2
BOUNDARY: END TRANSACTION A
To run the transaction, the following code is required:
PREPARE (RUN) TRANSACTION A
IF TRANSACTION A SUCCEEDED
COMMIT TRANSACTION A
ELSE
ROLLBACK TRANSACTION A
Let's assume that there are sufficient funds to subtract $50 from the savings account, so the first part of
the transaction succeeds. However, let's also assume that the second part fails. When the computer attempts
to add 50 dollars to the checking account, it discovers that the checking account is frozen. Because the
second part of the transaction fails, the entire transaction fails. As a result, the first part of the transaction
needs to be rolled back: means $50 needs to be placed back into the savings account 12345-1. This is essential.
Otherwise, each time the computer tries to transfer money from the savings to the checking account, it will
lose the money!
If the entire transaction succeeds, then the entire transaction is committed, and the results are made permanent.
Note that the commit process takes two phases to complete. In the first phase, checks are made to see that the
transaction ran without error. If there were no errors, the results are committed in the second phase. If there
were errors in the first-phase check, the transaction is rolled back. This common transaction strategy is
appropriately called the two-phase commit protocol.
Transactions in the J2EE Environment:
The Java Transaction API(JTA) is part of the J2EE platform. The API gives you the ability to perform
distributed transactions, that is, an application can use the API to perform transactions on more than
one data store in the network at the same time. But to do this efficiently, it helps to have another
component operating in the application server: a J2EE transaction manager. A transaction manager helps
to efficiently schedule and execute the potentially large number of transactions coming in through the
application server.
Many database vendors provide their own transaction managers. However, a particular DBMS's transaction
manager might not work with databases from different vendors. If you want to work with these heterogeneous
databases, for example, if you want to update multiple databases from different vendors, you should consider
using a JTA transaction with a corresponding J2EE transaction manager. The JTA specification states that
"A JTA transaction is controlled by the J2EE transaction manager." Note that the J2EE transaction manager
does have one limitation: the J2EE transaction model is flat. Support for nested transactions is not part
of J2EE. This means that the J2EE transaction manager cannot start a transaction for an instance until the
previous transaction has ended.
Learning the JTA:
There are three separate interfaces that you can use with the JTA to perform transactions, and each uses a
unique approach to handling transactions. The interfaces are:
javax.transaction.UserTransaction: This interface allows you to specify the transaction boundaries,
bypassing a transaction manager.
javax.transaction.TransactionManager. This interface allows you to delegate the boundaries of the
transactions, as well as various transaction operations, to the J2EE transaction manager.
javax.transaction.xa.XAResource. This interface maps to the X/Open CAE Specification (Distributed Transaction
Processing: The XA Specification) standard for using third-party XA-compliant transaction managers to perform
transactions.
Because most J2EE programmers only use the first interface, I am writing for that only.
EJB Transactions: Container and Bean-Managed Transactions, not explaining here.
Container-managed transactions can be used with any type of enterprise bean (session bean, entity bean, or message-
driven bean). With container-managed transactions, the EJB container sets the boundaries of the transaction. This is
typically done by marking one or more methods in the bean as individual transactions. The container sets the
transaction boundary just before the beginning of the method, and sets the end boundary just before the method
exits. However, with container-managed transactions, each method can be only one transaction -- multiple transactions
are not allowed. When deploying a bean, you specify which of the bean's methods are associated with transactions.
You do this by setting the transaction attributes.
The sequence of transaction events differs between container-managed and bean-managed transactions.
Below are the sequence:
Container-managed Transactions:
For EJB applications with container-managed transactions, a basic transaction works in the following way:
1. In the EJB’s deployment descriptor, the Bean Provider or Application Assembler specifies the transaction type
(transaction-type element) for container-managed demarcation (Container).
2. In the EJB’s deployment descriptor, the Bean Provider or Application Assembler specifies the default transaction
attribute (trans-attribute element) for the EJB, which is one of the following settings:
NotSupported, Required, Supports, RequiresNew, Mandatory, or Never.
Detailed description of all these attributes are written in the blog article.
3. However in the EJB’s deployment descriptor, we can set trans-attribute for one or more methods as per
requirement. However this is optional.
4. When a client application invokes a method in the EJB, the EJB container checks the trans-attribute setting in the
deployment descriptor for that method. If no setting is specified for the method, the EJB uses the default
trans-attribute setting for that EJB.
5. The EJB container takes the appropriate action depending on the applicable trans-attribute setting.
For example, if the trans-attribute setting is Required, the EJB container invokes the method within the
existing transaction context or, if the client called without a transaction context, the EJB container
begins a new transaction before executing the method.
In another example, if the trans-attribute setting is Mandatory, the EJB container invokes the method within
the existing transaction context. If the client called without a transaction context, the EJB container throws
the javax.transaction.TransactionRequiredException exception.
Detailed description of all these attributes are written in the blog article.
6. During invocation of the business method, if it is determined that a rollback is required, the business method
calls the EJBContext.setRollbackOnly method, which notifies the EJB container that the transaction is to be
rolled back at the end of the method invocation.
Note: Calling the EJBContext.setRollbackOnly method is allowed only for methods that have a meaningful transaction
context.
7. At the end of the method execution and before the result is sent to the client, the EJB container completes the
transaction, either by committing the transaction or rolling it back (if the EJBContext.setRollbackOnly() was called).
Bean-managed Transactions:
For EJB applications with bean-managed transaction demarcations, a basic transaction works in the following way:
1. In the EJB’s deployment descriptor, the Bean Provider or Application Assembler specifies the transaction type
(transaction-type element) for container-managed demarcation (Bean).
2. The client application uses JNDI to obtain an object reference to the UserTransaction object for the WebLogic
Server domain.
3. The client application begins a transaction using the UserTransaction.begin method, and issues a request to
the EJB through the EJB container. All operations on the EJB execute within the scope of a transaction.
If a call to any of these operations raises an exception (either explicitly or as a result of a communication
failure), the exception can be caught and the transaction can be rolled back using the UserTransaction.rollback
method.
If no exceptions occur, the client application commits the current transaction using the UserTransaction.commit
method. This method ends the transaction and starts the processing of the operation. The transaction is committed
only if all of the participants in the transaction agree to commit.
4. The UserTransaction.commit method causes the EJB container to call the transaction manager to complete the transaction.
5. The transaction manager is responsible for coordinating with the resource managers to update any databases.
Transaction attributes control the scope of a transaction when one enterprise bean method calls another enterprise
bean method. The JTA specification states that an enterprise bean method can be marked with one of six different
transaction attributes in the EJB deployment descriptor. The transaction attribute indicates how the EJB container
should treat the method called by the client enterprise bean when transactions are involved.
Transaction attributes appear in the EJB deployment descriptor as follows:
<ejb-jar>
...
<enterprise-beans>
...
</enterprise-beans>
<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>BankBean</ejb-name>
<method-intf>Remote</method-intf>
<method-name>transferMoney</method-name>
<method-params>
<method-param>java.lang.String</method-param>
<method-param>java.lang.double</method-param>
</method-params>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
</assembly-descriptor>
</ejb-jar>
Here is what the specification says about each of the six transaction attributes:
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. Most container-managed
transactions use Required.
RequiresNew - If the client is running within a transaction and invokes the enterprise bean's method,
the container suspends the client's transaction, starts a new transaction, delegates the call to the
method, and finally 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.
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.
There are two ways to Roll-back a container-managed transaction. If a system exception is thrown, the container
automatically rolls back the transaction. You can also roll back a transaction by invoking the setRollbackOnly()
ethod of the EJBContext interface. This instructs the container to roll back the transaction. If an enterprise bean
throws an application exception, the rollback is not automatic, but the rollback can be initiated by a call to
setRollbackOnly(). Note that you cannot invoke some JTA methods while using container-managed transactions.
That's because these methods are reserved for use with bean-managed transactions. These methods are:
Any resource-specific functions that conflict with the transactional semantics, such as the commit(),
setAutoCommit(), and rollback() methods of java.sql.Connection.
The getUserTransaction() method of javax.ejb.EJBContext.
Any method of javax.transaction.UserTransaction
In a bean-managed transaction, the code explicitly marks the boundaries of the transaction.
When you code a bean-managed transaction you typically can use either JDBC or JTA transactions.
A JDBC transaction is controlled by the transaction manager of the database management system, and
not by the J2EE transaction manager. To perform a JDBC transaction, use the commit() and rollback() methods of the
java.sql.Connection interface.
The beginning of a transaction is generally assumed with the first SQL statement that follows the most recent commit(),
rollback(), or connect() statement. For JTA transactions, you can invoke the begin(), commit(), and rollback() methods
of the javax.transaction.UserTransaction interface. The begin() and commit() methods mark the transaction boundaries.
If the transaction operations fail, an exception handler typically invokes the rollback() method, and throws an
EJBException. The following code shows how to use the JTA javax.transaction.UserTransaction interface to perform a
bean-managed transaction:
//All class imports
import javax.naming.*;
import javax.transaction.UserTransaction;
import javax.transaction.SystemException;
import javax.transaction.HeuristicMixedException
import javax.transaction.HeuristicRollbackException
import javax.transaction.NotSupportedException
import javax.transaction.RollbackException
import javax.transaction.IllegalStateException
import javax.transaction.SecurityException
import java.sql.*;
import java.util.*;
//Getting UserTransaction
Context ctx = null;
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
//Substitute the correct hostname, port number. Also user name, and password for your environment:
env.put(Context.PROVIDER_URL, "t3://localhost:7001");
env.put(Context.SECURITY_PRINCIPAL, "Fred");
env.put(Context.SECURITY_CREDENTIALS, "secret");
ctx = new InitialContext(env);
UserTransaction tx = (UserTransaction) ctx.lookup("java:comp/env/jdbc/customer");
//UserTransaction ut = context.getUserTransaction();
try {
ut.begin();
//Do whatever transaction functionality is necessary
ut.commit();
}
catch (Exception ex) {
try {
ut.rollback();
}
catch (SystemException syex) {
throw new EJBException("Rollback failed: " + syex.getMessage());
}
throw new EJBException ("Transaction failed: " + ex.getMessage());
}
//Or you can get a JDBC data source connection:
Context context=new InitialContext();
//Set context attributes
DataSource ds=(DataSource)context.lookup("java:comp/env/jdbc/customer");
Connection connection=ds.getConnection();
//Now use normal JDBC operations.
The code to perform a JDBC bean-managed transaction is similar. Note, however, that the code turns off the
auto-commit on the database connection. This way, the database treats all subsequent operations as a single
transaction (until the code calls the commit() method) .
try {
Connection con = makeDatabaseConnection(); //Using JDBC
con.setAutoCommit(false);
// Do whatever database transaction functionality
// is necessary
con.commit();
}
catch (Exception ex) {
try {
con.rollback();
} catch (SQLException sqx) {
throw new EJBException("Rollback failed: " +
sqx.getMessage());
}
}
finally {
releaseDatabaseConnection();
}
Here are a few rules stated by the JTA specification:
In a stateless session bean with bean-managed transactions, a business method must commit or roll back a
transaction before returning.
However, a stateful session bean does not have this restriction. In a stateful session bean with a JTA
transaction, the association between the bean instance and the transaction is retained across multiple
client calls. Even if each business method called by the client opens and closes the database connection,
the association is retained until the instance completes the transaction.
In a stateful session bean with a JDBC transaction, the JDBC connection retains the association between
the bean instance and the transaction across multiple calls. If the connection is closed, the association
is not retained.
There is one method limitation with JTA bean-managed transactions: do not invoke the getRollbackOnly() and
setRollbackOnly() methods of the EJBContext interface (these methods should be used only in container-managed
transactions). For bean-managed transactions, invoke the getStatus() and rollback() methods of the UserTransaction
interface instead. And, be sure not to invoke any resource-specific functions that conflict with the transactional
semantics.
------------------------------END------------------------------------
Tuesday, March 20, 2012
JTA and Transaction Attributes
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment