Tuesday, September 4, 2012

JTA Internals - Part 1

Transaction management is one of the most important part of design of an application which requires adherence to ACID properties.

Java EE provides JTA specification to manage distributed transactions. However there are many popular framworks  like Spring framework which provide integration to JTA as well as  old school JDBC (native database transactions through the JDBC Connection API -  more commonly known as resource local transaction). On the top of it if you are using an ORM (like Hibernate) then there is another layer on top of that. Couple that with concepts of transactional second level caches in ORM's like Hibernate in JTA environment. So just knowing about the ACID properties of transaction is not enough to understand the infrastructure. Also as always if you need to debug any transaction related issue you need to have  knowledge of what goes on behind the scenes.

For those who are not satisfied with just using an API but want to uncover the internals I will be writing up a bit of detailed information in the coming weeks. This is the first part of the series.

JTA (Java Transaction API) is a part of Java EE specification and is defined as
standard Java interfaces between a transaction manager and the parties involved in a distributed transaction system: the resource manager, the application server, and the transactional applications.
Let's see each of the parties here in a bit more details. But before that it would be really good to explain a bit about some key interfaces supplied by JTA (there are only very few interfaces to name).


This is the interface used by your application code to manage the transaction boundaries and commit and rollback. In application server environment, the implementation of this interface is bound usually to jndi and the code can use lookup or dependency injection to get hold of this.
UserTransaction ut = getUserTransaction();
} catch (Exception e) {

This is the interface used by the application server code which provides the infrastructure related to transaction management. Your application can be configured to use the application server transaction facility using declarative approach  -  meaning you tell your application server through configuration that your application code requires transactions at such and such place. To begin and end the transaction, the application server uses code which is similar to the above but this code is hidden in application server code managing the transaction infrastructure so your classes don't have to write this.
Usually the implementation for UserTransaction and TransactionManager Interfaces are done in the same implementation class as there are just few methods extra in TransactionManager interface (though this may vary from implementations)
Also this implementaion is bound to jndi from where it is looked up by the application server.


This is the interface representing the transaction associated with a current thread.
It is crucial to understand a bit of details of how this is used although you wont be directly using this interface in your code. Also it will help you in understanding what happens under the covers when your application uses other framework layers such as Spring and Hibernate.

So in either case ( programmatic or declarative transaction management), when a transaction begins ( either by your application code calling UserTransaction begin method or TransactionManager begin method is called by application server code), a Transaction object is created and bound to the current thread using Threadlocal variable approach. If there is an active Transaction object bound to the current thread then a transaction is said to be in progress. Any transaction aware code can check the existence of this transaction to see if there is a  transaction in progress. For e.g., when a connection is requested from a transaction aware implementation of DataSource , it checks the existence of a transaction and enlists the resource in transaction using Transaction interface enlist method.

This check is also essential for many operations in transaction and more specifically when deciding for transaction propagation "required". For required propagation, if there is a transaction already in progress in the current thread then no new transaction is created.

No comments:

Post a Comment