The Open Session in View Pattern is a well publicised design pattern for Hibernate applications and is considered the best practice approach to presenting data within the Web tier of an application. In this article I’ll demonstrate how simple it is to configure a Spring application to work the same way when JPA is used for the persistence technology. The exact same principles apply for a plain Spring/Hibernate application that does not use JPA.
What is Open Session in View?
The Java Persistence API (JPA) allows an object oriented model to be mapped to a relational database. JPA is a standard specification for Java based Object Relational Mapping frameworks – in order to use JPA an underlying implementation must be available; the most common choice being Hibernate.
Both JPA an Hibernate support lazy loading of data to restrict the number of queries fired off to the database. In general this means that data will be loaded on demand when methods are called, on a loaded object, that require more data to be loaded. In order for this to work, the object that the method is called on must have been loaded by JPA and be part of the current running transaction.
In a Spring application, calls to demarcate transactions are generally handled by the Spring interceptors.Transactions are normally started when a method call is made on a Spring managed object and committed once that method call ends. This means that if a JSP page requests data by calling a transactional method on a Spring managed bean, then it can only access the data in that bean that has already been loaded within that call. Any calls for data that might be loaded lazily will fail because the object is no longer attached to a JPA transaction after that method call has returned.
Hibernate developers solved this problem using the Open Session in View design, which associates the active session (and hence it’s transaction) with the thread that makes the call. In this design, the transaction will be committed when the thread completed processing the request, rather than when a method call completes. This allows lazily loaded data to be loaded within the JSP page not just within Spring managed objects.
Providing Request Scoped Transactions
A standard way to intercept requests in any Java Web application is to use a web filter. Spring provide an out-of-the-box Web filters that implement the Open Session in View design for both Hibernate and JPA. We will see the JPA version here, but the Hibernate one works in just the same way; just change the class name in the configuration file.
<filter> <filter-name>oemInViewFilter</filter-name> <filter-class> org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter </filter-class> <init-param> <param-name>entityManagerFactoryBeanName</param-name> <param-value>reportsEntityManagerFactory</param-value> </init-param> </filter> <filter-mapping> <filter-name>oemInViewFilter</filter-name> <url-pattern>*.jsp</url-pattern> </filter-mapping>
The filter class is from the Spring framework libraries. The filter mapping, in this example, applies this filter to all URLs ending with ‘.jsp'; this means that all JSPs that retrieve a lazily loaded object form the service tier of the application are now free to read any data members from it – any unloaded data will be loaded from the database when calls are made to access it.
Be aware that the filter turns off the auto-flush behaviour of the standard entity manager. This means that any changes that are made to the data in the JSP will not be persisted. The filter can be configured to flush these if requested.
Finally, the init-param that’s provided to the filter is optional and can be used to explicitly name the entity manager factory that will be used. The example shows how to use an entity manager named ‘reportsEntityManagerFactory’ in the Spring configuration files; the default value for this is ‘entityManagerFactory’.