0

There is an technology stack: Java EE (WebSpere), JPA, EJB3, JMS (MDB), JSF.

Architecture: JMS messages arrive (via MDB) and are registered as persisted entities - (using EntityManager). There is a Singleton class with infinite loop which is responsible for processing of those entities. The Singleton is notified about created entities by MDB. Initially entities are stored in queue inside the Singleton. Created entity can be processed up to several minutes. No more than certain amount of entities can be processed simultaneously (several parallel processes in Singleton). The Singleton is not an EJB, but there are EJB services used by it. There is a class which represents Execution Context for given entity (simple DTO). The Execution Context holds dependencies on needed EJBs and is created on MDB interaction step and passed to the Singleton service along with notification a new message (basically MDB has annotated injections of those EJBs and EM, and creates new Execution Context passing those injected instances).

The problem is: processing of an entity is started but EntityManager at some point of time (after a few seconds) begins returning nulls for search requests, and it should not, as just a second ago the entity was updated.

It looks like the architecture is not good. I suspect that the EM's behavior is a sign that persistence context has gone after some time after interaction between MDB and the Singleton has done. Singleton has life time much longer than life time of any managed bean in system. So, injection of EJB instances (and EM instance) to such component seems not to be a solution at all (passing references to injected EJB instances from MDB to the Singleton probably is a worst decision).

Probably EJB, as well as EM should be looked up by the Singleton using JNDI each time they are needed? In this case, should I lockup the EJBs for each call?

Which way would you design the system: if MDB only registered message (as entities). And processing of entities may start latter. And you have to use some EJB services (local interface). And there is Entity Manager as well.

Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
aillusions
  • 194
  • 1
  • 15

1 Answers1

0

If the entity manager that the Singleton is using is transaction scoped, then the lifetime of the Singleton doesn't matter. In a way, stateless session beans also have an infinite lifetime once created (their scope is essentially 'none', but their instances are pooled and kept being re-used).

Every time the method in the singleton services a request, a new transaction is started and a new persistence context is piggy-backed to that, even though the entity manager instance seems to be the same throughout those requests. This is normal behavior and should not 'suddenly' return nulls.

It might be worth checking if your singleton is using appropriate locks. If the entity manager is accessed concurrently then this may be the cause of undefined behavior.

Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
  • EM is used concurrently, but single entity is processed in dedicated thread in a sequence (a thread is created for each entity which is pulled from the Singleton's queue). The queue contains IDs of the entities. And as soon as thread is started, the attached EM is used to look-up entity by that ID. On the first steps of the the processing sequence entity seems to be not null and has properly initialized members (references). On further steps the entity may not be returned by EM by ID or members of the entity may not be populated correctly, e.g. collections of relations may be null etc. – aillusions Dec 13 '12 at 15:11
  • 1
    >EM is used concurrently - If that is indeed the case, then basically all bets are off. It doesn't really matter if you process single entities in a single thread. With a shared EM, the behavior is undefined, and the idea behind undefined behavior is simply that you can't explain it with logic without knowing all the intricate implementation details (on which you should not rely anyway). So the solution should be fairly simple; don't share the entity manager. – Arjan Tijms Dec 13 '12 at 16:33
  • Thanks. I think you are right, series of requests to EM to find same entity with a short pause between them gives different results. How would I create separate EM instances for different threads? Using EntityManagerFactory? – aillusions Dec 14 '12 at 13:45
  • 1
    The easiest way is probably to inject the entity manager into an `@Stateless` bean, inject that bean into the singleton, and delegate the persistence operations to that. A stateless bean is automatically thread-safe (every concurrent call on it will be routed under the covers to a different instance). – Arjan Tijms Dec 14 '12 at 17:23