/*_########################################################################## _## _## Copyright (C) 2013 Kaito Yamada _## _########################################################################## */ package com.github.kaitoy.sneo.giane.interceptor; import java.lang.reflect.Field; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.EntityTransaction; import javax.persistence.Persistence; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.github.kaitoy.sneo.giane.model.dao.impl.EntityManagerInjectee; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.interceptor.AbstractInterceptor; import com.opensymphony.xwork2.interceptor.PreResultListener; public class EntityManagerInjectionInterceptor extends AbstractInterceptor { /** * */ private static final long serialVersionUID = 4062045728313229561L; private static final Logger logger = LoggerFactory.getLogger( EntityManagerInjectionInterceptor.class ); private static final EntityManagerFactory entityManagerFactory; static { try { entityManagerFactory = Persistence.createEntityManagerFactory("hibernate-h2-persistenceUnit"); } catch (Exception e) { logger.error("Initial EntityManagerFactory creation failed: " + e); throw new ExceptionInInitializerError(e); } } @Override public String intercept(ActionInvocation invocation) throws Exception { Object action = invocation.getAction(); EntityManager em = null; EntityTransaction tx = null; try { for (Class<?> cls = action.getClass(); cls != null; cls = cls.getSuperclass()) { if (cls.isAssignableFrom(ActionSupport.class)) { break; } for (Field field: cls.getDeclaredFields()) { field.setAccessible(true); Object fieldObj = field.get(action); if (!(fieldObj instanceof EntityManagerInjectee)) { continue; } if (em == null) { em = entityManagerFactory.createEntityManager(); } EntityManagerInjectee injectee = (EntityManagerInjectee)fieldObj; injectee.setEntityManager(em); } } if (em != null) { tx = em.getTransaction(); tx.begin(); } invocation.addPreResultListener(new Committer(tx)); String result = invocation.invoke(); // If commit here and fail, there is no way to change the action result to an error. // So, commits are done in Committer which is a PreResultListener. // // if (tx != null && tx.isActive()) { // tx.commit(); // } return result; } catch (Exception e) { if (tx != null && tx.isActive()) { tx.rollback(); } throw e; } finally { if (em != null && em.isOpen()) { em.close(); } } } private static class Committer implements PreResultListener { private final EntityTransaction tx; private Committer(EntityTransaction tx) { this.tx = tx; } public void beforeResult(ActionInvocation invocation, String resultCode) { if (tx != null && tx.isActive()) { tx.commit(); } } } }