Debugging transactions in Java EE
-
26-09-2019 - |
Question
I have an @Stateless EJB method in which I
- delete some entries from a database
using JPA
remove()
's - throw an Exception that is annotated as
@ApplicationException(rollback=true)
I have no other transaction-specific annotations for the method (I set @TransactionAttribute(TransactionAttributeType.REQUIRED)
but that should be the default anyway!). Transactions are container managed. JPA provider is EclipseLink.
And still, the transaction is not rolled back when the exception is thrown. Eg. the entries that I deleted from the database before the rollback don't come back. Btw. I call entityManager.flush() before the throw, can it cause such behaviour (it shouldn't)?
I also tried to call SessionContext.setRollbackOnly()
, with the same result.
How can I debug this problem?
I'm using Glassfish v3 and Netbeans for debugging, but I'd be equally happy with println's I just don't know where to put them...
Solution
I have an @Stateless EJB method in which I (...)
Just to clarify how do you get the EntityManager?
(...) I set @TransactionAttribute(TransactionAttributeType.REQUIRED
Indeed, this is the default and shouldn't be required anyway.
And still, the transaction is not rolled back when the exception is thrown. Eg. the entries that I deleted from the database before the rollback don't come back.
Hmm, that's very strange and unexpected.
Btw. I call entityManager.flush() before the throw, can it cause such behaviour (it shouldn't)?
No, flush != commit
I also tried to call SessionContext.setRollbackOnly(), with the same result.
Well, still unexpected (but at least consistent...).
I'm using Glassfish v3 and Netbeans for debugging
Maybe activate the logging of the following categories (e.g. via the admin Console under Configuration > Logging > Log Levels) to see if you can spot anything weird:
- javax.enterprise.system.core.transaction
- javax.enterprise.resource.jta
- javax.enterprise.system.container.ejb
As an alternative (sort of "poor man's logging"), you could implement SessionSynchronization
to get notified about transaction.
Really weird problem...
See also
OTHER TIPS
In addition to Pascal's good answer, some things to check... Your EntityManager
is guaranteed not to participate in container-managed transactions if any of the following are true:
- You created the EntityManager via an EntityManagerFactory
- You specified
transaction-type="RESOURCE_LOCAL"
in your persistence.xml
Secondary things to check:
<jta-data-source>
is filled in in the persistence.xml- the DataSource referenced via
<jta-data-source>
is setup to participate in JTA transactions (auto-commit is off)
These last two are somewhat vendor specific in that some vendors will automatically fill in the <jta-data-source>
if it is not specified. As well some will fail deployment if the <jta-data-source>
is pointing to a DataSource that is not setup to participate in JTA transactions (that setup is vendor specific). Not sure how Glassfish handles these two items.