Generic CRUD Components with Java EE 5 📎
public interface CrudService<K,T> {
public T create(T t);
public T find(K id);
public void delete(T t);
public T update(T t);
//finders...
}
It is a plain interface without the @Remote annotation (a simple POJI).
The CRUD-logic is realized in a stateless session bean which provides the type of the primary key, as well as of the persistent entity:
@Stateless
@Remote(CrudService.class)
public class CrudServiceBean implements CrudService<Integer,Customer> {
@PersistenceContext
private EntityManager em;
public Customer create(Customer t) {
this.em.persist(t);
return t;
//remaining methods
}
In this particular case, the interface is defined only once and realized by specific EJBs (which have to be implemented and deployed for each JPA-entity)
However a type-unsafe variation can be even more flexible.The usage of the java.io.Serializable (or Object), instead of a generic type allows the deployment of only one EJB, which is able then to manage all JPA-entities.
public interface GenericCrudService {
public Serializable create(Serializable t);
public Serializable find(Serializable id,Class type);
public void delete(Serializable t);
public Serializable update(Serializable t);
public Collection<Serializable> findByNamedQuery(String queryName);
public Collection<Serializable> findByNamedQuery(String queryName,int resultLimit);
}
The implementation of the interface is straightforward:
@Stateless
@Remote(GenericCrudService.class)
public class GenericCrudServiceBean implements GenericCrudService {
@PersistenceContext
private EntityManager em;
public Serializable create(Serializable t) {
this.em.persist(t);
return t;
}
@SuppressWarnings("unchecked")
public Serializable find(Serializable id, Class type) {
return (Serializable) this.em.find(type, id);
}
public void delete(Serializable t) {
t = this.em.merge(t);
this.em.remove(t);
}
public Serializable update(Serializable t) {
return this.em.merge(t);
}
public Collection<Serializable> findByNamedQuery(String queryName) {
return this.em.createNamedQuery(queryName).getResultList();
}
public Collection<Serializable> findByNamedQuery(String queryName, int resultLimit) {
return this.em.createNamedQuery(queryName).setMaxResults(resultLimit).getResultList();
}
EJB 3 are even efficient enough for the implementation of really simple use cases. This change a lot, comparing it to the J2EE/EJB 2.0 spec.
The whole example is available in p4j5.