[hibernate-dev] JTA synchronizations on WildFly
Gunnar Morling
gunnar at hibernate.org
Tue Mar 10 13:14:15 EDT 2015
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