Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 5 Next »

JTA Best Practices

Why is the JTA API your friend ? How does it help you writing better code ? Those are questions that we will try to answer here.

Why using the JTA API

Even if you're only planning to use a single database in your application (ie: if you don't plan to make use of 2 Phase Commit) using the JTA API is still a good idea as it helps separating concerns in your application.

The biggest benefit is the separation of the transaction management concern from the connection management concern. What does that mean ?

When using 'good old' JDBC, you work with a single object type: the Connection but this object is used twofolds: for data manipulation (ie: SELECT, INSERT, UPDATE, DELETE) and for transaction management (ie: COMMIT and ROLLBACK).

This is awkward as you often end up using an object for a concern (data manipulation) then keep it aside for later usage for another concern (committing or rolling back your changes).

Straight JDBC Example

Take this simple example to illustrate our concern:

Example 1

This code is reasonably clean as the calling business method (executeA_B_C()) does no know that the underlying logic is using JDBC which is good Object Oriented design. It is also possible to encapsulate the JDBC boilerplate code in some helper class, DAO or even delegate that to a more powerful solution like Spring's JdbcTemplate. Data access code will change in that case but the idea stays the same.

Unfortunately the data manipulation is not atomic: if an error happen in executeBusinessLogicB then all modifications made by executeBusinessLogicA cannot be rolled back.

A commonly found way to fix this problem is by sharing the Connection object between all 3 business methods:

Example 2

The code is now much less clean as to ensure all 3 business methods will execute in the same transaction, we pass them a Connection object which is not of any business value.

Best of both worlds

How to get the clean data access encapsulation of the first example together with correct transaction handling of the second example ? A straightforward continuation of the same logic could lead us to some kind of ConnectionHolder singleton that would store the connection in a ThreadLocal variable. The different business methods would then get their Connection from the ConnectionHolder object.

While this would work, this is not as trivial as it sounds. You would have to initialize the ConnectionHolder (or make it initialize lazily) then clean up all resources it holds together with exception handling. This also makes the code less reusable as you always need to ensure you have access to a ConnectionHolder from within your business methods.

A better solution is to separate the transaction management logic from the data access logic, and this is exactly what JTA is for.

Not only is this code more maintainable than the previous example 2 but it also improves example one in two areas: not only is it now fully transactional but the error handling is now centralized.

You don't have to care about connections, just get them from the pool when needed and release them as soon as you're done with it. The transaction manager and the connection pool will ensure the transaction will be committed at the right time.

  • No labels