[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:38: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:37 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	
A the iteration goes from the first listener to the second, the loop may be broken due to a concurrent modification exception on the list of listeners.
But this idea might potentially even work out, if the vodoo listener, would be triggered before the oncompletion event in fact.

The fact is that the:
javax.transaction.Transaction registerSynchronization seems to give no option on sorting the order of 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, 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.








> 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