Wow - very cool. When do you think this patch will be released? And would you be able to provide a brief code snippet of how to use/extend this new class? My current setup is below which uses an ExecuteAndWaitInterceptor to create a class that extends the BackgroundProcess class.

Again thanks for all your work on this.


@Component
public class OpenSessionExecuteAndWaitInterceptor extends ExecuteAndWaitInterceptor {

    @Autowired
    private transient EntityManagerFactory entityManagerFactory;

    @Override
protected BackgroundProcess getNewBackgroundProcess(String arg0, ActionInvocation arg1, int arg2) { return new OpenSessionBackgroundProcess(arg0, arg1, arg2, entityManagerFactory);
    }
}


public class OpenSessionBackgroundProcess extends BackgroundProcess implements Serializable {

    private static final long serialVersionUID = 1L;

    private final transient EntityManagerFactory entityManagerFactory;

    // used for synchronization
    protected boolean initializationComplete;
    private transient Object lock = new Object();

public OpenSessionBackgroundProcess(String name, ActionInvocation invocation, int threadPriority, EntityManagerFactory entityManagerFactory) {
        super(name, invocation, threadPriority);
        this.entityManagerFactory = entityManagerFactory;
        initializationComplete = true;
        synchronized (lock) {
            lock.notify();
        }
    }

    protected void beforeInvocation() throws Exception {
        while (!initializationComplete) {
            try {
                synchronized (lock) {
                    lock.wait(100);
                }
            } catch (InterruptedException e) {
                // behavior ignores cause of re-awakening.
            }
        }
        EntityManager em = entityManagerFactory.createEntityManager();
TransactionSynchronizationManager.bindResource(entityManagerFactory, new EntityManagerHolder(em));
        super.beforeInvocation();
    }

    protected void afterInvocation() throws Exception {
        super.afterInvocation();
        EntityManagerHolder emHolder = (EntityManagerHolder)
TransactionSynchronizationManager.unbindResource(entityManagerFactory); EntityManagerFactoryUtils.closeEntityManager(emHolder.getEntityManager());
    }

    /**
     * Override default readObject() method when deserializing
     *
     * @param serialized the serialized object
     */
private void readObject(ObjectInputStream serialized) throws IOException, ClassNotFoundException {
        serialized.defaultReadObject();
        lock = new Object();
    }
}

------ Original Message ------
From "Lukasz Lenart" <lukaszlen...@apache.org>
To "Struts Users Mailing List" <user@struts.apache.org>
Date 10/5/2022 2:12:20 AM
Subject Re: Race condition in recommended "OpenSessionBackProccess" class

I refactored the BackgroundProcess and it should solve your problem,
yet it will require some coding.
https://github.com/apache/struts/pull/609

niedz., 2 paź 2022 o 13:09 Lukasz Lenart <lukaszlen...@apache.org> napisał(a):

śr., 28 wrz 2022 o 16:15 Burton Rhodes <burtonrho...@gmail.com> napisał(a):
>
> Lukasz -
> I have queried you on this before, but I am trying to get to the bottom of
> why the class Dale Newfield recommended (many years ago) to solve the Open
> Session during ExecuteAndWait problem gives me issues from time to time
> [1]. Recently (as our user base grows) I am getting NPEs more and more on
> the synchronized "lock" variable. I posed the question to StackExchange
> [2], and one contributor suggested there is a race condition by extending
> the BackgroundProcess class.
>
> Full disclosure, this kind of problem starts to get over my head, so I am
> wondering if you might have some guidance on how I can once and for all fix
> this issue.
>
> As always, thanks in advance.
>
> [1]
> 
https://cwiki.apache.org/confluence/display/WW/HibernateAndSpringEnabledExecuteAndWaitInterceptor
>
> [2]
> 
https://stackoverflow.com/questions/73858251/how-to-properly-use-a-lock-variable-for-synchronization-in-a-serializable-clas?noredirect=1#comment130421653_73858251

As far as I understand the answer on SO, we must change how the
BackgroundProcess is initialised - instead of using a constructor
based logic, move it into a method or so.
Would you mind registering a ticket in JIRA with the above description?


Regards
--
Łukasz
+ 48 606 323 122 http://www.lenart.org.pl/

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscr...@struts.apache.org
For additional commands, e-mail: user-h...@struts.apache.org

Reply via email to