title: Spring @Transactional not creating required transaction
body: <p>Ok, so I've finally bowed to peer pressure and started using Spring in my web app :-)...</p>
  
  <p>So I'm trying to get the transaction handling stuff to work, and I just can't seem to get it.</p>
  
  <p>My Spring configuration looks like this:</p>
  
  <pre><code>
  &lt;?xml version="1.0" encoding="UTF-8"?&gt;
  
  &lt;beans xmlns="http://www.springframework.org/schema/beans"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:p="http://www.springframework.org/schema/p"
         xmlns:tx="http://www.springframework.org/schema/tx"
         xsi:schemaLocation="http://www.springframework.org/schema/beans 
                             http://www.springframework.org/schema/beans/spring-beans.xsd
                             http://www.springframework.org/schema/tx
                             http://www.springframework.org/schema/tx/spring-tx.xsd"&gt;
  
      &lt;bean id="groupDao" class="mil.navy.ndms.conops.common.dao.impl.jpa.GroupDao" lazy-init="true"&gt;
          &lt;property name="entityManagerFactory" &gt;&lt;ref bean="entityManagerFactory"/&gt;&lt;/property&gt;
      &lt;/bean&gt;
  
   &lt;!-- enables interpretation of the @Required annotation to ensure that dependency injection actually occures --&gt;
    &lt;bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/&gt;  
  
    &lt;!-- enables interpretation of the @PersistenceUnit/@PersistenceContext annotations providing convenient
         access to EntityManagerFactory/EntityManager --&gt;
    &lt;bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/&gt;
  
    &lt;!-- uses the persistence unit defined in the META-INF/persistence.xml JPA configuration file --&gt;
    &lt;bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean"&gt;
          &lt;property name="persistenceUnitName" value="CONOPS_PU" /&gt; 
    &lt;/bean&gt;
  
    &lt;!-- transaction manager for use with a single JPA EntityManagerFactory for transactional data access
         to a single datasource --&gt;
    &lt;bean id="jpaTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"&gt;
        &lt;property name="entityManagerFactory" ref="entityManagerFactory"/&gt;
    &lt;/bean&gt;
  
    &lt;!-- enables interpretation of the @Transactional annotation for declerative transaction managment
         using the specified JpaTransactionManager --&gt;
    &lt;tx:annotation-driven transaction-manager="jpaTransactionManager" proxy-target-class="true"/&gt;
  
  &lt;/beans&gt;
  </code></pre>
  
  <p>persistence.xml:</p>
  
  <pre><code>
  &lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"&gt;
  
    &lt;persistence-unit name="CONOPS_PU" transaction-type="RESOURCE_LOCAL"&gt;
  
      &lt;provider&gt;org.hibernate.ejb.HibernatePersistence&lt;/provider&gt;
  
      ... Class mappings removed for brevity...
  
      &lt;properties&gt;
  
        &lt;property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/&gt;
  
        &lt;property name="hibernate.connection.autocommit" value="false"/&gt;
        &lt;property name="hibernate.connection.username" value="****"/&gt;
        &lt;property name="hibernate.connection.password" value="*****"/&gt;
  
        &lt;property name="hibernate.connection.driver_class" value="oracle.jdbc.OracleDriver"/&gt;
        &lt;property name="hibernate.connection.url" value="jdbc:oracle:thin:@*****:1521:*****"/&gt;
        &lt;property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/&gt;
        &lt;property name="hibernate.hbm2ddl.auto" value="create"/&gt;
        &lt;property name="hibernate.show_sql" value="true"/&gt;
        &lt;property name="hibernate.format_sql" value="true"/&gt;
  
      &lt;/properties&gt;
  
    &lt;/persistence-unit&gt;
  
  &lt;/persistence&gt;
  </code></pre>
  
  <p>The DAO method to save my domain object looks like this:</p>
  
  <pre><code>
      @Transactional(propagation=Propagation.REQUIRES_NEW)
      protected final T saveOrUpdate (T model)
      {
          EntityManager em = emf.createEntityManager ( );
          EntityTransaction trans = em.getTransaction ( );
  
          System.err.println ("Transaction isActive () == " + trans.isActive ( ));
  
          if (em != null)
          {
              try
              {
                  if (model.getId ( ) != null)
                  {
                      em.persist (model);
                      em.flush ();
                  }
                  else
                  {
                      em.merge (model);
                      em.flush ();
                  }
              }
              finally
              {
                  em.close ();
              }
          }
  
          return (model);
      }
  
  </code></pre>
  
  <p>So I try to save a copy of my Group object using the following code in my test case:</p>
  
  <pre><code>
      context = new ClassPathXmlApplicationContext(configs);
      dao = (GroupDao)context.getBean("groupDao");
  
      dao.saveOrUpdate (new Group ());
  </code></pre>
  
  <p>This bombs with the following exception:</p>
  
  <pre><code>
  javax.persistence.TransactionRequiredException: no transaction is in progress
      at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:301)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:48)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
      at java.lang.reflect.Method.invoke(Method.java:600)
      at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:341)
      at $Proxy26.flush(Unknown Source)
      at mil.navy.ndms.conops.common.dao.impl.jpa.GenericJPADao.saveOrUpdate(GenericJPADao.java:646)
      at mil.navy.ndms.conops.common.dao.impl.jpa.GroupDao.save(GroupDao.java:641)
      at mil.navy.ndms.conops.common.dao.impl.jpa.GroupDao$$FastClassByCGLIB$$50343b9b.invoke()
      at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149)
      at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622)
      at mil.navy.ndms.conops.common.dao.impl.jpa.GroupDao$$EnhancerByCGLIB$$7359ba58.save()
      at mil.navy.ndms.conops.common.dao.impl.jpa.GroupDaoTest.testGroupDaoSave(GroupDaoTest.java:91)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:48)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
      at java.lang.reflect.Method.invoke(Method.java:600)
      at junit.framework.TestCase.runTest(TestCase.java:164)
      at junit.framework.TestCase.runBare(TestCase.java:130)
      at junit.framework.TestResult$1.protect(TestResult.java:106)
      at junit.framework.TestResult.runProtected(TestResult.java:124)
      at junit.framework.TestResult.run(TestResult.java:109)
      at junit.framework.TestCase.run(TestCase.java:120)
      at junit.framework.TestSuite.runTest(TestSuite.java:230)
      at junit.framework.TestSuite.run(TestSuite.java:225)
      at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)
      at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
  
  </code></pre>
  
  <p>In addition, I get the following warnings when Spring first starts. Since these reference the entityManagerFactory and the transactionManager, they probably have some bearing on the problem, but I've no been able to decipher them enough to know what:</p>
  
  <pre><code>
  Mar 11, 2010 12:19:27 PM org.springframework.context.support.AbstractApplicationContext$BeanPostProcessorChecker postProcessAfterInitialization
  INFO: Bean 'entityManagerFactory' is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
  Mar 11, 2010 12:19:27 PM org.springframework.context.support.AbstractApplicationContext$BeanPostProcessorChecker postProcessAfterInitialization
  INFO: Bean 'entityManagerFactory' is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
  Mar 11, 2010 12:19:27 PM org.springframework.context.support.AbstractApplicationContext$BeanPostProcessorChecker postProcessAfterInitialization
  INFO: Bean 'jpaTransactionManager' is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
  Mar 11, 2010 12:19:27 PM org.springframework.context.support.AbstractApplicationContext$BeanPostProcessorChecker postProcessAfterInitialization
  INFO: Bean '(inner bean)' is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
  Mar 11, 2010 12:19:27 PM org.springframework.context.support.AbstractApplicationContext$BeanPostProcessorChecker postProcessAfterInitialization
  INFO: Bean '(inner bean)' is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
  Mar 11, 2010 12:19:27 PM org.springframework.context.support.AbstractApplicationContext$BeanPostProcessorChecker postProcessAfterInitialization
  INFO: Bean 'org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor' is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
  Mar 11, 2010 12:19:27 PM org.springframework.context.support.AbstractApplicationContext$BeanPostProcessorChecker postProcessAfterInitialization
  INFO: Bean 'org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor' is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
  Mar 11, 2010 12:19:27 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
  INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@37003700: defining beans [groupDao,org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor,org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor,entityManagerFactory,jpaTransactionManager,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor]; root of factory hierarchy
  </code></pre>
  
  <p>Does anyone have any idea what I'm missing? I'm totally stumped...</p>
  
  <p>Thanks</p>