Description
From [email protected] on February 02, 2013 05:40:00
Form the commit rb7a02b02d81c (Jul 7, 2011), in JpaPersistService.java which is a Provider<EntityManager>, in the get() method, we can see that if we don't already have an EntityManager stored in the thread local variable, we call the begin() method. This method will create a new EntityManager, and store it in the thread local variable.
So, if we follow the documentation in the wiki (page "Using JPA", section "Using the EntityManager inside transactions"), for each thread, for every other action needing an EntityManager, the same instance will always be returned, and this EntityManager will never be closed.
This can lead to broken threads, as if for any reason the EntityManager can no longer be used (connection closed, etc.), there is no way to replace it.
Note that this issue doesn't happen if the injection of EntityManager is done inside an opened UnitOfWork or inside a method annotated with @
Transactional. In these cases, the EntityManager is already created, and will be destroyed at the end of the transaction, or on UnitOfWork close.
While taking a look at the get() method of JpaPersistService, we can also see that there is a strange precondition test. As said, if the EntityManager doesn't exist, it's created. Juste after that, we check if we have an EntityManager. If we don't have any, we throw this error message: "Requested EntityManager outside work unit.". Sounds like a bug, we should either remove the Precondition test, or remove the begin() call if the EntityManager doesn't exist.
So, my suggestion would be either to fix the get() method, or change the documentation to tell about this potential issue, and suggest the injection of Provider<EntityManager> in every cases.
Original issue: http://code.google.com/p/google-guice/issues/detail?id=739
Activity