title: Spring Hibernate "You cannot commit during a managed transaction!"
body: <p>After upgrading my application from JSF 1.2 to JSF 2.1 I have the following Spring Hibernate exception when trying to login:</p>
  
  <pre><code>DEBUG,[interceptor.ExceptionInterceptor][],org.springframework.transaction.TransactionSystemException: Could not commit Hibernate transaction; nested exception is org.hibernate.TransactionException: commit failed
      at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:472)
      at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
      at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
      at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:392)
      at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
      at myapp.aop.interceptor.MethodExceptionInterceptor.invoke(MethodExceptionInterceptor.java:21)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
      at myapp.aop.interceptor.SessionActivityInterceptor.invoke(SessionActivityInterceptor.java:47)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
      at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:90)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
      at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
      at com.sun.proxy.$Proxy121.endSession(Unknown Source)
      at myapp.web.action.connection.ConnectionBean.connect(ConnectionBean.java:100)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:606)
      at org.jboss.seam.util.Reflections.invoke(Reflections.java:22)
      at org.jboss.seam.intercept.RootInvocationContext.proceed(RootInvocationContext.java:32)
      at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:56)
      at myapp.web.interceptor.ExceptionInterceptor.aroundInvoke(ExceptionInterceptor.java:42)
      at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
      at org.jboss.seam.transaction.RollbackInterceptor.aroundInvoke(RollbackInterceptor.java:28)
      at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
      at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
      at org.jboss.seam.core.MethodContextInterceptor.aroundInvoke(MethodContextInterceptor.java:44)
      at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
      at org.jboss.seam.core.SynchronizationInterceptor.aroundInvoke(SynchronizationInterceptor.java:35)
      at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
      at org.jboss.seam.intercept.RootInterceptor.invoke(RootInterceptor.java:107)
      at org.jboss.seam.intercept.JavaBeanInterceptor.interceptInvocation(JavaBeanInterceptor.java:186)
      at org.jboss.seam.intercept.JavaBeanInterceptor.invoke(JavaBeanInterceptor.java:104)
      at myapp.web.action.connection.ConnectionBean_$$_javassist_seam_2.connect(ConnectionBean_$$_javassist_seam_2.java)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:606)
      at org.jboss.el.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:335)
      at org.jboss.el.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:348)
      at org.jboss.el.parser.AstPropertySuffix.invoke(AstPropertySuffix.java:58)
      at org.jboss.el.parser.AstValue.invoke(AstValue.java:96)
      at org.jboss.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:276)
      at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
      at org.apache.myfaces.trinidad.component.MethodExpressionMethodBinding.invoke(MethodExpressionMethodBinding.java:46)
      at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:101)
      at org.apache.myfaces.trinidad.component.UIXCommand.broadcast(UIXCommand.java:190)
      at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:786)
      at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1251)
      at oracle.adfinternal.view.faces.lifecycle.LifecycleImpl._invokeApplication(LifecycleImpl.java:1074)
      at oracle.adfinternal.view.faces.lifecycle.LifecycleImpl._executePhase(LifecycleImpl.java:402)
      at oracle.adfinternal.view.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:225)
      at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:295)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
      at oracle.adfinternal.view.faces.webapp.rich.RegistrationFilter.doFilter(RegistrationFilter.java:105)
      at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl$FilterListChain.doFilter(TrinidadFilterImpl.java:502)
      at oracle.adfinternal.view.faces.activedata.AdsFilter.doFilter(AdsFilter.java:60)
      at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl$FilterListChain.doFilter(TrinidadFilterImpl.java:502)
      at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl._doFilterImpl(TrinidadFilterImpl.java:327)
      at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl.doFilter(TrinidadFilterImpl.java:229)
      at org.apache.myfaces.trinidad.webapp.TrinidadFilter.doFilter(TrinidadFilter.java:92)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:246)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
      at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:83)
      at org.jboss.seam.web.LoggingFilter.doFilter(LoggingFilter.java:60)
      at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
      at myapp.web.filter.SessionActivityFilter.doFilter(SessionActivityFilter.java:67)
      at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
      at org.jboss.seam.web.IdentityFilter.doFilter(IdentityFilter.java:40)
      at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
      at org.jboss.seam.web.MultipartFilter.doFilter(MultipartFilter.java:90)
      at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
      at org.jboss.seam.web.ExceptionFilter.doFilter(ExceptionFilter.java:64)
      at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
      at org.jboss.seam.web.RedirectFilter.doFilter(RedirectFilter.java:45)
      at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
      at org.jboss.seam.servlet.SeamFilter.doFilter(SeamFilter.java:158)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:246)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
      at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
      at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:149)
      at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:389)
      at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:169)
      at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:145)
      at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:97)
      at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:102)
      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:336)
      at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:856)
      at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:653)
      at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:920)
      at java.lang.Thread.run(Thread.java:724)
   Caused by: org.hibernate.TransactionException: commit failed
      at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:185)
      at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:468)
      ... 93 more
   Caused by: org.hibernate.TransactionException: unable to commit against JDBC connection
      at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doCommit(JdbcTransaction.java:116)
      at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:178)
      ... 94 more
   Caused by: java.sql.SQLException: You cannot commit during a managed transaction!
      at org.jboss.jca.adapters.jdbc.BaseWrapperManagedConnection.jdbcCommit(BaseWrapperManagedConnection.java:1052)
      at org.jboss.jca.adapters.jdbc.WrappedConnection.commit(WrappedConnection.java:757)
      at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doCommit(JdbcTransaction.java:112)
      ... 95 more
  </code></pre>
  
  <p>Here is my spring beans configuration :</p>
  
  <pre><code>    &lt;bean id="parentSessionFactory" abstract="true"&gt;
          &lt;property name="dataSource"&gt;
              &lt;ref bean="myDS" /&gt;
          &lt;/property&gt;
          &lt;property name="hibernateProperties"&gt;
              &lt;props&gt;
                  &lt;prop key="hibernate.connection.driver_class"&gt;
                      org.h2.Driver
                  &lt;/prop&gt;
                  &lt;prop key="hibernate.show_sql"&gt;false&lt;/prop&gt;
                  &lt;prop key="hibernate.cache.region.factory_class"&gt;org.hibernate.cache.ehcache.EhCacheRegionFactory&lt;/prop&gt;
                  &lt;prop key="hibernate.cache.use_query_cache"&gt;true&lt;/prop&gt;
                  &lt;prop key="hibernate.cache.use_second_level_cache"&gt;true&lt;/prop&gt;
                  &lt;prop key="hibernate.cache.use_structured_cache"&gt;true&lt;/prop&gt;                            
              &lt;/props&gt;
          &lt;/property&gt;
      &lt;/bean&gt;
  
      &lt;bean id="myDS"
            class="org.springframework.jndi.JndiObjectFactoryBean"&gt;
          &lt;property name="jndiName" value="java:/myDS" /&gt;
      &lt;/bean&gt;
  
  
      &lt;bean id="sessionFactory" parent="parentSessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"&gt;   
        &lt;property name="configLocation"&gt;
          &lt;value&gt;
              classpath:model/hibernate.cfg.xml
          &lt;/value&gt;
        &lt;/property&gt;
  
        &lt;property name="hibernateProperties"&gt;
          &lt;props merge="true"&gt;
              &lt;prop key="hibernate.dialect"&gt;
                  org.hibernate.dialect.H2Dialect
              &lt;/prop&gt;    
          &lt;/props&gt;        
        &lt;/property&gt;
      &lt;/bean&gt;
  
      &lt;bean id="transactionManager"
        class="org.springframework.orm.hibernate4.HibernateTransactionManager"&gt;
        &lt;property name="sessionFactory"&gt;
          &lt;ref bean="sessionFactory"/&gt;
        &lt;/property&gt;
      &lt;/bean&gt;
  
  
      &lt;!-- the transactional advice (i.e. what 'happens'; see the &lt;aop:advisor/&gt; bean below) --&gt;
      &lt;tx:advice id="txAdvice" transaction-manager="transactionManager"&gt;
      &lt;!-- the transactional semantics... --&gt;
        &lt;tx:attributes&gt;
          &lt;!-- all methods starting with 'get' are read-only --&gt;
          &lt;tx:method name="get*" read-only="true" /&gt;
          &lt;tx:method name="find*" read-only="true" /&gt;
          &lt;tx:method name="list*" read-only="true" /&gt;
          &lt;tx:method name="read*" read-only="true" /&gt;
          &lt;tx:method name="save*" read-only="false" isolation="READ_COMMITTED"/&gt;
          &lt;tx:method name="remove*" read-only="false" isolation="READ_COMMITTED"/&gt;
          &lt;tx:method name="refresh*" read-only="false" isolation="READ_COMMITTED"/&gt;
          &lt;tx:method name="delete*" read-only="false" isolation="READ_COMMITTED"/&gt;
          &lt;!-- other methods use the default transaction settings (see below) --&gt;
          &lt;tx:method name="*" /&gt;
        &lt;/tx:attributes&gt;
      &lt;/tx:advice&gt;
      &lt;tx:annotation-driven transaction-manager="transactionManager"/&gt;
  
  &lt;!-- ensure that the above transactional advice runs for any execution
      of an operation defined by the *Service interface --&gt;
      &lt;aop:config&gt;
          &lt;aop:pointcut id="serviceOperation"
                        expression="execution(* services..*Service*.*(..))" /&gt;
          &lt;aop:pointcut id="daoOperation"
                        expression="execution(* dao..*Dao.*(..))" /&gt;
  
  
          &lt;aop:advisor advice-ref="sessionActivityInterceptor"
                       pointcut-ref="serviceOperation" /&gt;         
          &lt;aop:advisor advice-ref="exceptionInterceptor"
                       pointcut-ref="serviceOperation" /&gt;      --&gt;
          &lt;aop:advisor advice-ref="txAdvice"
                       pointcut-ref="serviceOperation" /&gt;
          &lt;aop:advisor advice-ref="txAdvice"
                       pointcut-ref="daoOperation" /&gt;      
      &lt;/aop:config&gt;
  </code></pre>
  
  <p>Here is the hibernate.cfg.xml:</p>
  
  <pre><code>&lt;hibernate-configuration&gt;
      &lt;session-factory&gt;
  
          &lt;property name="hibernate.dialect"&gt;org.hibernate.dialect.H2Dialect&lt;/property&gt;
  &lt;!--        &lt;property name="hibernate.cache.provider_class"&gt;net.sf.ehcache.hibernate.EhCacheProvider&lt;/property&gt; --&gt;
          &lt;property name="hibernate.cache.region.factory_class"&gt;org.hibernate.cache.ehcache.EhCacheRegionFactory&lt;/property&gt;
          &lt;property name="hibernate.cache.use_query_cache"&gt;true&lt;/property&gt;
          &lt;property name="hibernate.cache.use_second_level_cache"&gt;true&lt;/property&gt;
  
  
          &lt;!-- Several mapping classes here --&gt;
      &lt;/session-factory&gt;
  &lt;/hibernate-configuration&gt;
  </code></pre>
  
  <p>The <code>@Transactional</code> annotation is only used in one method in my application and in my unit tests, but is not used for what concerns the login part of the app.</p>
  
  <p>Investigating my exception further I see the code that throw the exception in <code>BaseWrapperManagedConnection</code> from <code>ironjacamar-jdbc-1.0.17</code> :</p>
  
  <pre><code>/**
      * JDBC commit
      * @exception SQLException Thrown if an error occurs
      */
     void jdbcCommit() throws SQLException
     {
        synchronized (stateLock)
        {
           if (inManagedTransaction)
              throw new SQLException("You cannot commit during a managed transaction!");
  
           if (jdbcAutoCommit)
              throw new SQLException("You cannot commit with autocommit set!");
        }
        con.commit();
  
        if (mcf.isJTA().booleanValue())
        {
           if (inLocalTransaction.getAndSet(false))
           {
              Collection&lt;ConnectionEventListener&gt; copy = null;
              synchronized (cels)
              {
                 copy = new ArrayList&lt;ConnectionEventListener&gt;(cels);
              }
  
              ConnectionEvent ce = new ConnectionEvent(this, ConnectionEvent.LOCAL_TRANSACTION_COMMITTED);
  
              for (Iterator&lt;ConnectionEventListener&gt; i = copy.iterator(); i.hasNext();)
              {
                 ConnectionEventListener cel = i.next();
                 try
                 {
                    cel.localTransactionCommitted(ce);
                 }
                 catch (Throwable t)
                 {
                    if (trace)
                       getLog().trace("Error notifying of connection committed for listener: " + cel, t);
                 }
              }
           }
        }
     }
  </code></pre>
  
  <p>the variable <code>inManagedTransaction</code> is set to true in <code>LocalManagedConnection</code> begin method from <code>ironjacamar-jdbc-1.0.17</code> :</p>
  
  <pre><code>/**
      * {@inheritDoc}
      */
     public void begin() throws ResourceException
     {
        lock();
        try
        {
           synchronized (stateLock)
           {
              if (!inManagedTransaction)
              {
                 try
                 {
                    if (underlyingAutoCommit)
                    {
                       underlyingAutoCommit = false;
                       con.setAutoCommit(false);
                    }
                    checkState();
                    inManagedTransaction = true;
                 }
                 catch (SQLException e)
                 {
                    checkException(e);
                 }
              }
              else
                 throw new ResourceException("Trying to begin a nested local tx");
           }
        }
        finally
        {
           unlock();
        }
     }
  </code></pre>
  
  <p>And the only place where this <code>inManagedTransaction</code> is set to false is in <code>LocalManagedConnection</code> <code>commit()</code> or <code>rollback()</code> method :</p>
  
  <pre><code>/**
      * {@inheritDoc}
      */
     public void commit() throws ResourceException
     {
        lock();
        try
        {
           synchronized (stateLock)
           {
              if (inManagedTransaction)
                 inManagedTransaction = false;
           }
           try
           {
              con.commit();
           }
           catch (SQLException e)
           {
              checkException(e);
           }
        }
        finally
        {
           unlock();
        }
     }
  
     /**
      * {@inheritDoc}
      */
     public void rollback() throws ResourceException
     {
        lock();
        try
        {
           synchronized (stateLock)
           {
              if (inManagedTransaction)
                 inManagedTransaction = false;
           }
           try
           {
              con.rollback();
           }
           catch (SQLException e)
           {
              try
              {
                 checkException(e);
              }
              catch (Exception e2)
              {
                 // Ignore
              }
           }
        }
        finally
        {
           unlock();
        }
     }
  </code></pre>
  
  <p><strong>Is it normal that I have two ManagedConnection one is <code>BaseWrapperManagedConnection</code> and the other <code>LocalManagedConnection</code> and that I'm going through both of their commit method ?</strong></p>
  
  <p>I have also read that JBoss could also take care of transactions (container managed transactions).  Is it possible that both Spring and JBoss try to handle my sessions and transactions ?</p>
  
  <p>I'm using Hibernate 4.2 and Spring 3.2.0.
  Most of it is classical configuration like found on many tutorials on the web nothing fancy.  The application using this configuration was working using JSF 1.2.
  Thanks for any advices, hints.</p>