I think we would need the same concurrency protection yes. If not today, in the near future.
> On 10 mars 2015, at 15:53, Scott Marlow <smar...@redhat.com> wrote: > > > >> On 03/10/2015 10:12 AM, Emmanuel Bernard wrote: >> So Gunnar, your workaround is fine today but will pose problems in the >> future if we decide that onRollback for ErrorHandler needs access to the >> session somehow to be able to compensate and undo the already executed >> operations: >> - a closed session will do us no good >> - there is a harder problem that Scott mentions below related to tx reaping >> in a different thread >> >> Let’s try and find a solution for the first problem. >> >> @Scott, I think what happens is the following: >> >> - Hibernate registers a Sync when the EM is created (for the flush() >> callbacks and a few other things) >> - Synchronization attached to the Hibernate Transaction objects are >> piggybacking on that initial Sync attachement >> - Wildfly attach a “close session” Sync once it has the instance of >> EntityManager >> - according to your rules, the close session afterTransaction Sync is called >> before the one Hibernate put >> - that explains why Gunnar finds an already closed Tx. >> >> But since Gunnar attaches its Sync when the Hibernate TransactionCoordinator >> creates the Hibernate transaction, which is when the EM is created, I can’t >> explain why the workaround works. > > Because Gunnar initially registered the Sync, via [3] > javax.transaction.Transaction.registerSynchronization(Sync), which might be > correct in some non-WildFly environments where perhaps all Syncs are > registered via [3] (as non-interposed syncs). When Gunnar, switched to the > Hibernate JtaPlatform mechanism for registering the Sync, we then switched to > an interposed Sync. I suspect that the JtaPlatform sync registration is a > good way to register the OGM, however, I have been told that the *best* way > is to register only one sync (to avoid ordering issues). > > If OGM could register to share the existing Hibernate EM sync, we would have > more control over when the OGM sync is invoked and in which thread > (application versus background tm reaping thread). > > Regarding the proposed "new proposal for tx timeout handling using > transaction DISASSOCIATING event notification" discussion and how that could > impact OGM. We will continue to run the interposed/non-interposed sync > callbacks in whatever thread the TM, calls them from (e.g. beforeCompletion > may or may not be called from app thread, afterCompletion will be called from > either app thread, background reaping thread or background communications > thread). The reason is that certain resources need to be cleaned up > immediately from the Sync.afterCompletion(int status) call. Certain other > resources (like clearing managed entities from persistence context after a > rollback), need to be handled from either the application thread or a > background thread after the application thread is disassociated from the JTA > transaction. > > IMO, the OGM ErrorHandling/Compensation API probably needs to be aware of the > same concurrency requirements to avoid presenting the executed operations > list, while the application thread is still executing new operations (because > it perhaps doesn't yet know that the tx rolled back). > > It would be good to know if OGM will also need the concurrency protection, so > that any new Hibernate 5.0 SPI can be used by OGM (e.g. currently the only > need is to run the Hibernate Session.clear when we know that the application > thread is not actively using the Session). > >> >> Emmanuel >> >>> On 10 Mar 2015, at 14:39, Scott Marlow <smar...@redhat.com> wrote: >>> >>> Hi Gunnar, >>> >>> Yes, this behaviour is expected since you registered an non-interposed >>> synchronization. For what purpose are you registering the transaction >>> synchronization? I would like to be aware of the synchronizations that >>> we register in WildFly. >>> >>> The non-interposed sync beforeCompletion callback are invoked first, >>> then the interposed sync beforeCompletion calls, then the interposed >>> afterCompletion(int status) calls and finally, the non-interposed >>> afterCompletion(int status) calls. >>> >>> The Synchronizations that are registered via the >>> javax.transaction.TransactionSynchronizationRegistry.registerInterposedSynchronization(Synchronization) >>> [2] are interposed. >>> >>> Synchronizations that are registered via the >>> javax.transaction.Transaction.registerSynchronization(Synchronization) >>> [3] are non-interposed. >>> >>> In WildFly, the transaction manager uses the registration order within >>> the interposed/non-interposed group. Before completion syncs (within >>> their respective group), are run in registration order. After >>> completion syncs (within their respective group), are run in reverse >>> registration order. >>> >>> I believe that your workaround, mentioned below, of using >>> JtaPlatform#registerSynchronization() on WildFly, is registering your >>> synchronization as interposed via the TransactionSynchronizationRegistry >>> [2]. There might be a way to register a sync callback at the Hibernate >>> session level (which would also run as interposed sync on WildFly). >>> >>> Not sure if you saw my email yesterday to Hibernate-dev ml. You should >>> be aware that the afterCompletion(int status) callback, may be called >>> from a non-application thread when the WildFly tm reaper handles tx >>> timeout (this can happen while the application thread is still invoking >>> calls on the Hibernate session). Because the Hibernate session is not >>> thread safe, we need to ensure that the Hibernate session >>> afterCompletion(int status) callback does not mutate the Hibernate >>> session (e.g. calling session.clear() what status == rolled back). >>> >>> Scott >>> >>> [2] >>> http://docs.oracle.com/javaee/5/api/javax/transaction/TransactionSynchronizationRegistry.html#registerInterposedSynchronization%28javax.transaction.Synchronization%29 >>> >>> [3] >>> http://docs.oracle.com/javaee/5/api/javax/transaction/Transaction.html#registerSynchronization%28javax.transaction.Synchronization%29 >>> >>>> On 03/10/2015 09:03 AM, Gunnar Morling wrote: >>>> Hi, >>>> >>>> I'm trying to perform a specific action upon transaction rollback. >>>> >>>> Assuming this could be done using a custom >>>> javax.transaction.Synchronization, I tried to register a synchronization as >>>> follows: >>>> >>>> TransactionImplementor transaction = ...; // e.g. a CMTTransaction >>>> transaction.registerSynchronization( new MySync() ); >>>> >>>> And indeed beforeCompletion() is invoked as expected. But afterCompletion() >>>> never is. I debugged this a bit on WildFly and observed the following: >>>> >>>> * Hibernate ORM registers RegisteredSynchronization with JTA. >>>> RegisteredSynchronization manages (indirectly, through >>>> TransactionCoordinator, SynchronizationRegistry etc.) those >>>> synchronizations added through o.h.t.Transaction.registerSynchronization() >>>> * WildFly (specifically, TransactionUtil [1]) registers its own >>>> SessionSynchronization >>>> for closing the entity manager/session >>>> >>>> Now that second synchronization is called first, closing the session. Upon >>>> SessionImpl#close(), the SynchronizationRegistry is cleared. Then when >>>> afterComplection() is called on RegisteredSynchronization afterwards, any >>>> previously registered delegate synchronizations are gone already and thus >>>> do not get invoked. >>>> >>>> I believe I found a workaround for my case by registering my >>>> synchronization through JtaPlatform#registerSynchronization() (which >>>> registers it with the actual JTA transaction). >>>> >>>> My questions are: >>>> >>>> * Is this behaviour expected? >>>> * Is the work-around of doing the registration via JtaPlatform viable or >>>> are there any drawbacks which I'm not aware of? >>>> >>>> Thanks, >>>> >>>> --Gunnar >>>> >>>> [1] >>>> https://github.com/wildfly/wildfly/blob/master/jpa/src/main/java/org/jboss/as/jpa/transaction/TransactionUtil.java >>>> _______________________________________________ >>>> hibernate-dev mailing list >>>> hibernate-dev@lists.jboss.org >>>> https://lists.jboss.org/mailman/listinfo/hibernate-dev >>> _______________________________________________ >>> hibernate-dev mailing list >>> hibernate-dev@lists.jboss.org >>> https://lists.jboss.org/mailman/listinfo/hibernate-dev >> _______________________________________________ hibernate-dev mailing list hibernate-dev@lists.jboss.org https://lists.jboss.org/mailman/listinfo/hibernate-dev