I'm planning to write a business method for those non-container-managed clients such as JRX-RS resources.
@Stateless
public class PersistenceService {
public <R> R apply(final Function<EntityManager, R> function) {
return function.apply(entityManager);
}
@PersistenceContext
private transient EntityManager entityManager;
}
So that a JAX-RS root resource class uses it like this.
@RequestScoped
@Path("/entities")
public class MyEntites {
@GET
@Path("/{id: \\d+}")
public Response read(final long id) {
return Response.ok(service.apply(m -> {
m.find(MyEntity.class, id);
})).build();
}
@Inject
private transient PersistenceService service;
}
The problem is that how can I prevent clients invoking close()
on specified entity manager?
service.apply(m -> {
m.close();
return null;
});
You can create a wrapper around the original entity manager, which ensures that close()
is never called:
public class NoCloseEntityManager implements EntityManager {
private EntityManager wrapped;
public NoCloseEntityManager(EntityManager wrapped) {
this.wrapped = wrapped;
}
public void close() {
throw new UnsupportedOperationException("Don't call close()");
}
// all other methods from the interface call the wrapped manager:
public void persist(Object entity) {
wrapped.persist(entity);
}
...
}
That one can you use in your service:
@Stateless
public class PersistenceService {
@PersistenceContext
private transient EntityManager entityManager;
public <R> R apply(final Function<EntityManager, R> function) {
return function.apply(new NoCloseEntityManager(entityManager));
}
}
But I don't know if the effort is worse the result, as entityManager.close()
isn't called very often - if someone calls it, he will not use it by mistake...