-->
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.  [ 8 posts ] 
Author Message
 Post subject: Open Session in View and Struts
PostPosted: Wed May 05, 2004 1:37 pm 
Beginner
Beginner

Joined: Mon Dec 29, 2003 12:49 pm
Posts: 41
Location: Boston, MA
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]

_________________
Brian R. Wainwright
Systems Developer
WGBH Educational Foundation

"WGBH Boston informs, inspires, and entertains millions through public broadcasting, the Web, and educational multimedia, and access services for people with disabilities."


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 05, 2004 3:03 pm 
CGLIB Developer
CGLIB Developer

Joined: Thu Aug 28, 2003 1:44 pm
Posts: 1217
Location: Vilnius, Lithuania
I do not see your "doFilter" in stack trace too, probably filter mapping in web.xml is wrong, does it log "*IN DOFILTER FILTER*" ?


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 05, 2004 3:15 pm 
Beginner
Beginner

Joined: Mon Dec 29, 2003 12:49 pm
Posts: 41
Location: Boston, MA
Thanks for the reply baliukas. Here's some more info about this.

"IN DOFILTER FILTER" does get logged, but only once. In other words, it only gets logged the first time a user hits the site. It doesn't get logged for any other requests, nor does the session get closed as I thought it would. So perhaps I need to change my web.xml file... from
Code:
<!-- the ScapeFilter - it handles Hibernate session openign and closing -->
   <filter>
      <filter-name>ScapeFilter</filter-name>
      <filter-class>org.wgbh.scape.ScapeFilter</filter-class>
   </filter>
   
   <filter-mapping>
      <filter-name>ScapeFilter</filter-name>
      <url-pattern>*.jsp</url-pattern>
   </filter-mapping>


to...
Code:
<!-- the ScapeFilter - it handles Hibernate session openign and closing -->
   <filter>
      <filter-name>ScapeFilter</filter-name>
      <filter-class>org.wgbh.scape.ScapeFilter</filter-class>
   </filter>
   
   <filter-mapping>
      <filter-name>ScapeFilter</filter-name>
      <url-pattern>*.do</url-pattern>
   </filter-mapping>


Changing the url-pattern from *.jsp to *.do - which is what's mapped to my action servlet....

Does that make sense? The initial request to the site is a result of a redirect on an index.jsp page. This could account for it getting logged that one time and not others. Thoughts?

Thanks!

_________________
Brian R. Wainwright
Systems Developer
WGBH Educational Foundation

"WGBH Boston informs, inspires, and entertains millions through public broadcasting, the Web, and educational multimedia, and access services for people with disabilities."


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 05, 2004 3:26 pm 
Beginner
Beginner

Joined: Mon Dec 29, 2003 12:49 pm
Posts: 41
Location: Boston, MA
That was indeed the problem. Chanign the url-pattern to *.do fixed that issue, but now I have a new issue - I get a new exception telling me that a collection is dirty. This doesn't make sense.... The collection hasn't been modified, it is just attempting to get lazy initialized via proxy...

Code:
org.wgbh.scape.exception.ScapeException: Unable to associate object with new session: reassociated object has dirty collection reference
        at org.wgbh.scape.ScapeFilter.reassociateWithSession(ScapeFilter.java:81)
        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.wgbh.scape.ScapeFilter.doFilter(ScapeFilter.java:101)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:213)
        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)


Here's the reassociatewithSession code from the Filter class.

Code:
   public static void reassociateWithSession(ScapeObject object) throws ScapeException
   {
      try
      {
         Session s = getCurrentDBSession();
         s.lock(object, LockMode.NONE);
         
      }
      catch(HibernateException he)
      {
         throw new ScapeException("Unable to associate object with new session: " + he.getMessage());
      }
   }


ScapeObject is an interface that all domain objects implement. Should I put in an isDirty() check and refresh the object? What could account for hibernate thinking the collection is dirty if it hasn't even ben fetched from the DB yet?

Thanks!

_________________
Brian R. Wainwright
Systems Developer
WGBH Educational Foundation

"WGBH Boston informs, inspires, and entertains millions through public broadcasting, the Web, and educational multimedia, and access services for people with disabilities."


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 05, 2004 3:40 pm 
CGLIB Developer
CGLIB Developer

Joined: Thu Aug 28, 2003 1:44 pm
Posts: 1217
Location: Vilnius, Lithuania
try to flush session before close and do not forget to abort/commit connection.


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 05, 2004 3:53 pm 
Beginner
Beginner

Joined: Mon Dec 29, 2003 12:49 pm
Posts: 41
Location: Boston, MA
Okay. That makes sense. Let me ask this. When doing queries I use the following code...

Code:
      List h_results = null;
      try
      {
         h_results = session.find(query.getQueryAsString());
      }
      catch(HibernateException e)
      {
         throw new ScapeException(e.getMessage());
      }
      return h_results;


And when doing updates/saves/deletes I use this...
Code:
   public void save(ScapeObject object) throws ScapeException
   {
      Session session = null;
      Transaction trans = null;
      
      
      try
      {
         logger.debug("SAVING:" + object.toString());
         session = getSession();
         trans = session.beginTransaction();
         session.saveOrUpdate(object);
         trans.commit();
         
      }
      catch(HibernateException he)
      {
         throw new ScapeException("Unable to save object: " + he.getMessage());

      }
}


So should I be using the Transaction API in both cases and calling commit()? Or can I set the flush mode to "AUTO" and after it executes queries, it will flush automatically? Or should I just flush the session right before it gets closed regardless? What are the ramifications of flushing a session that's already been flushed?

--BW

_________________
Brian R. Wainwright
Systems Developer
WGBH Educational Foundation

"WGBH Boston informs, inspires, and entertains millions through public broadcasting, the Web, and educational multimedia, and access services for people with disabilities."


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 05, 2004 4:48 pm 
Beginner
Beginner

Joined: Mon Dec 29, 2003 12:49 pm
Posts: 41
Location: Boston, MA
So what i did is call session.flush() right before I call session.close() and everything works fine. Thanks for all your help.

_________________
Brian R. Wainwright
Systems Developer
WGBH Educational Foundation

"WGBH Boston informs, inspires, and entertains millions through public broadcasting, the Web, and educational multimedia, and access services for people with disabilities."


Top
 Profile  
 
 Post subject:
PostPosted: Thu May 06, 2004 12:58 am 
CGLIB Developer
CGLIB Developer

Joined: Thu Aug 28, 2003 1:44 pm
Posts: 1217
Location: Vilnius, Lithuania
call session.connection().commit() in filter after doFilter() ( if session is open ),
it is dangerous to return uncommited connections to pool, next request will see "old" data (if reads are repeatable) and some concurency control algorythms use read locks, it can cause deadlock.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 8 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:
cron
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.