Question

I'm trying to implement a Hibernate session/transaction interceptor to avoid LazyInitializationException on json results in Struts2, but I get this exception anyway:

245968 [http-8080-7] ERROR util.HibernateEndTransInterceptor  - org.apache.struts2.json.JSONException: org.apache.struts2.json.JSONException: org.apache.struts2.json.JSONException: org.apache.struts2.json.JSONException: java.lang.reflect.InvocationTargetException
org.apache.struts2.json.JSONException: org.apache.struts2.json.JSONException: org.apache.struts2.json.JSONException: org.apache.struts2.json.JSONException: java.lang.reflect.InvocationTargetException
    at org.apache.struts2.json.JSONWriter.bean(JSONWriter.java:238)
    at org.apache.struts2.json.JSONWriter.processCustom(JSONWriter.java:171)
    at org.apache.struts2.json.JSONWriter.process(JSONWriter.java:161)
    at org.apache.struts2.json.JSONWriter.value(JSONWriter.java:127)
    at org.apache.struts2.json.JSONWriter.write(JSONWriter.java:95)
    at org.apache.struts2.json.JSONUtil.serialize(JSONUtil.java:116)
    at org.apache.struts2.json.JSONResult.createJSONString(JSONResult.java:196)
    at org.apache.struts2.json.JSONResult.execute(JSONResult.java:170)
    at com.opensymphony.xwork2.DefaultActionInvocation.executeResult(DefaultActionInvocation.java:374)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:278)
    at util.HibernateEndTransInterceptor.intercept(HibernateEndTransInterceptor.java:55)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    at org.apache.struts2.interceptor.debugging.DebuggingInterceptor.intercept(DebuggingInterceptor.java:256)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    at com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:176)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    at com.opensymphony.xwork2.validator.ValidationInterceptor.doIntercept(ValidationInterceptor.java:265)
    at org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:68)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    at com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.intercept(ConversionErrorInterceptor.java:138)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:236)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:236)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    at com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:190)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    at org.apache.struts2.interceptor.MultiselectInterceptor.intercept(MultiselectInterceptor.java:75)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    at org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:90)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    at org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:243)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    at com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor.intercept(ModelDrivenInterceptor.java:100)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    at com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor.intercept(ScopedModelDrivenInterceptor.java:141)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    at com.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:145)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    at com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:171)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    at com.opensymphony.xwork2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:176)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    at org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    at com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:192)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    at com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:187)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    at util.HibernateBeginTransInterceptor.intercept(HibernateBeginTransInterceptor.java:32)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    at util.LoginInterceptor.intercept(LoginInterceptor.java:36)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
    at org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:54)
    at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:511)
    at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)
    at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:91)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
    at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:831)
    at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:652)
    at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1203)
    at java.lang.Thread.run(Thread.java:722)
Caused by: org.apache.struts2.json.JSONException: org.apache.struts2.json.JSONException: org.apache.struts2.json.JSONException: java.lang.reflect.InvocationTargetException
    at org.apache.struts2.json.JSONWriter.bean(JSONWriter.java:238)
    at org.apache.struts2.json.JSONWriter.processCustom(JSONWriter.java:171)
    at org.apache.struts2.json.JSONWriter.process(JSONWriter.java:161)
    at org.apache.struts2.json.JSONWriter.value(JSONWriter.java:127)
    at org.apache.struts2.json.JSONWriter.add(JSONWriter.java:363)
    at org.apache.struts2.json.JSONWriter.bean(JSONWriter.java:223)
    ... 73 more
Caused by: org.apache.struts2.json.JSONException: org.apache.struts2.json.JSONException: java.lang.reflect.InvocationTargetException
    at org.apache.struts2.json.JSONWriter.bean(JSONWriter.java:238)
    at org.apache.struts2.json.JSONWriter.processCustom(JSONWriter.java:171)
    at org.apache.struts2.json.JSONWriter.process(JSONWriter.java:161)
    at org.apache.struts2.json.JSONWriter.value(JSONWriter.java:127)
    at org.apache.struts2.json.JSONWriter.add(JSONWriter.java:363)
    at org.apache.struts2.json.JSONWriter.bean(JSONWriter.java:223)
    ... 78 more
Caused by: org.apache.struts2.json.JSONException: java.lang.reflect.InvocationTargetException
    at org.apache.struts2.json.JSONWriter.bean(JSONWriter.java:238)
    at org.apache.struts2.json.JSONWriter.processCustom(JSONWriter.java:171)
    at org.apache.struts2.json.JSONWriter.process(JSONWriter.java:161)
    at org.apache.struts2.json.JSONWriter.value(JSONWriter.java:127)
    at org.apache.struts2.json.JSONWriter.add(JSONWriter.java:363)
    at org.apache.struts2.json.JSONWriter.bean(JSONWriter.java:223)
    ... 83 more
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.apache.struts2.json.JSONWriter.bean(JSONWriter.java:218)
    ... 88 more
Caused by: org.hibernate.LazyInitializationException: could not initialize proxy - no Session
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:165)
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:272)
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185)
    at com.lm.model.common.Language_$$_javassist_0.getName(Language_$$_javassist_0.java)
    ... 93 more

My Interceptor looks like this:

package util;

import java.util.Map;

import org.apache.log4j.Logger;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

import util.hibernate.HibernateUtil;

import com.lm.action.ActionsConstants;
import com.lm.action.user.Constants;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;

public class HibernateEndTransInterceptor implements Interceptor, Constants, ActionsConstants {


    private static final long serialVersionUID = -8734958511612355789L;

    private static SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
    private transient Logger log = Logger.getLogger(HibernateEndTransInterceptor.class);
    private Session s=null;
    private Transaction t=null;

    @Override
    public void destroy() {
    }

    @Override
    public void init() {
    }

    @Override
    public String intercept(final ActionInvocation invocation) throws Exception {
        /*invocation.addPreResultListener(new PreResultListener() {

            @Override
            public void beforeResult(ActionInvocation arg0, String arg1) {
                Map<String, ResultConfig> resultsMap = invocation.getProxy().getConfig().getResults();
                //ResultConfig finalResultConfig = resultsMap.get(resultCode);

            }
        });*/


        Map<String,Object> strutsSession = invocation.getInvocationContext().getSession();
        String res=null;
        try {
            s=sessionFactory.openSession();
            t = s.beginTransaction();
            strutsSession.put("hibernateSession", s);
            strutsSession.put("hibernateTransaction", t);
            res=invocation.invoke();
            t.commit();
        } catch (Throwable t2) {
            log.error(t2,t2);
            try {
                t.rollback();
            } catch (Throwable t3) {
                log.error(t3,t3);
            }
        } finally {
            try {
                s.close();
            } catch (Throwable t) {
                log.error(t,t);
            }
            strutsSession.remove("hibernateSession");
            strutsSession.remove("hibernateTransaction");
        }
        return res;
    }

}

This is not working, I'm getting LazyInitializationException even before trans.commit() and session.close();

Was it helpful?

Solution 2

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;
    }
}

OTHER TIPS

Do not reimplement the weel. If you need to implement the open session in view concept then use Hibernate Full Plugin. If you want to fix the LazyInitializationException put FetchType.EAGER on the collections.

If this is a Struts2 interceptor this is absolutely not the way to implement it.

An application has a single instance of the interceptor for all requests so one request is setting the variable in the intercept method then another is coming in and resetting them while the first is still processing. The first request then comes back on calls session.close() on the second request's session.

Your interceptor should look more like this:

@Override
public String intercept(final ActionInvocation invocation) throws Exception {
    final Map<String, Object> strutsSession = invocation.getInvocationContext().getSession();
    String res = null;
    Session s = null;
    Transaction t = null;
    try {
        s = sessionFactory.openSession();
        t = s.beginTransaction();
        strutsSession.put("hibernateSession", s);
        strutsSession.put("hibernateTransaction", t);
        res = invocation.invoke();
        t.commit();
    } catch (Throwable t2) {
        log.error(t2, t2);
        t.rollback();
    } finally {
        s.close();
        strutsSession.remove("hibernateSession");
        strutsSession.remove("hibernateTransaction");
    }
    return res;
}

Notice all variables are local unless you want them to be shared across requests.

Also, it's best practice to extend AbstractInterceptor so that you do not have all the empty methods that you have.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top