-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 
Author Message
 Post subject: LazyInitialisationExpception *within open session*
PostPosted: Sun Nov 26, 2006 10:32 am 
Newbie

Joined: Sun Nov 26, 2006 10:21 am
Posts: 2
Hi,

I am seeing a very strange issue. I am using the OpenSessionInView with long conversations filter. From my log statements (and normal behaviour of the application), this is working as expected.

However, in certain circumstances, I still get a LazyInitialisationException:

2006-11-26 13:57:42,036 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[localhost].[/ccapp].[jsp]] Servlet.service() for servlet jsp threw exception
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.ccapp.model.Charity.bookings, no session or session was closed

However, the logs show the session is open as expected, and then closed etc following this exception:

2006-11-26 13:57:42,043 INFO [HibernateJTAFilter] Trying to rollback database transaction after exception
2006-11-26 13:57:42,044 INFO [HibernateJTAFilter] Cleanup after exception!
2006-11-26 13:57:42,045 DEBUG [HibernateJTAFilter] Unbinding Session after exception
2006-11-26 13:57:42,045 DEBUG [HibernateJTAFilter] Closing Session after exception
2006-11-26 13:57:42,045 DEBUG [HibernateJTAFilter] Removing Session from HttpSession
2006-11-26 13:57:42,045 DEBUG [HibernateJTAFilter] <<< End of conversation

As I say, it's bizarre, because certain operations will leave this working fine - even accessing the same collection.

I am using JSF... not sure if that can have an impact?

This is my filter class:


Code:
package com.ccapp.hibernate;

import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.FlushMode;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.StaleObjectStateException;
import org.hibernate.context.ManagedSessionContext;

public class HibernateJTAFilter implements Filter
{

   private static Log log = LogFactory.getLog(HibernateJTAFilter.class);
   // private UserTransaction tx;
   private SessionFactory sf;

   public static final String HIBERNATE_SESSION_KEY = "hibernateSession";
   public static final String END_OF_CONVERSATION_FLAG = "endOfConversation";
   public static final String INVALIDATE_SESSION_FLAG = "invalidateSession";
   
   public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
         throws IOException, ServletException
   {

      org.hibernate.classic.Session currentSession;

      // Try to get a Hibernate Session from the HttpSession
      HttpSession httpSession = ((HttpServletRequest) request).getSession();
      Session disconnectedSession = (Session) httpSession.getAttribute(HIBERNATE_SESSION_KEY);
      
      try
      {
         // Start a new conversation or in the middle?
         if (disconnectedSession == null)
         {
            log.debug(">>> New conversation");
            currentSession = sf.openSession();
            log.debug("Opened session");
            currentSession.setFlushMode(FlushMode.MANUAL);
            log.debug("Set flush mode to never/manual");
         }
         else
         {
            log.debug("< Continuing conversation");
            currentSession = (org.hibernate.classic.Session) disconnectedSession;
         }

         log.debug("Binding the current Session");
         ManagedSessionContext.bind(currentSession);

         log.debug("Starting a database transaction");
         currentSession.beginTransaction();

         log.debug("Processing the event");
         chain.doFilter(request, response);



         // End or continue the long-running conversation?
         if (httpSession.getAttribute(END_OF_CONVERSATION_FLAG)!=null || request.getAttribute(END_OF_CONVERSATION_FLAG) != null
               || request.getParameter(END_OF_CONVERSATION_FLAG) != null)
         {
            log.debug("Flushing Session");
            currentSession.flush();

            log.debug("Committing the database transaction");
            currentSession.getTransaction().commit();

            log.debug("Unbinding Session after processing");
            currentSession = ManagedSessionContext.unbind(sf);
            
            log.debug("Closing the Session");
            currentSession.close();

            log.debug("Cleaning Session from HttpSession");
            httpSession.setAttribute(HIBERNATE_SESSION_KEY, null);
            httpSession.removeAttribute(END_OF_CONVERSATION_FLAG);
            
            log.debug("<<< End of conversation");
         }
         else
         {
            log.debug("Committing database transaction");
            currentSession.getTransaction().commit();

            log.debug("Storing Session in the HttpSession");
            httpSession.setAttribute(HIBERNATE_SESSION_KEY, currentSession);
            
            if (httpSession.getAttribute(INVALIDATE_SESSION_FLAG)!=null)
            {
               log.debug("Invalidating session");
               httpSession.invalidate();
               log.debug("<<< Session invalidated, conversation closed");
            }   
            else log.debug("> Returning to user in conversation");
         }
         
      }
      catch (StaleObjectStateException staleEx)
      {
         log.warn("This transaction modifies already changed data.. redirecting user to stale data notification page");
         // log.error("Your application will not work until you add compensation actions!");
         // Redirect to stale data error page

         try // Rollback only
         {
            if (sf.getCurrentSession().getTransaction().isActive()) //  & !sf.getCurrentSession().getTransaction().wasRolledBack()
            {
               log.info("Trying to rollback database transaction after exception");
               sf.getCurrentSession().getTransaction().rollback();
            }
         }
         catch (Throwable rbEx)
         {
            log.error("Could not rollback transaction after exception!", rbEx.fillInStackTrace());
         }
         finally
         {
            log.info("Cleanup after exception!");

            // Cleanup
            log.debug("Unbinding Session after exception");
            currentSession = ManagedSessionContext.unbind(sf);

            log.debug("Closing Session after exception");
            currentSession.close();

            log.debug("Removing Session from HttpSession");
            httpSession.setAttribute(HIBERNATE_SESSION_KEY, null);

            log.debug("<<< End of conversation");            
         }

         // Redirect to standard error page
         log.info("Final action post exception - redirect user to datachanged.jsf");
         HttpServletResponse httpResponse = (HttpServletResponse) response;
         httpResponse.sendRedirect("datachanged.jsf");
         
         
      }
      catch (Throwable ex)
      {
         log.error("Error:", ex);
         
         try // Rollback only
         {
            if (sf.getCurrentSession().getTransaction().isActive()) //  & !sf.getCurrentSession().getTransaction().wasRolledBack()
            {
               log.info("Trying to rollback database transaction after exception");
               sf.getCurrentSession().getTransaction().rollback();
            }
         }
         catch (Throwable rbEx)
         {
            log.error("Could not rollback transaction after exception!", rbEx.fillInStackTrace());
         }
         finally
         {
            log.info("Cleanup after exception!");

            // Cleanup
            log.debug("Unbinding Session after exception");
            currentSession = ManagedSessionContext.unbind(sf);

            log.debug("Closing Session after exception");
            currentSession.close();

            log.debug("Removing Session from HttpSession");
            httpSession.setAttribute(HIBERNATE_SESSION_KEY, null);

            log.debug("<<< End of conversation");            
         }

         // Redirect to standard error page
         log.info("Final action post exception - redirect user to standard_error.jsf");
         HttpServletResponse httpResponse = (HttpServletResponse) response;
         httpResponse.sendRedirect("standard_error.jsf");
      }
   }

   public void init(FilterConfig filterConfig) throws ServletException
   {
      log.debug("Initializing filter...");
      log.debug("Obtaining SessionFactory from HibernateUtil");
      sf = HibernateUtil.getSessionFactory();

      /*
       * try { // Get a JNDI context for lookup, re-use Hibernate
       * configuration Properties hibernateCfg =
       * HibernateUtil.getConfiguration().getProperties(); Context jndiContext =
       * NamingHelper.getInitialContext(NamingHelper.getJndiProperties(hibernateCfg));
       *  // Find out the name of the JTA UserTransaction in JNDI, re-use //
       * Hibernate cfg TransactionManagerLookup tmLookup =
       * TransactionManagerLookupFactory
       * .getTransactionManagerLookup(hibernateCfg); String userTxName =
       * tmLookup.getUserTransactionName();
       *
       * log.debug("Initializing filter, obtaining JTA UserTransaction"); tx =
       * (UserTransaction) jndiContext.lookup(userTxName);
       *  } catch (NamingException ex) { throw new ServletException("Couldn't
       * obtain JTA UserTransaction from JNDI" + ex); }
       */
   }

   public void destroy()
   {
   }

}



Any suggestions gratefully received..!


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 27, 2006 2:16 am 
Senior
Senior

Joined: Sat Jul 17, 2004 5:16 pm
Posts: 143
I believe if the session that was used to load the object is closed (e.g. if some other object has a lazy initialization exception), then you will get this exception (even if a new Session is open int he mean time). Thus, I believe if you are going to throw away your session you need to disassociate each object and lock them to the next session you open. This part gives you some decisions to make, and is a bit complicated. Maybe if you throw away your Session you can throw away all your objects and get them again...

Chris


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 27, 2006 6:27 am 
Newbie

Joined: Sun Nov 26, 2006 10:21 am
Posts: 2
Ah yes, this is indeed what is happening. Anytime I call a function that flushes and closes the session, if the next page view uses proxied objects still around, it will throw the exception.

I understand this now, but is there any best practice solution regarding what to do with your in-memory POJOs that have become detached due to a session flush?

Manually calling lock, refresh, merge or load for each one seems a rather heavy solution.. I imagine this is a common scenario, so I wonder if there is a more elegant pattern out there?


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.