In the early days of computing, there was no need for distributed transactions. As number of applications increased, synchronization of the data become an important issue. Companies paid a lot to maintain synchronized systems in terms of data flow. As a result, the 2 phase commit protocol referred to as XA(eXtended Architecture) arose. This protocol provides ACID-like properties for global transaction processing. Throughout this article, I will try to explain details of XA transactions and use of XA Transactions in Spring framework.
2 phase commit protocol is an atomic commitment protocol for distributed systems. This protocol as its name implies consists of two phases. The first one is commit-request phase in which transaction manager coordinates all of the transaction resources to commit or abort. In the commit-phase, transaction manager decides to finalize operation by committing or aborting according to the votes of the each transaction resource. We will next move on to implementation details of 2PC protocol.
XA transactions need a global transaction id and local transaction id(xid) for each XA resource. Each XA Resource is enlisted to XA Manager by start(xid) method. This method tells that XA Resource is being involved in the transaction(be ready for operations). After that, the first phase of the 2PC protocol is realized by calling prepare(xid) method. This method requests OK or ABORT vote from XA Resource. After receiving vote from each of XA Resource, XA Manager decides to execute a commit(xid) operation if all XA Resources send OK or decides to execute a rollback(xid) if an XA Resource sends ABORT. Finally, the end(xid) method is called for each of XA Resource telling that the transaction is completed. Look at the figure to understand better. As we build a background in XA transaction implementation, we will next go deeper and see types of failures and possible solutions.
Failures can occur at any time due to network loss, machine down and some administrator mistake. In XA transaction, we will categorize these failures according to the phases that they occur. The first failure phase is before protocol is started. This is a simple failure that system does need not to rollback or any kind of operation. We just do not do the operation for that particular moment. Second type of failure can occur at prepare(commit-request) phase which can be easily handled by rollbacks using timeout policies. Last but not the least is commit phase failures which can occur due to incomplete rollbacks and any problem in chain. In all of these above situation, transaction manager tries to recover the problem. We will next see how transaction manager tries to overcome failures.
For recovery, transaction manager calls recover method of each XA resource. XA Resources trace the logs and tries to rebuild its latest condition. Transaction Manager calls necessary rollback operations and mission is accomplished. This process can seem to be happy path but there are a lot of exceptional situations where logs are problematic like being corrupted. In these kinds of situations, transaction manager follows some heuristics to solve the problem. Moreover, the recovery process depends on the write-ahead logs where you write operation logs before applying. For performance issues these logs are written in their own format(not using any serialization) and system should better batch them if possible. We next go to fun part which is XA transaction support by Spring framework.
Spring framework provides extensive environment to develop web and stand alone applications. Like other utilities it provides, XA transactions are also supported by Spring. However, this support is not a native implementation and requires hibernate, web container or a framework that provides XA Transaction Management. Spring has JtaTransactionManager that provides transaction management utilities and hides the details. By this way, we can have transaction management for multiple DataSources which are updated simultaneously. When it comes to use XA Transaction Management, hibernate and web containers support for XA transactions are well documented, do not need to be mentioned. However, working with a framework that provides XA transactions can be confusing.
JTA Implementors: Basically there are 3 popular JTA implementor’s in the Java worls.
- Atomikos Transaction Essentials
- Bitronix JTA
JBossTS, formerly known as Arjuna Transaction Service, comes with a very robust implementation, which supports both JTA and JTS API. JBossTS comes with a recovery service, which could be run as a separate process from your application processes. Unfortunately, it doesn’t support out-of-the box integration with Spring, but it is easy to integrate as we will see in our exercise. Also there is no support for JMS resources, only database resources are supported.
Atomikos Transaction Essentials
Atomikos’s JTA implementation has been open sourced very recently. The documentation and literature on the internet shows that it is a production quality implementation, which also supports recovery and some exotic features beyond the JTA API. Atomikos provides out of the box Spring integration along with some nice examples. Atomikos supports both database and JMS resources. It also provides support for pooled connections for both database and JMS resources.
Bitronix’s JTA implementation is fairly new and is still in beta. It also claims to support transaction recovery as good as or even better than some of the commercial products. Bitronix provides support for both database and JMS resources. Bitronix also provides connection pooling and session pooling out of the box.
Examples: On the way soon ….