How to properly use standalone TransactionManager in web application?

1.1k views Asked by At

I'd like to write my next tiny Java webapp by using one of micro-frameworks. E.g. Spark or Jooby. The problem is that both of them doesn't support JTA, so I need to use one of third-party libraries. I've googled for open-source JTA implementations and found two: Atomikos and Bitronix. It seems that the latter project is slightly abandoned so I've decided to go with Atomikos. Unfortunately documentation is scarce so I can't find answers to my questions.

Here is the use case. Suppose we have two DAO classes which methods should be executed under single transaction:

class SomeService {

    // both injected by Guice
    private FooDao fooDao;
    private BarDao barDao;

    public void someMethod() {
        // both methods should be executed in a single transaction
        fooDao.insert(new Foo());
        barDao.insert(new Bar());
    }
}

I've never used javax.transaction API directly/manually before (you know declarative transactions are very simple with Spring) so I'm a bit confused. JTA provides two general abstractions(UserTransaction and TransactionManager) and they both have methods to handle JDBC transaction. As far as I understand TransactionManager operates UserTransaction objects by using ThreadLocal variables. Therefore UserTransaction should be thread-confined and TransactionManager supposed to be thread-safe. Am I correct?

So there are several approaches possible:

  1. I can inject TransactionManager into my service (via Guice) and use it directly.
  2. I can share TransactionManager via public static variable.
  3. I can create an UserTransaction provider/factory (via Guice) and get objects from it.

Which is correct/best-practice?

Another question if someone familiar with Atomikos is that it provides two transaction manager implementations (maybe even more): J2eeTransactionManager and UserTransactionManager. Again documentation is too scarce so I don't see any difference except JNDI. I suppose UserTransactionManager should be enough for my purposes but description states the following

J2eeTransactionManager

An implementation of TransactionManager that should be used by J2EE applications.

.. without any explanation.

ps. Sorry my english isn't well I know it.

1

There are 1 answers

3
Evan On

Ок, since no-one answered me, after digging into source code, I think I'm ready to answer my own question:

  1. Both Atomikos and Bitronix TMs implemented as singletons [1], [2]
  2. Both Atomikos and Bitronix TMs are thread-safe. Particularly, Atomikos uses intrinsic synchronization and Bitronix simply doesn't share state between threads.
  3. Both Atomikos and Bitronix TMs implement both (oops) TransactionManager and UserTransaction interfaces so in basically doesn't matter which one you'll use. Even if you look at the Atomikos UserTransactionImp class you'll see that it internally instantiates and uses corresponding TransactionManager implementation.

So it is safe to have one TM-per-webapp instance, which you can share any way you like. Since Atomikos TM supposed to be instantiated it's better to share it through dependency injection. Bitronix TM can be used through public static method as any other singleton.

Additionally you can manage transactions via JNDI. You can find an example in the Java Persistence with Hibernate book source code.