Events, CDI and EntityManager

Hello,
we are using EJB session beans with JPA EntityManager to access database. Additionally we use CDI to inject service instances.
Now we are trying to decouple different services by using asynchronous events. Unfortunatly we have trouble with closed EntityManager exceptions. It seems that the EntityManager from the sending thread will be propagated to the thread, which processes the async event. After processing the async event it closes the EntityManager. In our case the originating thread is not finished yet and still needs his EntityManager. At this point we get the IllegalStateExceptions noting a closed EntityManager.

When trying the same flow with synchronous events, everthing works fine.

Does anybody have hints about whats going wrong here? Is it correct, that processing an asynchronous event closes my EntityManager?

I’m on payara 5 CE, docker image payara/server-full:5.2022.5-jdk11

Thank you
Michael

Hello Michael,
There are several ways, how to solve this situation. The best way would be, if you could make a reproducer, a simple program demonstrating the issue, so we can reproduce it. As you describe the situation, it looks like an issue in the server, but it needs some investigation. E.g. do you use ManagedExecutorService or ManagedThreadFactory?

I see a simple workaround, try @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) on the inner service (method or class).

As you are using server version, which is no more supported, I suggest you to upgrade to Payara 6, Jakarta EE 10 supports new ways for asynchronous execution like @Asynchronous annotation. We offer free tools for automated upgrade.

Of course, you can switch to Payara Enterprise, which offer long-term support: Payara Server Enterprise – Payara Services Ltd

Petr

Hello Michael,

I’ve had the same problem with closed connections since switching to Payara 5 and JSF with asynchronous database queries. Especially when using lazy loading queries, i.e. dynamically loading content to display it in a table, I have sporadically closed connections.
No one could help me and I always opened the connections manually (via @PersistenceUnit EntityManagerFactory) in the critical areas where asynchronous queries were required, made the query to the database and then closed the connection again. All non-synchronous queries were solved using the standard, i.e. via EJB and the EntityManager.

…and I always find it difficult to post an example here to simulate a database connection and query. How is that supposed to work? For example, do you have an Oracle database with configuration XY to test it?

Steven

Hello,

thanks for your responses. We still have issues with closed EntityManagers. Always asynchronous operations are involved. Currently i start two operations with ManagedExecutorService. These operations do a web request and returns the result as Pojo’s. Both operations don’t access the database. After both operations are finished, the main thread continues and when it tries to use the EntityManager, it gets the exception “… closed EntityManager”.

Switching to Payara 6 is planned but it will take time.

Our production environments are running with Payara Enterprise. I will try to check, if these exceptions occure there too.

Separating a reproducer may be difficult.

Thanks
Michael

Hello,

i have a little progress and maybe a workaround.

I was able to log the Transaction-Id and the EntityManagerImpl-Id at several points of the application. I can see, that every time, when no transaction is active, the EntityManagerImpl-Id is always the same. So it seems, that the Payara/JPA-Framework uses always the same instance of EntityManagerImpl, if there is currently no transaction active. This is also true for the asynchronous operation and it seems, that this EntityManagerImpl will be closed when the asynchronous operation finishes.

My workaround is, to put the whole asynchronous operation into a separate transaction.
Start the async operation in a service:

    private Future<List>> asyncLoad() {
        return managedExecutor.submit(() -> {
            return client.loadResults();
        });
    }

The real operation in another service starts a new transaction:

    @Transactional(value = Transactional.TxType.REQUIRES_NEW)
    public List loadResults() {
        ... do something
    }

This seems to work on Payara Community … we have to thest this on Payara Enterprise too.

I have to check, if this also works for asynchronous events i mentioned in the first post of this thread.

Thanks
Michael