Ok, finally I've solved adding injection of generic DAO (with session and transaction) to a genericAction. This works for JSONResults & jsp's with lazy hibernate beans.
Thanks for contributions to "bmorris591" and "Roman C" (I don't want, even need, all this plugin).
I leave my examples, I hope I don't forget anything...
Interceptor configuration (struts.xml fragment):
<package name="lmp" extends="struts-default,json-default">
<interceptors>
<interceptor name="login" class="util.LoginInterceptor"/>
<interceptor name="hibernateSessionTransInjector" class="util.HibernateSessionTransInjectorInterceptor"/>
<interceptor-stack name="loggingStack">
<interceptor-ref name="login" />
<interceptor-ref name="defaultStack" />
<interceptor-ref name="hibernateSessionTransInjector"/>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="loggingStack"/>
<global-results>
<result name="login" type="redirectAction">login</result>
</global-results>
</package>
<package name="myAction" extends="lmp">
<action name="myAction" class="com.lmp.MyAction">
<result name="json" type="json">
<param name="ignoreHierarchy">false</param>
</result>
<result name="*">/jsp/myAction.jsp</result>
</action>
</package>
Interceptor implementation:
package util;
import org.apache.log4j.Logger;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import util.hibernate.HibernateUtil;
import com.lm.action.ActionsConstants;
import com.lm.action.user.Constants;
import com.lm.dao.DAO;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
public class HibernateSessionTransInjectorInterceptor implements Interceptor, Constants, ActionsConstants {
private static final long serialVersionUID = -8734958511612355789L;
private static SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
private transient Logger log = Logger.getLogger(HibernateSessionTransInjectorInterceptor.class);
@Override
public void destroy() {
}
@Override
public void init() {
}
@Override
public String intercept(final ActionInvocation invocation) throws Exception {
String res=null;
DAO dao=null;
try {
Session s=sessionFactory.openSession();
dao = new DAO(s);
dao.beginTransaction();
**invocation.getStack().setValue("dao", dao, true);**
res=invocation.invoke();
boolean rollback=(Boolean)invocation.getStack().findValue("rollbackTransaction", Boolean.class);
if (rollback)
dao.rollBackTransaction();
if (!dao.getT().wasRolledBack())
dao.commitTransaction();
} catch (Throwable t2) {
log.error(t2,t2);
if (dao!=null)
try {
dao.rollBackTransaction();
} catch (Throwable t3) {
log.error(t3,t3);
}
} finally {
if (dao!=null)
try {
dao.finallyClose();
} catch (Throwable t) {
log.error(t,t);
}
}
return res;
}
}
UserDAO example:
public class UserDAO extends DAO {
[...]
public UserDAO(Session s) {
super(s);
}
[...]
}
GenericDAO example:
public class DAO {
protected static final transient Logger log = Logger.getLogger(DAO.class);
public static SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
public Session s = null;
public Transaction t = null;
public DAO(Session s) {
this.s=s;
}
public void beginTransaction(Transaction t) {
this.t=t;
}
private int exceptionErr=0;
public void beginTransaction() {
try {
t=s.beginTransaction();
} catch (Throwable t) {
log.error(t,t);
}
}
public void rollBackTransaction() {
if (t!=null && t.isActive())
t.rollback();
}
public void commitTransaction() {
if (t!=null && t.isActive())
t.commit();
}
public void finallyClose() {
if (t!=null && t.isActive())
t.rollback();
if (s!=null && s.isOpen())
s.close();
}
public Session getS() {
return s;
}
public void setS(Session s) {
this.s = s;
}
public Transaction getT() {
return t;
}
public void setT(Transaction t) {
this.t = t;
}
}
GenericAction:
public class GenericAction extends ActionSupport {
private DAO dao=null; //Interceptor injects here
public GenericAction() {
}
...
@JSON(deserialize=false, serialize=false)
public DAO getDao() {
return dao;
}
@JSON(deserialize=false, serialize=false)
public void setDao(DAO dao) {
this.dao = dao;
}
}
MyAction:
public class MyAction extends GenericAction {
public MyAction() {
}
@Override
public String execute() throws Exception {
super.execute();
UserDAO userDAO=new UserDAO(getDao().getS());
OtherDAO otherDAO=new OtherDAO(getDao().getS());
userDAO.loadUsers(...);
return SUCCESS;
}
}