1

I'm developing a system to process messages and update the database accordingly, but I need to keep some degree of isolation between layers. I have in mind something like the following.

  • MyDao.java: a @Stateless bean that provides database access. MyDao accesses the database using JPA, with an EntityManager injected by @PersistenceContext.
  • MyMdb.java: an MDB that listens on a queue. MyMdb uses MyDao by injection with @EJB.

One single execution of MyMdb.onMessage() needs to perform several accesses to the database, both read and write.

  • On the one hand, this makes me think that a @Stateless bean is not the right choice for MyDao: the EntityManager instance in MyDao could be randomly accessed by different executions of MyMdb.onMessage(), leading threads to interfere with each other.
  • On the other hand, JPA documentation says that the injected EntityManager is just a proxy: the actual persistence context on which it operates is the one bound to the JTA transaction. This way everything should be ok because, even though EntityManagers are "shared", each MDB will have a different transaction ongoing and thus work in safe isolation.

What is the right scenario? Am I missing something?

Davide
  • 136
  • 8

1 Answers1

0

Entity managers injected in a stateless EJB in the way that you described are exactly what you should do. This type of injection provides a 'Container-Managed Entity Manager' which is 'transaction scoped'. So in the scenario that you describe.

  1. the onMessage MDB call will create a transaction
  2. the call to the stateless bean will happen to the same transaction context, creating an Entity Manager which will live until the transaction finishes usually when the MDB method returns.

The specific type of injected entity manager for the same EJB instance doesn't survive and is not re-used across different transactions.

garfield
  • 571
  • 9
  • 21
  • About point 2, `MyDao` is a stateless session bean: why do you say that it will be created anew? Being it stateless, the container could pick any other pooled instance of `MyDao`. This means that it will already have an `EntityManager` injected some time before by **another** instance of `MyMdb`, messing things up. Am I missing something? – Davide Aug 02 '18 at 15:25
  • The lifecycle of the sessions beans is somehow complex to be reproduced here. The whole point is that what you see is a proxy to a thread that may be pooled or not. As for the Entity manager although it may appear as an instance of a bean it's lifetime is associated with the transaction context that's why is called 'transaction scoped'. Always refering to our MDB SLSB EJB case. Beyond that extended persistence, contexts may be used with Stateful EJBs, which is another story. – garfield Aug 02 '18 at 15:52