Note that there are some explanatory texts on larger screens.

plurals
  1. POOpenSessionInView working but not providing its session for @Transactional
    text
    copied!<p>I am trying to use Spring MVC 3 and Hibernate 4.1 to get declarative transaction management, providing an open session for the entire length of the request. I only have one "manager" layer for data access, which directly uses the session. This is annotated with @Transactional, and the session closes upon exiting this layer and I get a lazy load exception in the controller. </p> <p>So I added the OpenSessionInViewFilter filter, and the logs state that this filter is correctly configured and they also show this filter opening a session. Unfortunately, my manager layer opens and closes its own session anyway, just as before, and I get the same lazy load exception in the controller. </p> <p>Edit: noted that in my log, I get the filter session open, HibernateTransactionManager session open, HibernateTransactionManager session closed, lazy load exception, then filter session closed. So I know that there is an open session somewhere during the lazy load exception, but the object was loaded in a transaction associated with the other, closed session.</p> <p>I thought that removing @Transactional from the manager class would remove session management from that layer and let the filter do its job, but then the sessionFactory().getCurrentSession() simply gets a closed session; it doesn't have access to the filter's provided open session. </p> <p>How can I get access to the OpenSessionInViewFilter's clearly open session?</p> <p>springapp-servlet.xml</p> <pre><code>&lt;beans .. &lt;context:component-scan base-package="springapp.web" /&gt; &lt;bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/&gt; &lt;bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/&gt; &lt;!-- Enables the Spring MVC @Controller programming model --&gt; &lt;mvc:annotation-driven /&gt; &lt;bean id="userManager" class="springapp.service.SimpleUserManager"&gt; &lt;property name="sessionFactory" ref="sessionFactory" /&gt; &lt;/bean&gt; &lt;bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"&gt; &lt;property name="prefix" value="/WEB-INF/jsp/" /&gt; &lt;property name="suffix" value=".jsp" /&gt; &lt;/bean&gt; &lt;import resource="hibernate-context.xml" /&gt; &lt;/beans&gt; </code></pre> <p>web.xml</p> <pre><code>&lt;listener&gt; &lt;listener-class&gt;org.springframework.web.context.ContextLoaderListener&lt;/listener-class&gt; &lt;/listener&gt; &lt;context-param&gt; &lt;param-name&gt;contextConfigLocation&lt;/param-name&gt; &lt;param-value&gt;/WEB-INF/springapp-servlet.xml&lt;/param-value&gt; &lt;/context-param&gt; &lt;filter&gt; &lt;filter-name&gt;openSessionInView&lt;/filter-name&gt; &lt;filter-class&gt;org.springframework.orm.hibernate4.support.OpenSessionInViewFilter&lt;/filter-class&gt; &lt;init-param&gt; &lt;param-name&gt;sessionFactoryBeanName&lt;/param-name&gt; &lt;param-value&gt;sessionFactory&lt;/param-value&gt; &lt;/init-param&gt; &lt;/filter&gt; &lt;filter-mapping&gt; &lt;filter-name&gt;openSessionInView&lt;/filter-name&gt; &lt;url-pattern&gt;/*&lt;/url-pattern&gt; &lt;/filter-mapping&gt; &lt;servlet&gt; &lt;servlet-name&gt;springapp&lt;/servlet-name&gt; &lt;servlet-class&gt;org.springframework.web.servlet.DispatcherServlet&lt;/servlet-class&gt; &lt;/servlet&gt; &lt;servlet-mapping&gt; &lt;servlet-name&gt;springapp&lt;/servlet-name&gt; &lt;url-pattern&gt;/&lt;/url-pattern&gt; &lt;/servlet-mapping&gt; </code></pre> <p>hibernate-context.xml</p> <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt; &lt;beans .. "&gt; &lt;context:property-placeholder location="/WEB-INF/hibernate.properties" /&gt; &lt;bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"&gt; &lt;property name="driverClassName" value="${hibernate.connection.driver_class}" /&gt; &lt;property name="url" value="${hibernate.connection.url}" /&gt; &lt;property name="username" value="${hibernate.connection.username}" /&gt; &lt;property name="password" value="${hibernate.connection.password}" /&gt; &lt;/bean&gt; &lt;bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"&gt; &lt;property name="sessionFactory" ref="sessionFactory"/&gt; &lt;/bean&gt; &lt;tx:annotation-driven /&gt; &lt;bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"&gt; &lt;property name="transactionManager" ref="transactionManager" /&gt; &lt;property name="transactionAttributeSource"&gt; &lt;bean class="org.springframework.transaction.annotation.AnnotationTransactionAttributeSource" /&gt; &lt;/property&gt; &lt;/bean&gt; &lt;bean id="managerTemplate" abstract="true" class="org.springframework.aop.framework.ProxyFactoryBean"&gt; &lt;property name="interceptorNames"&gt; &lt;list&gt; &lt;value&gt;transactionInterceptor&lt;/value&gt; &lt;/list&gt; &lt;/property&gt; &lt;/bean&gt; &lt;bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"&gt; &lt;property name="packagesToScan" value="databeans" /&gt; &lt;property name="dataSource" ref="dataSource" /&gt; &lt;property name="hibernateProperties"&gt; &lt;props&gt; &lt;prop key="hibernate.dialect"&gt;${hibernate.dialect}&lt;/prop&gt; &lt;/props&gt; &lt;/property&gt; &lt;/bean&gt; &lt;/beans&gt; </code></pre> <p>manager.java</p> <pre><code>@Service("userManager") @Transactional public class SimpleUserManager implements UserManager { @Autowired private SessionFactory sessionFactory; public void setSessionFactory(SessionFactory sessionFactory){ this.sessionFactory = sessionFactory; } .. </code></pre> <p>controller.java</p> <pre><code>@Controller @RequestMapping("/users") public class UserController { @Autowired private UserManager userManager; .. </code></pre> <p>and my exception, which occurs in the controller, on the first property read of an object loaded in the manager class and passed to that controller:</p> <p>org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.hibernate.LazyInitializationException: could not initialize proxy - no Session org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:894) org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778) javax.servlet.http.HttpServlet.service(HttpServlet.java:617) javax.servlet.http.HttpServlet.service(HttpServlet.java:717) org.springframework.orm.hibernate4.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:119) org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)</p> <p>I've been researching this for hours.. all I can find is a mix of solutions using hibernate 3 and grainy explanations on hibernate 4 session/transaction theory without examples. </p> <p>Any thoughts?</p> <p>UPDATE: FIXED!</p> <p>Found this:</p> <p><a href="https://stackoverflow.com/questions/10904427/spring-mvc-opensessioninviewinterceptor-not-working">Spring MVC OpenSessionInViewInterceptor Not Working</a></p> <p>which unfortunately has not helped the OP there, but it helped me. Notably, this:</p> <p>"it will be better to not import applicationContext.xml in dispatcher-servlet.xml, instead load it using a ContextLoaderListener"</p> <p>which, applied to my configuration, is exactly everything I have posted above, but instead of </p> <pre><code>&lt;import resource="hibernate-context.xml" /&gt; </code></pre> <p>in my springapp-servlet.xml, I modified my ContextLoaderListener to:</p> <pre><code>&lt;context-param&gt; &lt;param-name&gt;contextConfigLocation&lt;/param-name&gt; &lt;param-value&gt;/WEB-INF/springapp-servlet.xml, /WEB-INF/hibernate-context.xml&lt;/param-value&gt; &lt;/context-param&gt; </code></pre> <p>and that was all it took for </p> <pre><code>sessionFactory.getCurrentSession() </code></pre> <p>to return to me the OSIV-created session. And, in fact, the second session that was being created is no longer, as I found these lovely little log lines:</p> <pre><code>2012-10-04 14:43:48,743 DEBUG http-8080-1 org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'transactionManager' 2012-10-04 14:43:48,743 TRACE http-8080-1 org.springframework.transaction.support.TransactionSynchronizationManager - Retrieved value [org.springframework.orm.hibernate4.SessionHolder@4146c5c0] for key [org.hibernate.internal.SessionFactoryImpl@12542011] bound to thread [http-8080-1] 2012-10-04 14:43:48,743 DEBUG http-8080-1 org.springframework.orm.hibernate4.HibernateTransactionManager - Found thread-bound Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=[] updates=[] deletions=[] collectionCreations=[] collectionRemovals=[] collectionUpdates=[] unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])] for Hibernate transaction 2012-10-04 14:43:48,743 DEBUG http-8080-1 org.springframework.orm.hibernate4.HibernateTransactionManager - Creating new transaction with name [springapp.service.SimpleUserManager.find]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; '' </code></pre> <p>which show that, outside of my @Transactional service layer, the OSIV-created session was alive and well, and a new transaction was simply started for it.</p> <p>Hope this helps someone else. I don't even want to think about how many hours I spent working on it.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload