Announcement Announcement Module
Collapse
No announcement yet.
Transaction management problem (Hibernate3, Spring MVC) Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Transaction management problem (Hibernate3, Spring MVC)

    Having some trouble with getting transactions to work in my hibernate3 app. I don't know, but I think it might be something related to executing in the context of an MVC-based web app. My unit tests are showing no issue, but the system is failing on integration, giving the exception:

    Code:
    java.lang.IllegalStateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
    	org.springframework.orm.hibernate3.SessionFactoryUtils.doGetSession(SessionFactoryUtils.java:350)
    	org.springframework.orm.hibernate3.SessionFactoryUtils.getSession(SessionFactoryUtils.java:200)
    	org.springframework.orm.hibernate3.support.HibernateDaoSupport.getSession(HibernateDaoSupport.java:165)
    	meridian.experimental.hibernatetest.DayListModelBean.getDayList(DayListModelBean.java:23)
    This unit test works:

    Code:
    public class TestSpringSetup extends TestCase
    {
    	public void testSetupWithDeclarativeTransactions ()
    	{
    		ApplicationContext context = new ClassPathXmlApplicationContext(
    		"meridian/experimental/hibernatetest/beandefinition.xml");
    
    		TransactionTestBean ttb = (TransactionTestBean) context.getBean ("ttb");
    		ttb.doTransactionTest ();
    	}
    }
    Code:
    <beans [...]>
    
    	<tx:annotation-driven transaction-manager="txManager" />
    	
    	<bean id="sessionFactory" autowire="byName"
    		class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
                [...]
    	</bean>
    	
    	<bean id="txManager" autowire="byName" 
    		class="org.springframework.orm.hibernate3.HibernateTransactionManager" />
    		
    	<bean id="model" autowire="byName"
    		class="meridian.experimental.hibernatetest.DayListModelBean" />
    	
    	<bean id="ttb" autowire="byName"
    		class="meridian.experimental.hibernatetest.TransactionTestBean" />
    </beans>
    Code:
    @Transactional
    public class TransactionTestBean extends Assert
    {
    	private DayListModel model;
    	
    	public DayListModel getModel()
    	{
    		return model;
    	}
    
    	public void setModel(DayListModel model)
    	{
    		this.model = model;
    	}
    
    	public void doTransactionTest()
    	{
    		Calendar c = Calendar.getInstance ();
    		c.set (2007, Calendar.JUNE, 21);
    		DayList retrieved = model.getDayList (c.getTime ());
    		assertNotNull (retrieved);
    		assertEquals (2, retrieved.getEntryList ().size ());		
    	}
    }
    Code:
    public class DayListModelBean extends HibernateDaoSupport implements DayListModel
    {
    
    	public DayListModelBean()
    	{
    		// TODO Auto-generated constructor stub
    	}
    
        /* (non-Javadoc)
    	 * @see meridian.experimental.hibernatetest.DayListModel#getDayList(java.util.Date)
    	 */
        public DayList getDayList (Date day)
        {
        	List dayLists = getSession (false)
        		.createQuery ("from DayList where listDate = ?").setDate (0, day).list ();
        	if (dayLists.size() == 0) return null;
        	DayList dl = (DayList) dayLists.get (0);
        	
        	return dl;
        }
        [...]
    }
    But this servlet fails:

    Code:
    <beans [...]>
    
    	<tx:annotation-driven transaction-manager="txManager" />
    
    ...
    	
    	<bean id="sessionFactory" autowire="byName"
    		class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
                [...]
    	</bean>
    	
    	<bean id="txManager" autowire="byName" 
    		class="org.springframework.orm.hibernate3.HibernateTransactionManager" />
    		
    	<bean id="model" autowire="byName"
    		class="meridian.experimental.hibernatetest.DayListModelBean" />
    
    [....]
    
    	<bean name="/viewDayList" class="meridian.webtest.ViewDayListController" autowire="byName" />
    </beans>
    Code:
    @Transactional
    public class ViewDayListController extends AbstractController
    {
    	private DayListModel model;
    	
    	public DayListModel getModel()
    	{
    		return model;
    	}
    
    	public void setModel(DayListModel model)
    	{
    		this.model = model;
    	}
    
    	protected ModelAndView handleRequestInternal(
    		HttpServletRequest request, HttpServletResponse response) throws Exception
    	{
    		Calendar c = Calendar.getInstance ();
    		c.set (2007, Calendar.JUNE, 21);	// FIXME: allow user to specify
    		DayList retrieved = model.getDayList (c.getTime ());
    		if (retrieved == null)
    			return new ModelAndView ("error", "message", "Day list not found for that date");
    		return new ModelAndView ("viewDayList", "daylist", retrieved);
    	}
    }
    Can anyone tell me what I'm doing wrong?
    Last edited by julesh; Jul 5th, 2007, 03:04 PM. Reason: More recent version of the working test, more similar to the failing code.

  • #2
    It's useful to view the complete stacktrace, you can then see if it includes a transaction. I would guess your problem is because you are trying to proxy a controller which actually has internal method calls. It typical to apply transactions at the service layer.
    http://www.springframework.org/docs/...ng-aop-proxies
    http://www.martinfowler.com/eaaCatal...viceLayer.html
    Last edited by karldmoore; Aug 29th, 2007, 10:48 AM.

    Comment


    • #3
      On a side note if you are writing tests using Spring, you might want to check out the Spring helper classes.
      http://www.springframework.org/docs/...e/testing.html
      Last edited by karldmoore; Aug 29th, 2007, 10:48 AM.

      Comment


      • #4
        Originally posted by karldmoore View Post
        It's useful to view the complete stacktrace, you can then see if it includes a transaction. I would guess your problem is because you are trying to proxy a controller which actually has internal method calls.
        Hmm. Complete stack trace is:

        Code:
        java.lang.IllegalStateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
        	org.springframework.orm.hibernate3.SessionFactoryUtils.doGetSession(SessionFactoryUtils.java:350)
        	org.springframework.orm.hibernate3.SessionFactoryUtils.getSession(SessionFactoryUtils.java:200)
        	org.springframework.orm.hibernate3.support.HibernateDaoSupport.getSession(HibernateDaoSupport.java:165)
        	meridian.experimental.hibernatetest.DayListModelBean.getDayList(DayListModelBean.java:23)
        	meridian.webtest.ViewDayListController.handleRequestInternal(ViewDayListController.java:35)
        	org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
        	sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        	sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        	sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        	java.lang.reflect.Method.invoke(Unknown Source)
        	org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:304)
        	org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:198)
        	$Proxy6.handleRequest(Unknown Source)
        	org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
        	org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:857)
        	org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:792)
        	org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:461)
        	org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:416)
        	javax.servlet.http.HttpServlet.service(HttpServlet.java:690)
        	javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
        I'm not sure how to tell if the transaction is being created, but the AOP proxy does seem to have been called, at least. I'll look into restructuring my code to move the transactions to the service layer. It'll probably make the code more complex, initially, which is why I've resisted it, but I dare say the overall quality will improve.

        Comment


        • #5
          Originally posted by julesh View Post
          I'm not sure how to tell if the transaction is being created, but the AOP proxy does seem to have been called, at least.
          No, there is no TransactionInterceptor in the stacktrace. So something must be wrong with that part of your configuration.

          Jörg

          Comment


          • #6
            Maybe it has something to do with your file structure. This thread contains a discussion about applying aop to Controllers. At the end of thread, the way files were loaded and imported made the difference in advices being applied or not.

            Comment


            • #7
              Lots of people have had problems with AOP and SpringMVC, the AOP forum is full of them. That's why I suggested the service layer.
              Last edited by karldmoore; Aug 29th, 2007, 10:48 AM.

              Comment

              Working...
              X