Announcement Announcement Module
Collapse
No announcement yet.
Lazily-loaded Hibernate objects in SiteMesh templates? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Lazily-loaded Hibernate objects in SiteMesh templates?

    Hi folks,
    I've just moved a (complicated, very) custom tag, which uses lazily loaded objects, from the page body to a SiteMesh template. And now I get "failed to lazily initialize a collection of role: <removed>- no session or session was closed". The reason is simple, the lazy objects have a database connection within the page body, but not within the SiteMesh template.

    Here's the interesting bit. I've been using both the OpenSessionInViewFilter and OpenViewInSessionInterceptors, and neither works. I suspect that in both cases they're considering the session as done *before* the SiteMesh template is processed.

    The Interceptor I understand, as I see it 'within' Spring MVC, and thus before SiteMesh. I'm not so sure of the Filter, perhaps I'm making a schoolboy error? Why wouldn't the following web.xml work:

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http&#58;//java.sun.com/xml/ns/j2ee"
        xmlns&#58;xsi="http&#58;//www.w3.org/2001/XMLSchema-instance"
        xsi&#58;schemaLocation="http&#58;//java.sun.com/xml/ns/j2ee http&#58;//java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">
      <display-name>Swan Labs Enterprise Manager</display-name>
    
      <context-param>
        <param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
        <param-value>messages</param-value>
      </context-param>
    
      <filter>
        <filter-name>securityFilter</filter-name>
        <filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
        <init-param>
          <param-name>targetClass</param-name>
          <param-value>net.sf.acegisecurity.util.FilterChainProxy</param-value>
        </init-param>
      </filter>
    
      <filter>
        <filter-name>sitemeshFilter</filter-name>
        <filter-class>com.opensymphony.module.sitemesh.filter.PageFilter</filter-class>
      </filter>
    
      <filter>
        <filter-name>hibernateFilter</filter-name>
        <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
      </filter>
    
      <filter>
        <filter-name>exportFilter</filter-name>
        <filter-class>org.displaytag.filter.ResponseOverrideFilter</filter-class>
      </filter>
    
      <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring*.xml</param-value>
      </context-param>
    
      <filter-mapping>
        <filter-name>securityFilter</filter-name>
        <url-pattern>/*</url-pattern>
      </filter-mapping>
    
      <filter-mapping>
        <filter-name>sitemeshFilter</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
      </filter-mapping>
    
      <filter-mapping>
        <filter-name>hibernateFilter</filter-name>
        <url-pattern>*.html*</url-pattern>
      </filter-mapping>
    
      <filter-mapping>
        <filter-name>exportFilter</filter-name>
        <url-pattern>*.html</url-pattern>
      </filter-mapping>
    
      <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>
    
      <servlet>
        <servlet-name>swanlabs</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
      </servlet>
    
      <servlet-mapping>
        <servlet-name>swanlabs</servlet-name>
        <url-pattern>*.html</url-pattern>
      </servlet-mapping>
    
      <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
      </welcome-file-list>
    
      <jsp-config>
        <taglib>
          <taglib-uri>/spring</taglib-uri>
          <taglib-location>/WEB-INF/spring.tld</taglib-location>
        </taglib>
      </jsp-config>
    
    </web-app>
    Alternatively, does anyone have any ideas about resolving this? What I *don't* want to do is have to 'touch' the items in the collection before throwing them back to the UI views.

    Any help appreciated, this is ruining my week! :-)

  • #2
    change the order of the filters

    If you would change the order of the filters so that OpenSessionInViewFilter is the before the sitemesh PageFilter, the lazy loadng will work.

    I suspect that the lazy loading exception you are getting is from the template JSP code, not from the decorated JSPs. This is because the way the sitemesh PageFilter works (as far as I see it):
    1. the filter creates a 'fake' http servlet response,
    2. executes the filter chain with the fake http servlet response,
    3. includes the template jsp; the <decorator:body/> tag includes the content written in the fake http servlet response; write the decorated page on the real http servlet response.

    Now, if the OpenSessionInViewFilter already closed the Hibernate session at step 2, and at step 3 the template JSP tries to do some lazy loading you will get an exception.

    Hope this explains your problem, Mircea.

    Comment


    • #3
      Re: change the order of the filters

      Originally posted by croco
      If you would change the order of the filters so that OpenSessionInViewFilter is the before the sitemesh PageFilter, the lazy loadng will work.
      I tried that, swapping the order of those two filters has no effect. And that's what's puzzling me.

      Comment


      • #4
        Hmm.. then maybe the lazy loading exception you are getting is because you are trying to access a relation (thet is not loaded) of a disconected object. Maybe your SecurityFilter is trying to load the set of roles of the current HTTP session user with some code like:
        Code:
        ....
        User user = request.getSession&#40;&#41;.getAttribute&#40;"user"&#41;;
        Set roles = user.getRoles&#40;&#41;;
        ...
        You should check if the error is comming from the objects you are keeping in the HTTP session. Could you post an error stacktrace ?

        Mircea

        Comment

        Working...
        X