[hibernate-dev] JTA synchronizations on WildFly
Steve Ebersole
steve at hibernate.org
Tue Mar 10 13:30:10 EDT 2015
Ah, that could be. Jipijapa does do a lot of things specific to the
provider used. Probably we just need some proper OGM Jipijapa hooks.
On Tue, Mar 10, 2015 at 12:14 PM, Gunnar Morling <gunnar at hibernate.org>
wrote:
> For some reason I'm seeing though JBossStandAloneJtaPlatform being used
> when debugging an OGM integration test on WildFly.
>
> WF's JtaPlatform seems not to be picked up. Tried to debug a but,
> apparently it never comes to the point where JipiJapa would inject the
> JBossAppServerJtaPlatform as platform. I could imagine it's due to OGM
> being used as persistence provider, so maybe the right implicit module
> dependencies don't get added? Scott?
>
> It's all a bit guess work on my side, I don't know that WF/JipiJapa code
> very well.
>
>
>
> 2015-03-10 16:50 GMT+01:00 Steve Ebersole <steve at hibernate.org>:
>
>> Gunnar, WildFly uses its own JtaPlatform...
>>
>> On Tue, Mar 10, 2015 at 10:44 AM, Gunnar Morling <gunnar at hibernate.org>
>> wrote:
>>
>>> Hi,
>>>
>>> > I believe that your workaround, mentioned below, of using
>>> JtaPlatform#registerSynchronization() on WildFly, is registering your
>>> synchronization as interposed via the TransactionSynchronizationRegistry
>>> [2].
>>>
>>> That seems not to be the case. If you check out AbstractJtaPlatform and
>>> TransactionManagerBasedSynchronizationStrategy in ORM,
>>> registerSynchronization() adds the Sync as non-interposed via
>>> TransactionManager.getTransaction().registerSynchronization().
>>>
>>> But the ordering is indeed what makes me wonder. As
>>> SessionSynchronization
>>> is interposed, the non-interposed beforeCompletion() hooks are run, but
>>> the
>>> non-interposed afterCompletion() hooks managed via
>>> RegisteredSynchronization are never run, as the session has been closed
>>> and
>>> thus the list of syncs to be invoked through RegisteredSynchronization
>>> has
>>> been cleared at this point. At least this behaviour was surprising to me.
>>>
>>> My work-around works because my non-interposed sync is added through
>>> JtaPlatform to the actual (Arjuna) Transaction instance directly (rather
>>> than indirectly via RegisteredSynchronization) and thus gets invoked
>>> properly.
>>>
>>> 2015-03-10 14:39 GMT+01:00 Scott Marlow <smarlow at redhat.com>:
>>>
>>> > 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#registerInterposedSynchronizat
>>> > ion%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 at lists.jboss.org
>>> >> https://lists.jboss.org/mailman/listinfo/hibernate-dev
>>> >>
>>> >>
>>> _______________________________________________
>>> hibernate-dev mailing list
>>> hibernate-dev at lists.jboss.org
>>> https://lists.jboss.org/mailman/listinfo/hibernate-dev
>>>
>>
>>
>
More information about the hibernate-dev
mailing list