views:

27

answers:

2

I have an @Stateless EJB method in which I

  1. delete some entries from a database using JPA remove()'s
  2. 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...

+1  A: 

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

Pascal Thivent
SessionSynchronization is what I was looking for, thank you! I rearranged the code so that it hurts less, but I'm really curious about what's going on...
Gabor Kulcsar
By the way, logging JTA does not help, because setting loglevel to NICE creates so much extra information that I can't get anything useful out of it.
Gabor Kulcsar
@Gabor Yeah, I was a bit afraid the app server logging would be too verbose, which is why I also mentioned `SessionSynchronization`.
Pascal Thivent
+1  A: 

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.

David Blevins
Informative answer, thank you. Unfortunately the problem is local, because otherwise transactions work as expected.
Gabor Kulcsar