[jboss-jira] [JBoss JIRA] (WFLY-8954) Wildfly 10 with eclipselink Onscucess observer gets stale entity

Nuno Godinho de Matos (JIRA) issues at jboss.org
Wed Jun 28 05:32:00 EDT 2017


    [ https://issues.jboss.org/browse/WFLY-8954?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13427948#comment-13427948 ] 

Nuno Godinho de Matos edited comment on WFLY-8954 at 6/28/17 5:31 AM:
----------------------------------------------------------------------

Hi,

It is a bit hard for me to keep up, as these APIs at the level of resource adapter developers and component integration.

But I see the point you bring up:
It is not such a trivial matter to manage the sequence by which Synchronization Listeners register on the JTA transaction context.


I believe however, that one way or another, somehow the  eclipselink:
org.eclipse.persistence.transaction.JTASynchronizationListener
Needs to be run before the CDI on completion synchronization listener.
This a level of service with quite a bit of importance.
To not do violates the exceptions that developers have of what the state of the DB an cached entities should be as a transaction is said to be completed. And in fact, with hibernate this level of service is upheld.


Side Notes:
I am tried to take a pick the eclipse link code related to the synchronization process.
I can see that with the increasing versions, the code in eclipselink is gettingbetter and better documented. Which i consider something very positive.

Here are some of the relevant classes I have spotted, but most likely you are aware of them all.

org.eclipse.persistence.transaction.JTATransactionController
This class is extended by multiple subclasses, specific to different application servers.
Among its apis it holds the method:
registerSynchronization_impl

QUOTE
{panel}
/**
     * INTERNAL:
     * Register the specified synchronization listener with the given active
     * transaction.
     *
     * @param listener The synchronization listener created for this transaction
     * @param txn The active transaction for which notification is being requested
     */
    protected void registerSynchronization_impl(AbstractSynchronizationListener listener, Object txn) throws Exception {
        ((Transaction)txn).registerSynchronization((Synchronization)listener);
    }
{panel}

NOTE: And here we know that the registration will be happening too late.

With the WildflyServerPlaform, 
{panel}
<dependency>
                <groupId>org.wildfly</groupId>
                <artifactId>jipijapa-eclipselink</artifactId>
                <version>10.0.0.Final</version>
                <scope>provided</scope>
            </dependency>
{panel}


it would  look to me as if the ideal spot to do the tunning would be on:
org.jipijapa.eclipselink.WildFlyServerPlatform.JBossAS7TransactionController

If this class could somehow override the registerSynchronization_impl  to ensure that when it registers it goes to earlies position on the list.
But from what I can see, at leas t from public APIs, there seems to be no support
to do anything such as manipulating the order of the listeners.

There is also the the class
org.eclipse.persistence.internal.jpa.EntityManagerImpl

This the class  that takes us  down the rabbit hole, 
and that will do the JTA synchronization registration listener is put in place in its:

org.eclipse.persistence.internal.jpa.EntityManagerImpl.getActivePersistenceContext(Object)
{panel}
 if (txn != null) {
                // if there is a txn, it means we have been marked to join with it.  
                // All that is left is to register the UOW with the transaction
                transaction.registerIfRequired(this.extendedPersistenceContext);
            }
{panel}


I will now mention two possibilities, that I believe none of them are feasible.
Any way, let me gun sling them away.

 Possbility 1,
I would call it a  "vodoo" work-around.
Ant that most likely is no feasible as explained bellow.

At time 1, when Wildfly registers the normal CDI Dummy synchronization listener - DelayedCDIObserverSynchronizationListenerr or something of the sort

At time 2, the arjuna is going over registered listeners and invoking them
com.arjuna.ats.internal.jta.resources.arjunacore.SynchronizationImple.afterCompletion(int) line: 96	

At time 3, the DelayedCDIObserverSynchronizationListenerr
gets called and it makes a late registrations into the transaction of the real CDI listener that is currently being invoked in first place.

At time 4, the eclipselink 
org.eclipse.persistence.transaction.JTASynchronizationListener

At time 5, the real CDI Observer notifier gets invoked since it was "vodoo" placed into the trasaction at the alst posisble moment in time.

I can well imagine that this sort of work-around might not even be technically possible  since it would verily likely lead to something like at concurrent modification exceptions on the:
com.arjuna.ats.internal.jta.resources.arjunacore.SynchronizationImple.afterCompletion(int) line: 96	
As we goes out of invoking the listener, and tries to move to the next one, the list is suddenly changed and the loop broken. 

But the fact is that the:
javax.transaction.Transaction registerSynchronization seems to give no option on sorting the order of the observers.
Also seems not to give any option to remove the observers.

Possibility 2 (might not be posisblle as well):
But this would be much much cleaner.

One would want to override method of:
registerSynchronization_impl

And write it to be something as simple as:
To (a) Get a list of all registered observers.
(b) Derisgeter them  all
(c) Register the eclipselink obverserver first on the list
(d) Ad all of the de-registered observers  back in.



Kindest regards.









was (Author: nuno.godinhomatos):
Hi,

It is a bit hard for me to keep up.
But I see the point.

It is not a trivial matter manage the sequence by which Synchronization Listeners register on the transaction.
But I would agree, that one way or another, somehow the  eclipselink:
org.eclipse.persistence.transaction.JTASynchronizationListener
Needs to be run before the CDI on completion synchronization listener.

Side Notes:
- I am trying take a pick the eclipse link code related to the synchronization process.
Here are some of the relevant classes:

(a) org.eclipse.persistence.transaction.JTATransactionController
This class is extended by multiple subclasses, specific to different application servers.
Among its apis it holds the method:
registerSynchronization_impl

QUOTE
{panel}
/**
     * INTERNAL:
     * Register the specified synchronization listener with the given active
     * transaction.
     *
     * @param listener The synchronization listener created for this transaction
     * @param txn The active transaction for which notification is being requested
     */
    protected void registerSynchronization_impl(AbstractSynchronizationListener listener, Object txn) throws Exception {
        ((Transaction)txn).registerSynchronization((Synchronization)listener);
    }
{panel}

And here we know that the registration will be happening too late.
With the WildflyServerPlaform, it would like the ideal thing would be if the inner class:
org.jipijapa.eclipselink.WildFlyServerPlatform.JBossAS7TransactionController

Could somehow override the registerSynchronization_impl  to ensure that when it registers it goes to earlies position on the list.
But I doubt there are public APIs for doing this level of tunning.



The class
org.eclipse.persistence.internal.jpa.EntityManagerImpl

Is that class that will go down the rabit hole, until the JTA synchronization registration listener is put in place in its:
org.eclipse.persistence.internal.jpa.EntityManagerImpl.getActivePersistenceContext(Object)

{panel}
 if (txn != null) {
                // if there is a txn, it means we have been marked to join with it.  
                // All that is left is to register the UOW with the transaction
                transaction.registerIfRequired(this.extendedPersistenceContext);
            }
{panel}



I could imagine the following Possbility 1,
That I could call a  "vodoo" work-around.
Ant that most likely is no feasible as explained bellow.

At time 1, when Wildfly registers the normal CDI Dummy synchronization listener - DelayedCDIObserverSynchronizationListenerr or something of the sort

At time 2, the arjuna is going over registered listeners and invoking them
com.arjuna.ats.internal.jta.resources.arjunacore.SynchronizationImple.afterCompletion(int) line: 96	

At time 3, the DelayedCDIObserverSynchronizationListenerr
gets called and it makes a late registrations into the transaction of the real CDI listener that is currently being invoked in first place.

At time 4, the eclipselink 
org.eclipse.persistence.transaction.JTASynchronizationListener

At time 5, the real CDI Observer notifier gets invoked since it was "vodoo" placed into the trasaction at the alst posisble moment in time.

I can well imagine that this sort of work-around might not even be technically possible  since it would verily likely lead to something like at concurrent modification exceptions on the:
com.arjuna.ats.internal.jta.resources.arjunacore.SynchronizationImple.afterCompletion(int) line: 96	
As we goes out of invoking the listener, and tries to move to the next one, the list is suddenly changed and the loop broken. 

But the fact is that the:
javax.transaction.Transaction registerSynchronization seems to give no option on sorting the order of the observers.
Also seems not to give any option to remove the observers.

Therefore a cleaner Possibility 2 (might not be posisblle as well:
One would want to override method of:
registerSynchronization_impl

And write it to be something as simple as:
To (a) Get a list of all registered observers.
(b) Derisgeter them  all
(c) Register the eclipselink obverserver first on the list
(d) Ad all of the de-registered observers  back in.



Kindest regards.








> Wildfly 10 with eclipselink Onscucess observer gets stale entity
> ----------------------------------------------------------------
>
>                 Key: WFLY-8954
>                 URL: https://issues.jboss.org/browse/WFLY-8954
>             Project: WildFly
>          Issue Type: Bug
>          Components: JPA / Hibernate
>    Affects Versions: 10.0.0.Final
>            Reporter: Nuno Godinho de Matos
>            Assignee: Scott Marlow
>
> Hi,
> In widlfly there seems to be an important issue concerning CDI events and observing these events during onsuccess. At least while using eclipselink.
> When using wildfly 10.0.0.Final together with eclipselink, if an application modifies an entity A, fires an event stating entity A has been modified, and an observer consumes this event during transaction success.
> Then the observer will be working with stale entities that do not reflect the modifications done to the entity.
> A sample application for this issue is available in:
> https://github.com/99sono/wildfly10-observe-on-success-stale-entity
> The widlfly configuration xml for the sample application, is available in the application itself, as can be seen in the readme documentation.
> Many thanks for taking a look.
> Kindest regards.



--
This message was sent by Atlassian JIRA
(v7.2.3#72005)


More information about the jboss-jira mailing list