Spring, Hibernate and OpenViewInSession   December 3rd, 2007

I was trying to use the Hibernate lazy loading functionality with my Spring web application and had some problems, as usual for all newbies :P First, I couldn´t show list of objects that are aggregated to one main object in a many-to-one or in a one-to-one association. On trying to show the main object, the aggregated objects are retrieved as the View is being build. At this point the session is already closed, so it throws an sessionNotFound Exception. The solution for this is to use the OpenSessionInViewFilter Filter of the Spring Framework to keep the Session "alive" until the View has being built. In this case I needed to declare the Filter in my web.xml file like this:

    <!– Hibernate OpenSession Filter –>
    <filter>
        <filter-name>openSessionInViewFilter</filter-name>
        <filter-class>
            org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
        </filter-class>
        <init-param>
            <param-name>singleSession</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>sessionFactoryBeanName</param-name>
            <param-value>sessionFactory</param-value>
        </init-param>
    </filter>
   
    <filter-mapping>
        <filter-name>openSessionInViewFilter</filter-name>
        <url-pattern>*.htm</url-pattern>
    </filter-mapping>

It works very well, if you are only reading data from the database.

But if you want to change some entries retrieved from the db, you will receive a failure message like  "Write operations are not allowed in read-only mode (FlushMode.NEVER/MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove ‘readOnly’ marker" from transaction definition."

To solve this problem, it is needed to overwrite the openSessionInViewFilter methods getSession and closeSession. This can be done declaring another class, that extends the Sping class OpenSessionInViewFilter for the filter. This is the class I´m using:

import org.springframework.orm.hibernate3.support.OpenSessionInViewFilter;
import org.hibernate.*;
import org.springframework.dao.*;

public class MySessionFilter extends OpenSessionInViewFilter {
    /*
     * The default mode is FlushMode.NEVER
     *
     * @see org.springframework.orm.hibernate.support.OpenSessionInViewFilter#getSession(net.sf.hibernate.SessionFactory)
     */
    protected Session getSession(SessionFactory sessionFactory)
                        throws DataAccessResourceFailureException {
        Session session = super.getSession(sessionFactory);
        session.setFlushMode(FlushMode.COMMIT);   
        return session;
    }
   
    /**
    * we do an explicit flush here just in case we do not have an automated flush
    */
    protected void closeSession(Session session, SessionFactory factory) {
        session.flush(); 
        super.closeSession(session, factory); 
    }
}

After writing this class the reference to the filter class should be updated in the web.xml file.

<filter>
        <filter-name>openSessionInViewFilter</filter-name>
        <filter-class>
            MySessionFilter
        </filter-class>

</filter>

Now it is possible to retrieve data and update them only when it is needed using the lazy load ability.

This entry was posted on Monday, December 3rd, 2007 at 14:26 and is filed under Spring Framework. You can follow any responses to this entry through the RSS 2.0 feed.You can leave a response, or trackback from your own site.

No Responses

Leave a Reply