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
Steve Ebersole <steve(a)hibernate.org>