Transaction Management is one of the fundamental topics of how an application manages data and below is an overview of how transaction management is handled using Java as the programming language.
What is transaction management?
In simple terms, a transaction is a group of tasks that must be processed together. Transaction is indivisible and must be executed as a whole; otherwise the data integrity is violated. For example, a banking money transfer request involves deducting money from the source account, transfer the money into an interim escrow account, and finally transfer the money to the destination account. And all these “tasks” need to happen together and otherwise, the money is “lost” in transaction. And data integrity is violated.
Transaction Management in Java EE world:
Now, let’s talk about tasks of a transaction in Java EE world. In the Java EE world, we are referring to group of SQL statements or processing of JMS messages.
Both Spring and EJB have provided comprehensive support for executing transactions in Java. The usage of spring is simpler as compared to the usage of EJB, while EJB is definitely the official Java EE standard. Both technologies have their own strong points and the usage can be sometimes interchangeable.
JDBC is definitely the first database API option for any Java developer. The transaction management using JDBC can be illustrated in simple and and boiler-plate terms:
Set auto-commit to false
Execute the sequence of JDBC SQL statements
Manipulate the data using the result set
Do commit OR rollback back for any exceptions
Transaction management “ways” using various Java APIs:
- The transaction is clearly controlled in the JDBC based program and no wonder it is called “Programmatic Transaction Management”. As the business logic grows complex, the code grows complex and, managing transactions in the program becomes difficult.
- Spring’s transaction management was introduced to reserve the flexibility of manual control of the transactions as compared to automated part of programmatic transaction management. Spring’s TransactionTemplate or PlatformTransactionManager API can be used for this purpose.
- EJB provides Bean Managed Transaction (BMT) to handle complex transaction commit and rollbacks to avoid major pitfalls. UserTransaction API is invented for the similar purpose of PlatformTransactionManager API in Spring.
Comparison and Analysis of these “ways”:
Since most of the time the transaction management logic is straightforward, most of the users prefer declarative transaction management. With the declarative model, developers usually don’t have to write any code related to the transaction itself. All we need are some annotations and configurations. It is easy to use declarative transaction management in Spring by just put @Transactional and @EnableTransactionManagement into the code. Under the hood, Spring implements it via APO proxy. The caller of one transaction actually invokes an AOP proxy where the transaction is created on the way in and committed or rolled back on the way out. If everything goes smoothly, the transaction will be successfully committed. In the default configuration, Spring will mark a transaction for rollback in the case of Runtime Exceptions. And of course this can be overridden by doing configuration changes to make Spring rollback the transactions on any exceptions. Similar to the Spring’s declarative transaction management, EJB provides the better worry-free container-managed transaction (CMT) demarcation. With CMT, the EJBs automatically become transactional by default. The application server is in charge of commit and rollback. Also in EJB world, one can use TransactionAttribute annotation to specify the TransactionAttributeType.
Programmatic transaction management is better only when a small number of tasks are involved to complete a transaction. On the other hand, if your applications has lots of transaction operations (tasks) or involve multiple resources, considering declarative transaction management is worthwhile.
A distributed transaction is one that involves more than one transactional resource. For instance, a transaction having operations in two different data sources, or one transaction writes to database and also need to put a message to a messaging middleware. There are many solutions to resolve this situation where atomicity, reliability and safety are the main criteria.
Spring provides a ChainedTransactionManager (CTM) API using 1-phase commit. Basically, no-XA recourses can be used without changing much of the existing transaction managers. However, this is not infrastructure failure tolerant. And hence the 2-phase commit mechanism seems to be a better solution. Spring also provides full support of JTA by using JtaTransactionManager API (JTM). And, the application server handles the XA-resources. However, this way requires more configuration changes as compared to CTM. CTM is easy to implement with the help of JTA. Just like how CTM is configured using set transactionAttribute and JTA takes care of the XA-resources’ commit and roll back atomically.