Announcement Announcement Module
Collapse
No announcement yet.
Lazy Loading error with Transaction when using ContextLoaderListener - Very odd Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Lazy Loading error with Transaction when using ContextLoaderListener - Very odd

    Hi,

    I'm getting a very odd issue with transaction management when using a ContextLoaderListener. Any help would be much appreciated.

    We have been using Transactions in our Spring MVC app for a couple of months now.
    We put our contextConfigLocation definition right in the DispatcherServlet, and everything was working fine.

    Here is our original, working web.xml:
    Code:
    	<servlet>
    		<servlet-name>spring</servlet-name>
    		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    		<init-param>
    			<param-name>contextConfigLocation</param-name>
    			<param-value>
    				classpath:servicesContext.xml
    				classpath:databaseContext.xml
    				classpath:daoContext.xml
    				/WEB-INF/spring-servlet.xml
    			</param-value>
    		</init-param>
    		<load-on-startup>1</load-on-startup>
    	</servlet>
    And our daoContext.xml had:
    Code:
    <tx:annotation-driven transaction-manager="transactionManager" />
    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>
    Now a couple of weeks ago, I had to integrate some other things, and the first step I needed to do was move the context instantiation to be in the ContextLoaderListener. All I changed was our web.xml to be:
    Code:
    <context-param>
    	<param-name>contextConfigLocation</param-name>
    	<param-value>
    			/WEB-INF/spring-servlet.xml
    			/WEB-INF/spring-security.xml
    			classpath:servicesContext.xml
    			classpath:databaseContext.xml
    			classpath:daoContext.xml
    	</param-value>
    </context-param>
    <listener>
    	<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <servlet>
    	<servlet-name>spring</servlet-name>
    	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    </servlet>
    Now it seems that Transactions are being lost after exiting the service layer, since Hibernate is throwing LazyInitilization errors, complaining about not finding an open session. This is code that works fine with the original web.xml
    Other than the Transactions, everything is working fine. All the beans are wired properly, data access is working properly, and our transactions are still open until we leave the service layer.

    I've ran through some tests, and here is an over-simplification of what seems to be happening. All of the below are defined with the Transactional annotation
    com.foo.bar.controller.mySpringController.handleRe quest()
    com.foo.bar.service.impl.myServiceImpl.findBaz()
    com.foo.bar.dao.impl.myDaoImpl.getBaz()

    getBaz() is called just fine, returns as expected
    findBaz() works just fine, lazy initialization works just fine, the entire object can be walked without issues
    handleRequest() blows up with a lazy initialization error and can't find the session

    And NOW for the REALLY annoying part. I have, kind of, gotten around the issue, however, I really dislike my solution. While playing around with some of my XML files, I moved the <tx:annotation-driven> and my transactionManager bean from the daoContext.xmlto the spring-servlet.xml context file, and EVERYTHING works when using the ContextLoaderListener

    We can't use this solution because we're packaging our our service/data access layer (including context files, etc.) to use in several of our applications


    Does the context load differently when instantiating it in a ContextLoaderListener rather than a DispatcherServlet?
    Why would the transactional stuff work when I move it to a different context file when everything else in that context file works fine?

    I can explain more if anybody can help me.

    Thanks,
    Scott.

  • #2
    I suggest

    1) Read the reference guide
    2) use the forum search...

    The ContextLoaderListener and DisptachterServlet BOTH have an ApplicationContext. The DispatcherServlet is using the one loaded by the ContextLoaderListener as its parent. In your case however you are ending up with multiple instances. Your spring-servlet.xml is loaded by the ContextLoaderListner AND the DispatcherServlet. However the beans loaded from the spring-servlet.xml are useless and ignored.

    Your initial configuration works because BeanFactoryPostProcessors work on the ApplicationContext they are loaded in. That is also why it works when you define the tx part in the spring-servlet (because it is loaded by the DispatcherServlet and processing that ApplicationContext).

    However the major flaw imho here is that it seems that your web methods (Controllers) are transactional (else it would still blow up imho).

    I suggest you look for the OpenSessionInViewFilter/-Interceptor which keeps the hibernate session (not transaction!) open until after the view has rendered.

    Comment

    Working...
    X