Today I've searched for a way to let some code run always in a new
transaction whether there is already one running or not. So that you
may have multiple parallel transactions that are totally independent
from each other. Sounds like the RequiresNew
Attribute from CMT (Container Managed Transaction)? That's because
the old application used CMT and besides the attribute RequiresNew also
Required,
NotSupported,
and Supports.
But some code from a reference project that we sould incorporate used
Bean Managed Transaction. It was an Interceptor that started the
transaction at the begin of a SessionBean call and committed it at the
end.
How to solve the situation? Required and Supports where ok. There was
always a transaction. For RequiresNew and NotSupported we've had some
help through our code organisation. The SessionBeans don't do any work.
All work is done through BO (Business Objects). So we could invent an
annotation that stops the starting of the transaction in the
Interceptor. For NotSupported the problem was solved. Code that had
RequiresNew should start the transaction in the BO. So whenever the
method is called, a new transaction is started, just was we wanted it.
Well that was a good plan, but how do you start a second transaction?
Try to call entityManager.getTransaction()
when your transaction typ is JTA in the persistence.xml and you get:
java.lang.IllegalStateException:
A JTA EntityManager cannot use getTransaction()
All you can do is to look up javax.transaction.UserTransaction
from the SessionContext. But there will be only one per thread. The
solution? Well. http://onjava.com/pub/a/onjava/2005/07/20/transactions.html
describes a javax.transaction.TransactionManager
that can not only create but also suspend and resume transactions. That
would solve my problem but unfortunately the TransactionManger is not
mandatory for application server. The may or may not provide it and the
one that provide it have each its own way. Sometimes each version has
its own way. So you would not only be bound to one vendor but also to a
specific version. Thast a bad thing.
Sounds like throwing away the code from the reference project and go
back to CMT? Well maybe, but there is also the option to change the
transaction type to RESOURCE_LOCAL. It works well for a small web
application I have to maintain additionally to this project.
To sum it up, I'm left with three options but none the silver bullet
needed.