Not exactly sure but this might be the way that Jipijapa registers the
JtaPlatform. Originally, Jipijapa used the service approach but
reverted that due to a memory leak (I think in envers?).
This was mentioned a while back via [3]. I think we talked about
switching Jipijapa back to using a
META-INF/services/org.hibernate.engine.transaction.jta.platform.spi.JtaPlatformProvider
but I never bothered since the current non-service approach works
(except for your use case :).
Scott
[3]
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(a)hibernate.org
<mailto:steve@hibernate.org>>:
Gunnar, WildFly uses its own JtaPlatform...
On Tue, Mar 10, 2015 at 10:44 AM, Gunnar Morling
<gunnar(a)hibernate.org <mailto:gunnar@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(a)redhat.com
<mailto:smarlow@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(a)lists.jboss.org
<mailto:hibernate-dev@lists.jboss.org>
>>
https://lists.jboss.org/mailman/listinfo/hibernate-dev
>>
>>
_______________________________________________
hibernate-dev mailing list
hibernate-dev(a)lists.jboss.org <mailto:hibernate-dev@lists.jboss.org>
https://lists.jboss.org/mailman/listinfo/hibernate-dev