06 April 2010

Using Dynamic Proxies to centralize JPA code

I was working on some project that required me not to use an Application Server, hence I've chosen JPA to persist data, I had to use JPA in standalone application (actually it is a web application that intended to run in tomcat)

One solution is to use some lightweight container such as Spring instead of real Containers, but this project was so simple that i needn't to complex the Dev process (and introduce many jars ....)

I went with using Java Daynaic Proxy to centralize the code/control of the JPA; here's the code of the proxy:

import java.util.Set;
import java.util.logging.Logger;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.Query;
import com.forat.model.Student;
import com.forat.service.exceptions.StudentNotFoundException;
/**
* This class should be called through {@link DAOProxy} as it injects the {@link EntityManager} and other JPA staff
* and takes care of the transactions (commiting/rollbacking) , etc...
* @see DAOProxy
* @author mohammed
*/
public class OnlineFormServiceImpl implements OnlineFromService {
private Logger logger = Logger.getLogger(this.getClass().getSimpleName());
private EntityManager em;
public OnlineFormServiceImpl() {
}
public void setEntityManager(EntityManager em) {
this.em = em;
}
// the code has been minimized, the code that is responsalbe of working with JPA staff has moved to the proxy class
// we we do here just use the EntityManager (as if we were in a managed environment)
public void addStudent(Student student) {
em.persist(student);
}
// other interface methods goes here ...
}

The idea is to centralize the control of the persistence code, and this implementation is a basic implementation that may contains errors.
Also, this code my includes performance impact, as I used reflections to invoke service methods, but for sure its performance impact will be more less than of application servers!