Hey all,
Details:
Hibernate 2.1.3
MySQL 4.0.17
I'm using (rather attempting to use) the Open Session in View pattern with Struts and am having a problem - the doFilter() method is not closing the Hibernate session when the request completes. I'm new to Servlet Filters, so perhaps I have a basic misunderstanding about their lifecycle. Here's what I expected to happen:
1. User submits a form, thereby creating a request. doFilter is called
Code:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
logger.debug("\n\n**IN DOFILTER FILTER**\n\n");
if (sessionHolder.get() != null)
throw new IllegalStateException(
"A session is already associated with this thread! "
+ "Someone must have called getSession() outside of the context "
+ "of a servlet request.");
try
{
chain.doFilter(request, response);
}
finally
{
Session sess = (Session)sessionHolder.get();
if (sess != null)
{
sessionHolder.set(null);
try
{
logger.debug("\n\n***CLOSING HIBERNATE SESSION***\n\n");
sess.close();
}
catch (HibernateException ex)
{
throw new ServletException(ex);
}
}
}
}
2. The action associated with the form is called which gets a hibernate
session:
Code:
MyFilter.getCurrentDBSession();
which in the Filter class is:
Code:
public static Session getCurrentDBSession() throws ScapeException
{
logger.debug("\n\nGETTING SESSION in FILTER\n\n");
Session sess = (Session)sessionHolder.get();
try
{
if (sess == null)
{
sess = getSessionFactory().openSession();
sessionHolder.set(sess);
}
}
catch(HibernateException e)
{
throw new ScapeException("Unable to obtain hibernate session: " + e.getMessage());
}
logger.debug("\n\nSESSION = " + sess);
return sess;
}
All of the above happens as expected.
3. The Hibernate session does what it needs to do (execute a find) and the action method finishes and returns a new ActionForward...
Code:
public ActionForward find(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception
{
HttpSession session = request.getSession(false);
if(session == null)
{
//maybe do other stuff like set error message to sesion timeout
return mapping.findForward("scape.login");
}
ScapeSearchForm theForm = (ScapeSearchForm)form;
theForm.buildCriteria();
//build a query object
QueryBuilder qbldr = QueryBuilderFactory.getInstance().getQueryBuilder();
try
{
logger.debug("\n\n*****\n\nATTEMPTING TO QUERY\n\n*****");
//session.setAttribute("current-db-session", ScapeUtilImpl.getCurrentDBSession());
ArrayList results = new ArrayList(qbldr.executeQueryAsList(ScapeFilter.getCurrentDBSession(), query));
ArrayList firstPage = null;
if(results.iterator().hasNext() && results.size() >= 30)
{
//display first 30 results
firstPage = new ArrayList(results.subList(0, 30));
//set the current batch = size of the first batch
session.setAttribute("current-batch", new Integer(firstPage.size()));
ScapeFormHelper.getInstance().assignCollection("search-results", firstPage);
session.setAttribute("total-search-results", results);
}
else
{
session.setAttribute("current-batch", new Integer(results.size()));
ScapeFormHelper.getInstance().assignCollection("search-results", results);
}
session.setAttribute("result-size", new Integer(results.size()));
}
catch(ScapeException e)
{
reportError(session, e);
}
//change to resuls page based on action
return mapping.findForward("searchResults");
}
4. doFilter is called again (for the response) and the Hibernate session is closed.
#4 is not happening... so I'm getting lazy initialization errors or errors telling me I'm trying to associate a proxy with 2 open sessions (when using lock.(object, LockMode.NONE);
Here's the error...
Code:
May 5, 2004 12:09:47 PM net.sf.hibernate.LazyInitializationException <init>
SEVERE: Illegally attempted to associate a proxy with two open Sessions
net.sf.hibernate.LazyInitializationException: Illegally attempted to associate a proxy with two open Sessions
at net.sf.hibernate.proxy.LazyInitializer.setSession(LazyInitializer.java:152)
at net.sf.hibernate.impl.SessionImpl.reassociateProxy(SessionImpl.java:1009)
at net.sf.hibernate.impl.SessionImpl.reassociateIfUninitializedProxy(SessionImpl.java:958)
at net.sf.hibernate.impl.ProxyVisitor.processEntity(ProxyVisitor.java:21)
at net.sf.hibernate.impl.AbstractVisitor.processValue(AbstractVisitor.java:72)
at net.sf.hibernate.impl.AbstractVisitor.processValues(AbstractVisitor.java:36)
at net.sf.hibernate.impl.AbstractVisitor.process(AbstractVisitor.java:93)
at net.sf.hibernate.impl.SessionImpl.doUpdateMutable(SessionImpl.java:1448)
at net.sf.hibernate.impl.SessionImpl.doUpdate(SessionImpl.java:1462)
at net.sf.hibernate.impl.SessionImpl.update(SessionImpl.java:1347)
at org.wgbh.scape.ScapeFilter.reassociateWithSession(ScapeFilter.java:70)
at org.wgbh.scape.action.ScapeViewAction.viewFromResults(ScapeViewAction.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at org.apache.struts.actions.DispatchAction.dispatchMethod(DispatchAction.java:280)
at org.apache.struts.actions.DispatchAction.execute(DispatchAction.java:216)
at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:484)
at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:274)
at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1482)
at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:525)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:760)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:247)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:256)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
at org.apache.catalina.core.StandardContext.invoke(StandardContext.java:2417)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:180)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)
at org.apache.catalina.valves.ErrorDispatcherValve.invoke(ErrorDispatcherValve.java:171)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:172)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:174)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
at org.apache.coyote.tomcat4.CoyoteAdapter.service(CoyoteAdapter.java:193)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:781)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:549)
at org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:589)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:666)
at java.lang.Thread.run(Thread.java:552)
May 5, 2004 12:09:47 PM org.apache.struts.action.RequestProcessor processException
WARNING: Unhandled Exception thrown: class net.sf.hibernate.LazyInitializationException
What happens here:
Code:
qbldr.executeQueryAsList(ScapeFilter.getCurrentDBSession(), query));
Is
Code:
public List executeQueryAsList(Session session, ScapeQuery query) throws ScapeException
{
//UFOSet results = new UFOSet();
List h_results = null;
try
{
h_results = session.find(query.getQueryAsString());
//Iterator i = h_results.iterator();
//while(i.hasNext())
//{
//results.add(i.next());
//}
}
catch(HibernateException e)
{
throw new ScapeException(e.getMessage());
}
return h_results;
}
The ScapeQuery formats an HQL query based on form values... for example:
Code:
select party from org.wgbh.scape.domain.Human as party where party.firstName = 'Brian' order by party.lastName, party.firstName asc
The above works fine.
Can someone explain what is supposed to happen and how I might resolve the issue? I guess my problem is that doFilter isn't called on the response back from the server so the session doesn't get closed?
Thanks!
--Brian
[/list]