One option is that instead of creating a new EntityManagerFactory in EMFactory (which is in the request area), you can create a singleton factory for EntityManagerFactory , and then just enter EntityManagerFactory in EMFactory .
public class EMFFactory implements Factory<EntityManagerFactory> { private final EntityManagerFactory emf; public EMFFactory (){ emf = Persistence.createEntityManagerFactory(persistenceUnit); } public EntityManagerFactory provide() { return emf; } ... } public class EMFactory implements Factory<EntityManager> { private final EntityManager em; @Inject public EMFactory (EntityManagerFactory emf){ em = emf.createEntityManager(); } public EntityManager provide() { return em; } ... }
We have not tested this exact implementation, but it should look something like this. I have used this template before.
register(new AbstractBinder() { @Override public void configure() { bindFactory(EMFFactory.class).to(EntityManagerFactory.class).in(Singleton.class); bindFactory(EMFactory.class).to(EntityManager.class).in(RequestScoped.class); } });
UPDATE
One comment on the above example is that it does not clear resources, i.e. EntityManager should be close; it will not close. There is a dispose method in the Factory class that we need to override, but from my experience it is never called Jersey.
What we can do is add an EntityManager to [ CloseableService ] [1]
public class EMFactory implements Factory<EntityManager> { private final EntityManagerFactory emf; private final CloseableService closeService; @Inject public EMFactory (EntityManagerFactory emf, CloseableService closeService){ this.emf = emf; this.closeService = closeService; } public EntityManager provide() { final EntityManager em = emf.createEntityManager(); this.closeService.add(new Closeable(){ @Override public void close() { em.close(); } }); return em; } ... }
Thus, the EntityManager will be closed at the end of the request.
Paul Samsotha Jan 24 '15 at 6:18 2015-01-24 06:18
source share