agnul agnul - 5 months ago 183
Java Question

How do I properly configure an EntityManager in a jersey / hk2 application?

I have a jersey-2 / hk2 application which uses JPA persistence. The

EntityManager
is bound at startup like this

public MyApplication() {
// ...
register(new AbstractBinder() {
@Override
public void configure() {
bindFactory(EmFactory.class)
.to(EntityManager.class)
.in(RequestScoped.class);
}
});
}


with the factory class being

public class EmFactory implements Factory<EntityManager> {

private static final String PERSISTENCE_UNIT = "unit";

private EntityManagerFactory emf;
private CloseableService closeableService;

@Inject
public EmFactory(@Named(PERSISTENCE_UNIT) String persistenceUnit,
CloseableService closeableService) {
emf = Persistence.createEntityManagerFactory(persistenceUnit);
this.closeableService = closeableService;
}

@Override
public EntityManager provide() {
final EntityManager entityManager = emf.createEntityManager();
closeableService.add(new Closeable() {

@Override
public void close() throws IOException {
if(entityManager.isOpen()) {
entityManager.close();
}
}
});
return entityManager;
}

@Override
public void dispose(EntityManager entityManager) {
if(entityManager.isOpen()) {
entityManager.close();
}
}
}


this works but then for each request i get a warning in the logs about an EntityManager being already registered:

HHH000436: Entity manager factory name (unit) is already registered. \
If entity manager will be clustered or passivated, specify a unique \
value for property 'hibernate.ejb.entitymanager_factory_name'


What am I doing wrong? What is the proper way to initialize an EntityManager in a jersey-2 / hk2 application?

Answer

One option is to instead of creating a new EntityManagerFactory in the EMFactory (which is in a request scope), you could create a singleton factory for the EntityManagerFactory, then just inject the EntityManagerFactory into the 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;
    }
    ...
}

Haven't tested this exact implementation out, but it should look something like this. I've used this pattern 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);
    }
});
Comments