Jersey + HK2 + Grizzly: Proper way to inject Entit

2020-02-26 00:46发布

问题:

I've managed to set up injection (into resource classes) of my own service classes in Jersey, HK2 and a plain GrizzlyServer. (Basically followed this example.)

I'm now curious what the best is to inject JPA EntityManagers into my resource classes? (I'm currently considering one request as one unit of work). One option that I'm currently exploring is to use a Factory<EntityManager> in the following way:

class MyEntityManagerFactory implements Factory<EntityManager> {

    EntityManagerFactory emf;

    public MyEntityManagerFactory() {
        emf = Persistence.createEntityManagerFactory("manager1");
    }

    @Override
    public void dispose(EntityManager em) {
        em.close();
    }

    @Override
    public EntityManager provide() {
        return emf.createEntityManager();
    }

}

and bind it as follows:

bindFactory(new MyEntityManagerFactory())
        .to(EntityManager.class)
        .in(RequestScoped.class);

The problem is that the dispose-method is never invoked.

My questions:

  1. Is this the right approach to injecting EntityManagers in Jersey+HK2?
  2. If so, how should I make sure my EntityManagers are closed properly?

(I'd rather not depend on heavy weight containers or an extra dependency-injection library just to cover this use case.)

回答1:

In place of Factory<T>.dispose(T), registering with the injectable CloseableService may do most of what you want. A Closeable adapter will be required. CloseableService closes() all registered resources upon exiting the request scope.

class MyEntityManagerFactory implements Factory<EntityManager> {
    private final CloseableService closeableService;
    EntityManagerFactory emf;

    @Inject
    public MyEntityManagerFactory(CloseableService closeableService) {
        this.closeableService = checkNotNull(closeableService);
        emf = Persistence.createEntityManagerFactory("manager1");
    }

    @Override
    public void dispose(EntityManager em) {
        em.close();
    }

    @Override
    public EntityManager provide() {
        final EntityManager em = emf.createEntityManager();
        closeableService.add(new Closeable() {
            public final void close() {
                em.close();
            }
        });
        return em;
    }
}