Post 1: http://m-hewedy.blogspot.com/2010/04/using-dynamic-proxies-to-centralize-jpa.html
Post 2: http://m-hewedy.blogspot.com/2012/06/using-dynamic-proxies-to-centralize.html
The following code is the more mature (
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.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import org.hibernate.HibernateException;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
/**
* http://stackoverflow.com/questions/2587702
*
* @author mohammad_abdullah
*/
public class ServiceProxy implements InvocationHandler {
private final Object object;
private final Logger logger = Logger.getLogger(this.getClass().getSimpleName());
private static final String SESSION_FACTORY_FIELD = "sessionFactory";
public static final Map ACTIVE_TRANSACTIONS = new HashMap();
private ServiceProxy(final Object object) {
this.object = object;
}
public static Object newInstance(final Object object) {
return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), new ServiceProxy(object));
}
@Override
public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
Object result = null;
SessionFactory sessionFactory = null;
boolean isActive = false;
try {
if (Modifier.isPublic(method.getModifiers())) {
sessionFactory = HibernateUtil.getSessionFactory();
final Field sessionField = this.object.getClass().getSuperclass().getDeclaredField(SESSION_FACTORY_FIELD);
if (sessionField == null) {
throw new UPSAdminException("Service Implementation should have field named: \"" + SESSION_FACTORY_FIELD + "\".");
}
sessionField.setAccessible(true);
sessionField.set(this.object, sessionFactory);
isActive = sessionFactory.getCurrentSession().getTransaction().isActive();
if (!isActive) {
this.logger.info("Tnx begin." + " {Method: " + method.getName() + "} {Thread: " + this.threadId() + "}");
final Transaction newTnx = sessionFactory.getCurrentSession().beginTransaction();
ACTIVE_TRANSACTIONS.put(this.threadId(), newTnx);
} else {
this.logger.info("Joing Active tnx" + " {Method: " + method.getName() + "} {Thread: " + this.threadId() + "}");
}
result = method.invoke(this.object, args);
if (!isActive) {
ACTIVE_TRANSACTIONS.remove(this.threadId()).commit();
this.logger.info("Tnx commit" + " {Method: " + method.getName() + "} {Thread: " + this.threadId() + "}");
}
} else {
result = method.invoke(this.object, args);
}
return result;
} catch (final InvocationTargetException _ex) {
final Throwable cause = _ex.getCause();
this.logger.severe("Caller Exept: " + cause + " {Method: " + method.getName() + "} {Thread: " + this.threadId() + "}");
if (!isActive && (sessionFactory.getCurrentSession() != null) && sessionFactory.getCurrentSession().getTransaction().isActive()) {
ACTIVE_TRANSACTIONS.remove(this.threadId()).rollback();
}
if (cause instanceof HibernateException) {
this.logger.severe("Hibernate Error. Rollback. {Method: " + method.getName() + "} {Thread: " + this.threadId() + "}");
throw new DBException(cause.getCause().getMessage());
} else if (cause instanceof SetRollbackException) {
this.logger.severe("Tnx marked rollback. {Method: " + method.getName() + "} {Thread: " + this.threadId() + "}");
return result;
} else {
this.logger.severe("Error in Business Method : " + method + ". Rollbacked Back." + " Thread: " + this.threadId() + "}");
throw cause;
}
} catch (final Exception ex) {
this.logger.severe("Error in Proxy code :" + ex + " {Mehtod :" + method + "} {Thread: " + this.threadId() + "}");
if (!isActive && (sessionFactory.getCurrentSession() != null) && sessionFactory.getCurrentSession().getTransaction().isActive()) {
ACTIVE_TRANSACTIONS.remove(this.threadId()).rollback();
}
if (ex instanceof HibernateException) {
throw new DBException(ex.getCause().getMessage());
}
throw ex;
}
}
private long threadId() {
return Thread.currentThread().getId();
}
}
No comments:
Post a Comment