import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.util.logging.Logger;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.daz.DBException;
import org.daz.SetRollbackException;
import org.daz.HibernateUtil;
/**
* http://stackoverflow.com/questions/2587702
*
* @author mohammad_abdullah
*/
public class ServiceProxy implements InvocationHandler {
private Object object;
private Logger logger = Logger.getLogger(this.getClass().getSimpleName());
private static final String SESSION_FIELD = "session";
private ServiceProxy(Object object) {
this.object = object;
}
public static Object newInstance(Object object) {
return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), new ServiceProxy(object));
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
Session session = null;
boolean joined = false;
try {
if (Modifier.isPublic(method.getModifiers())) {
session = HibernateUtil.getSessionFactory().getCurrentSession();
Field sessionField = object.getClass().getSuperclass().getDeclaredField(SESSION_FIELD);
if (sessionField == null)
throw new RuntimeException("Service Implementation should have field named: \"" + SESSION_FIELD + "\".");
sessionField.setAccessible(true);
sessionField.set(object, session);
if (session.getTransaction().isActive()) {
joined = true;
logger.info("Using Already Active transaction");
} else {
logger.info("Transaction Began");
session.beginTransaction();
}
result = method.invoke(object, args);
if (!joined) {
session.getTransaction().commit();
logger.info("Transaction Commited");
}
} else {
result = method.invoke(object, args);
}
return result;
} catch (InvocationTargetException _ex) {
Throwable cause = _ex.getCause();
logger.severe("Caller Exception: " + cause);
if (!joined && session != null && session.getTransaction().isActive())
session.getTransaction().rollback();
if (cause instanceof HibernateException) {
logger.severe("Hibernate Error. Rollbacked Back.");
throw new DBException(cause.getCause().getMessage());
/*SetRollbackException is a user-defined exception that can be thrown from Business method to mark transaction for rollback */
} else if (cause instanceof SetRollbackException) {
logger.severe("Transaction marked for Rollback. Rollbacked Back.");
return result;
} else {
logger.severe("Error in Business Method : " + method + ". Rollbacked Back.");
throw cause;
}
} catch (Exception ex) {
logger.severe("Error in Proxy code :" + ex);
if (!joined && session != null && session.getTransaction().isActive())
session.getTransaction().rollback();
if (ex instanceof HibernateException)
throw new DBException(ex.getCause().getMessage());
throw ex;
}
}
}
28 June 2012
Using Dynamic Proxies to centralize Transaction Management (2)
I've talked about Using Dynamic Proxies to centralize JPA code In an earlier time, and here's a refined version of the Proxy class:
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment