[jboss-dev-forums] [Design of JBoss Transaction Services] - TransactionLocal: values, locks and headaches

jhalliday do-not-reply at jboss.com
Fri Sep 21 05:52:39 EDT 2007


A TransactionLocal is similar to a ThreadLocal except it is keyed on the Transaction. Beyond that the documentation is rather sparse. Unlike a ThreadLocal, TransactionLocal is part of the app server, not the standard Java libraries. It?s also pluggable through the use of TransactionLocalDelegate. All this means you can?t be certain of much when it comes to TransactionLocal behaviour.

With the switch from the old in-memory TM to the use of JBossTS as the default transaction manager, we also see a new TransactionLocal implementation.  Needless to say, it does not work quite the same way as its predecessor. This impacts JBossAS 4.0.x if users retrofit it with the JBossTS, plus all later AS versions since they use the JBossTS implementation by default.

The JBossTS version originally (pre-TS 4.2.3.SP6) worked much the same way as the in-memory version: it used a Synchronization registered on the Transaction to store the state of ThreadLocals. This involved WeakReferences, which were suspected of causing more garbage collection load than was desirable. More seriously, there are some nasty corner cases in which it should be possible to change a TransactionLocal but it?s not possible to register a Synchronization.

In order to support JTA 1.1?s new TransactionSynchronizationRegistry interface, a generic Object storage mechanism was implemented on Transaction instances. Basically each Transaction behaves as a Map. So TransactionLocalDelegate was reimplemented to use this storage instead of a Synchronization.

In JBossTS, javax.transaction.Transaction is implemented by TransactionImple, which has the Map as a member variable. Up until transaction resolution (commit|rollback) a Transaction is represented by the same TransactionImple instance. After that all bets are off ? getTransaction() will generally return a new TransactionImple Object instance on each call i.e. after resolution, Object identity and transaction identity are no longer the same thing.  That?s nice for us because it means TransactionLocal state, which is part of the TransactionImple, goes away at transaction resolution time just like it?s supposed to, no WeakRefs required.

But?

The locks go away too. It?s possible to lock and unlock a TransactionLocal. The lock state is stored in the same Map on the TransactionImple. This is important because in JBossTS, transactions that have reached their timeout are rolled back by a dedicated Thread.

Unlike its in-memory predecessor, the reaper in JBossTS won?t try to lock a TransactionLocal before rolling back the Transaction. It?s not required to. So, a transaction may roll back under the feet of a Thread which has done a lock() and therefore expects the TransactionLocal?s value to stay constant.

Furthermore, to avoid race conditions you can?t write a TransactionLocal on a terminated Transaction, so that Thread may attempt to update the TransactionLocal and fail. Note that unlock() will fail silent if the transaction has terminated, so calling that is not a problem.

The short version:

1) Much of the existing code that makes use of TransactionLocal essentially assumes the behaviour of the in-memory implementation, which no longer holds. In order to support the weaker, more general contract that actually holds for pluggable transaction implementations, it may need more robust exception handling.

2) The pluggable API for transactions in JBossAS should probably be revisited and more thoroughly documented so that I can avoid writing long essays on implementation changes in the future.


View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4087138#4087138

Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4087138



More information about the jboss-dev-forums mailing list