Search code examples
jpaejbjax-rs

How can I prevent from a close method being invoked?


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;
});

Solution

  • 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...