[hibernate-dev] Exceptions thrown in a tx synchronization are eaten
steve at hibernate.org
Wed Jul 14 12:10:28 EDT 2010
For the sake of posterity (by which I mean my awful memory)...
We discussed this on IRC and really we have 2 discussions here, both
related to how the Hibernate Transaction API treats registered syncs:
1) The choice of whether to ignore/rethrow exceptions from the syncs
2) The problem with envers specifically not writing audit data in jta
(2) was the more troubling to me and we discovered that this only
happens with HEM + envers in JTA environments. The issue is that of
sync ordering. Essentially what happens is that Hibernate registers a
sync named CacheSynchronization. HEM then registers its own sync. The
HEM sync takes responsibility to initiate the "managed flush" during
beforeCompeletion() callbacks; CacheSynchronization is left to drive
the rest of the "before completion" processing within Hibernate. The
problem is that since CacheSynchronization was registered first most
transaction managers call it first (and even if they do not explicitly,
the behavior is non-deterministic; more about that later). In the
envers case, that really boils down to its "phase" being executed before
the flush which would cause the changes it listens to in order to write
its audit records.
Obviously we need to better control the ordering there.
Then a discussion with the JBossTS team when JBossAS first made the
switch for its TM came back to me, namely that JTA/JTS make no
guarantees about the order in which registered synchronizations get
called. Hibernate's Transaction API (org.hibernate.Transaction) allows
registrations of syncs. In JTA environments it currently simply
delegates that registration to the underlying JTA transaction. However,
this non-ordering issue is concerning. I suggest we alter that behavior
to act exactly as well do for JDBC-based transactions, and just host
those syncs within our Transaction locally.
As for (1), to be honest I still have not seen a compelling argument as
to why this should change. Outside of JCA and XA, the danger of mixed
heuristics is just too problematic. We discussed various potential ways
to allow syncs to signal that they should have their exceptions rethrown
should we decide to go that route.
On Tue, 2010-07-13 at 15:49 +0100, Emmanuel Bernard wrote:
> On 10 juil. 2010, at 09:05, Adam Warski wrote:
> > This, however, as it turns out, causes big problems in a JTA environment (with resource-local txs all works fine): audit records are sometimes not written. This is because the before tx completion process is called before tx synchronizations, and in JTA the auto-flush at the end of a session is done using a TX synchronization (AbstractEntityManagerImpl:1020). And it doesn't look like exceptions are eaten when thrown from a synchronization in JTA - otherwise any exception that occurred during a flush would go unnoticed (and I know from practice this doesn't happen ;) ).
> FYI, HEM does register the flush as a Synchronization operation because flush is conditionally executed (based on the fact that a PC has joined the tx or not).
> I could try and do the beforeCommit phase as an actionQueue#registerProcess(), but the question is will it fix the problem all the time? Today the impl seems to rely on a List so it's likely to work if the em#joinTransaction call is done before Hibernate Search and Hibernate Envers registrations.
> hibernate-dev mailing list
> hibernate-dev at lists.jboss.org
Steve Ebersole <steve at hibernate.org>
More information about the hibernate-dev