4 Replies Latest reply on Apr 3, 2008 6:32 AM by ericml

    Hibernate Open Session In View (in Portlet)

    ericml

      Hey. I'm using JBoss AS 4.2.2 GA with Portal 2.6.4 and running into problems with accessing objects in the view:

      "Caused by: org.hibernate.LazyInitializationException: could not initialize proxy - no Session"

      I am using the HibernateService deployed as HAR to retrieve objects in the processAction-Method of the GenericPortlet. The configuration of the Service is as follows (jboss-service.xml):

      <server>
       <mbean code="org.jboss.hibernate.jmx.Hibernate"
       name="ebal:name=SessionFactory">
       <attribute name="DatasourceName">java:/PortalDS</attribute>
       <attribute name="Dialect">
       org.hibernate.dialect.MySQLDialect
       </attribute>
       <attribute name="SessionFactoryName">
       java:/hibernate/SessionFactory
       </attribute>
       <attribute name="Hbm2ddlAuto">update</attribute>
       <attribute name="ShowSqlEnabled">true</attribute>
       <attribute name="ScanForMappingsEnabled">true</attribute>
       </mbean>
      </server>
      


      The service uses the standard PortalDS which is bound to a transaction:

      <datasources>
       <local-tx-datasource>
       <jndi-name>PortalDS</jndi-name>
       <connection-url>jdbc:mysql://localhost:3306/jbossportal?useServerPrepStmts=false</connection-url>
       <driver-class>org.gjt.mm.mysql.Driver</driver-class>
       <user-name></user-name>
       <password></password>
       </local-tx-datasource>
      </datasources>
      


      In the init()-Method of my Portlet I am retrieving the HibernateService:
      public void init(javax.portlet.PortletConfig config)
       throws PortletException {
       super.init(config);
       try {
       InitialContext ctx = new InitialContext();
       sessionFactory = (SessionFactory) ctx
       .lookup("java:/hibernate/SessionFactory");
       } catch (NamingException e) {
       throw new PortletException(e.getMessage());
       }
       };
      


      and later in the processAction-Method I am retrieving some objects through sessionFactory.getCurrentSession() and store them in the PortalSession. This works fine for I retrieve the current session bound to the transaction. Btw, I have also included the transattribute in the jboss-portlet.xml:

      <portlet>
       <portlet-name>TestPortlet</portlet-name>
       <trans-attribute>Required</trans-attribute>
       </portlet>
      


      Everything works fine so far until I try to access properties from objects in the portletSession in the view (jsp, through jstl) which are proxied through hibernate (lazy initialized). The session is already closed in the view and so is the transaction. Normally I would set a HibernateSession filter in the web.xml and open/close the session before/after the request in a standard struts/spring mvc webapplication and have the session open in view but I fear this will not work in a portlet environment.

      I did browse through this forum and the web all the day but did not come to a conclusion how to achieve to hold the session/transaction open (and closed after the entire request).

      Is there anyone who was running into the same problem? Maybe I miss something substantial because I could not find any solution to this very common problem? Is there a way to span the transaction around the view-rendering as well? Every help or hints are appreciated!

      Regards,
      Eric

        • 1. Re: Hibernate Open Session In View (in Portlet)

          If you access an hibernate object outside the scope of the hibernate session where it has been loaded or saved, then before accessing a "lazy" property you have to open a new session and reattach the object to the new session. Check the hibernate session interface to do that - I believe it's update() ...

          • 2. Re: Hibernate Open Session In View (in Portlet)
            ericml

            Hi PMN, thanks for your suggestions, but I dont think that this would be the best way to handle it for several reasons:

            * Writing Java Code in a JSP is not recommended
            * Opening a new session and reattaching the objects in the JSP violates the MVC-pattern.
            * Performance will suffer a lot because you need additional selects for the reattachment

            Is there no way to span the transaction around the whole request?

            TXStart-->processAction-->...-->doView-->...-->(rendering JSP)-->TXEnd

            Is there no equivalent of an HibernateSessionRequestFilter (http://www.hibernate.org/43.html) for ServletApps in JBoss Portal?

            • 3. Re: Hibernate Open Session In View (in Portlet)

              I am not an expert of JSP 186 but I would rather commit the transaction in processAction to let changes seen by other portlets that may use another session.

              An alternative to share an object outside the current session, why don't you reload it in the doView() ? Using a second level cache has almost the same caching feature.

              • 4. Re: Hibernate Open Session In View (in Portlet)
                ericml

                The problem is, that you have an open session in the doView()-Method of the GenericPortlet. However, The strange thing is that the session is open as well in the jsp as my latest investigations have shown.

                These are the last lines of the doView-Method:

                rResponse.setContentType("text/html");
                PortletRequestDispatcher prd = getPortletContext().getRequestDispatcher("/WEB-INF/jsp/test/test.jsp");
                prd.include(rRequest, rResponse);
                


                The session is open before and after the call to prd.include(rRequest, rResponse);. It is open as well in the JSP (I have put the session into the httpsession and retrieved it in the jsp). I can even reattach objects to that session in the JSP and work with the lazy objects. If I dont reattach the objects the mentioned Lazy Initialization Exception (no session or session is closed) will be thrown.

                The question is: why do I have to reattach the objects although the session has not been closed?

                Keeping an closer eye on the "lazy" object I found out that the PersistentMap from Hibernate which is used instead of the "normal" collection has the session-attribute set to null. Is there anyone who can explain at which point this happened or how i can prevent this from happening?

                Maybe this has something to do with the bound JTA-Transaction?