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..!