title: How works @Transactional timeout attribute with different propagations
body: <p>I am confused with the behaviour of the @Transactional <strong>timeout</strong> attribute</p>
  
  <p>I have the following sequence</p>
  
  <pre><code>Main -&gt; 
  UserExecutionServiceImpl.executeRecordInvoice -&gt;
  ProcessInvoiceServiceImpl.recordInvoice -&gt;
  WarehouseServiceImpl.checkStockAvailability
  </code></pre>
  
  <p>To force the rollback exception <strong>timeout</strong> is set to 0.</p>
  
  <p>If <strong>executeRecordInvoice</strong> has <code>@Transactional(timeout=0)</code> the exception is thrown and there stop all. It has sense</p>
  
  <p>If <strong>executeRecordInvoice</strong> has <code>@Transactional</code> and <strong>recordInvoice</strong> has <code>@Transactional(timeout=0)</code> the exception is not thrown. Practically the timeout value has been ignored. </p>
  
  <p>I could assume because the transaction really begins with <strong>executeRecordInvoice</strong> and furthermore because both methods have by default <code>Propagation.Required</code>, it means, the second (<strong>recordInvoice</strong>) is considered within the first (<strong>executeRecordInvoice</strong>), the already existing transaction, which is running</p>
  
  <p>Even more, I did two simple experiments:</p>
  
  <ol>
  <li><p>If <strong>executeRecordInvoice</strong> has <code>@Transactional</code> and <strong>recordInvoice</strong> has <code>@Transactional(propagation.Propagation.REQUIRES_NEW, timeout=0)</code> the exception is  thrown. Now works because a <strong>new</strong> Transaction begins in <strong>recordInvoice</strong> and therefore <strong>timeout</strong> is considered.</p></li>
  <li><p>Call from the Main class directly the <code>ProcessInvoiceServiceImpl.recordInvoice</code>, it with <code>@Transactional(propagation.Propagation.REQUIRED, timeout=0)</code> or with <code>@Transactional(propagation.Propagation.REQUIRES_NEW, timeout=0)</code>, again <strong>timeout</strong> is considered.</p></li>
  </ol>
  
  <p>Until here, I am fine, and all has sense. But applying 1 and 2 for <strong>WarehouseServiceImpl.checkStockAvailability</strong>, it does not work:</p>
  
  <ol>
  <li><p>If <strong>executeRecordInvoice</strong> and <strong>recordInvoice</strong> have <code>@Transactional</code> (therefore both Propagation.REQUIRED by default) and <strong>checkStockAvailability</strong> has <code>@Transactional(propagation.Propagation.REQUIRES_NEW, timeout=0)</code>. The exception is <strong>not</strong> thrown!.</p></li>
  <li><p>Call from the Main class directly the <code>WarehouseServiceImpl.checkStockAvailability</code>, it with <code>@Transactional(propagation.Propagation.REQUIRED, timeout=0)</code> or with <code>@Transactional(propagation.Propagation.REQUIRES_NEW, timeout=0)</code>, again <strong>timeout</strong> is <strong>not</strong> considered.</p></li>
  </ol>
  
  <p>Class declaration</p>
  
  <pre><code>@Service
  @Transactional
  @Scope("prototype")
  public class WarehouseServiceImpl implements WarehouseService {
  
      // Unique method implementation
      @Transactional(propagation = Propagation.REQUIRES_NEW, timeout=0)
      public boolean checkStockAvailability(Product product, BigDecimal quantity) {
  
          ...
  
      return true;
  
      }
  }
  </code></pre>
  
  <p>Any idea or suggestion is welcome.</p>
  
  <p>Spring Framework 4.0.5</p>
  
  <p>Thank you.</p>
  
  <p>After to do the suggestion of Andrei, I have the following:</p>
  
  <pre><code>@Transactional
  @Scope("prototype")
  @Service("processInvoiceService")
  public class ProcessInvoiceServiceImpl implements ProcessInvoiceService {
  
      @Override
      @Transactional(propagation = Propagation.REQUIRES_NEW, timeout=0)
      public void recordInvoice(InvoiceHeader invoiceHeader) {
  </code></pre>
  
  <p>And in the MainTest class</p>
  
  <pre><code>ProcessInvoiceService processInvoiceService = context.getBean(ProcessInvoiceService.class);
  
          try{
              processInvoiceService.recordInvoice(invoiceHeader03);
          }
          catch(Exception e){
              logger.error("ERROR ALFA: {}", e.getMessage());
          }
  </code></pre>
  
  <p>With shows the Console, part in the result output</p>
  
  <pre><code>Creating instance of bean 'processInvoiceService'
  20:16:57,320 DEBUG ctory.support.DefaultListableBeanFactory: 249 - Returning cached instance of singleton bean 'productService'
  20:16:57,320 DEBUG ctory.support.DefaultListableBeanFactory: 249 - Returning cached instance of singleton bean 'invoiceHeaderService'
  20:16:57,320 DEBUG ctory.support.DefaultListableBeanFactory: 249 - Returning cached instance of singleton bean 'invoiceDetailService'
  20:16:57,321 DEBUG ctory.support.DefaultListableBeanFactory: 449 - Creating instance of bean 'warehouseServiceImpl'
  20:16:57,321 DEBUG ctory.support.DefaultListableBeanFactory: 249 - Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
  20:16:57,321 DEBUG xy.InfrastructureAdvisorAutoProxyCreator: 593 - Creating implicit proxy for bean 'warehouseServiceImpl' with 0 common interceptors and 1 specific interceptors
  20:16:57,321 DEBUG amework.aop.framework.JdkDynamicAopProxy: 117 - Creating JDK dynamic proxy: target source is SingletonTargetSource for target object [com.manuel.jordan.model.service.support.impl.WarehouseServiceImpl@7b4c50bc]
  20:16:57,321 DEBUG ctory.support.DefaultListableBeanFactory: 477 - Finished creating instance of bean 'warehouseServiceImpl'
  20:16:57,322  INFO e.process.impl.ProcessInvoiceServiceImpl:  46 - ProcessInvoiceServiceImpl arg constructor
  20:16:57,322 DEBUG ctory.support.DefaultListableBeanFactory: 249 - Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
  20:16:57,322 DEBUG xy.InfrastructureAdvisorAutoProxyCreator: 593 - Creating implicit proxy for bean 'processInvoiceService' with 0 common interceptors and 1 specific interceptors
  20:16:57,322 DEBUG amework.aop.framework.JdkDynamicAopProxy: 117 - Creating JDK dynamic proxy: target source is SingletonTargetSource for target object [com.manuel.jordan.model.service.process.impl.ProcessInvoiceServiceImpl@5884a914]
  20:16:57,322 DEBUG ctory.support.DefaultListableBeanFactory: 477 - Finished creating instance of bean 'processInvoiceService'
  20:16:57,322 DEBUG ctory.support.DefaultListableBeanFactory: 249 - Returning cached instance of singleton bean 'transactionManager'
  20:16:57,322 DEBUG .datasource.DataSourceTransactionManager: 367 - Creating new transaction with name [com.manuel.jordan.model.service.process.impl.ProcessInvoiceServiceImpl.recordInvoice]: PROPAGATION_REQUIRES_NEW,ISOLATION_DEFAULT,timeout_0; ''
  20:16:57,322 DEBUG k.jdbc.datasource.SimpleDriverDataSource: 138 - Creating new JDBC Driver Connection to [jdbc:hsqldb:mem:testdb]
  20:16:57,323 DEBUG .datasource.DataSourceTransactionManager: 206 - Acquired Connection [org.hsqldb.jdbc.JDBCConnection@50378a4] for JDBC transaction
  20:16:57,323 DEBUG .datasource.DataSourceTransactionManager: 223 - Switching JDBC Connection [org.hsqldb.jdbc.JDBCConnection@50378a4] to manual commit
  20:16:57,323  INFO e.process.impl.ProcessInvoiceServiceImpl:  59 - ProcessInvoiceServiceImpl recordInvoice - start
  20:16:57,323 DEBUG ctory.support.DefaultListableBeanFactory: 249 - Returning cached instance of singleton bean 'transactionManager'
  20:16:57,323 DEBUG .datasource.DataSourceTransactionManager: 472 - Participating in existing transaction
  20:16:57,323 DEBUG ctory.support.DefaultListableBeanFactory: 249 - Returning cached instance of singleton bean 'transactionManager'
  20:16:57,323 DEBUG .datasource.DataSourceTransactionManager: 472 - Participating in existing transaction
  20:16:57,324 DEBUG g.springframework.jdbc.core.JdbcTemplate: 908 - Executing prepared SQL update
  20:16:57,324 DEBUG g.springframework.jdbc.core.JdbcTemplate: 627 - Executing prepared SQL statement [INSERT INTO invoiceheader(id, number, date, total) VALUES(?, ?, ?, ?)]
  20:16:57,324 DEBUG .datasource.DataSourceTransactionManager: 854 - Participating transaction failed - marking existing transaction as rollback-only
  20:16:57,324 DEBUG .datasource.DataSourceTransactionManager: 295 - Setting JDBC transaction [org.hsqldb.jdbc.JDBCConnection@50378a4] rollback-only
  20:16:57,324 DEBUG .datasource.DataSourceTransactionManager: 854 - Participating transaction failed - marking existing transaction as rollback-only
  20:16:57,325 DEBUG .datasource.DataSourceTransactionManager: 295 - Setting JDBC transaction [org.hsqldb.jdbc.JDBCConnection@50378a4] rollback-only
  20:16:57,325 DEBUG .datasource.DataSourceTransactionManager: 847 - Initiating transaction rollback
  20:16:57,325 DEBUG .datasource.DataSourceTransactionManager: 281 - Rolling back JDBC transaction on Connection [org.hsqldb.jdbc.JDBCConnection@50378a4]
  20:16:57,325 DEBUG .datasource.DataSourceTransactionManager: 324 - Releasing JDBC Connection [org.hsqldb.jdbc.JDBCConnection@50378a4] after transaction
  20:16:57,325 DEBUG ramework.jdbc.datasource.DataSourceUtils: 327 - Returning JDBC Connection to DataSource
  20:16:57,325 ERROR          com.manuel.jordan.main.MainTest:  93 - ERROR ALFA: Transaction timed out: deadline was Mon Jun 30 20:16:57 PET 2014
  20:16:57,325 DEBUG ctory.support.DefaultListableBeanFactory: 249 - Returning cached instance of singleton bean 'transactionManager'
  </code></pre>
  
  <p>the error message appears how is expected..</p>
  
  <p>Now for the other class</p>
  
  <pre><code>@Service
  @Transactional
  @Scope("prototype")
  public class WarehouseServiceImpl implements WarehouseService {
  
      private static final Logger logger = LoggerFactory.getLogger(WarehouseServiceImpl.class);
  
      @Override
      @Transactional(propagation = Propagation.REQUIRES_NEW, timeout=0)
      public boolean checkStockAvailability(Product product, BigDecimal quantity) {
  </code></pre>
  
  <p>And in the MainTest class</p>
  
  <pre><code>WarehouseService warehouseService = context.getBean(WarehouseService.class);
  
          try{
              logger.info("Pre");
              boolean result = warehouseService.checkStockAvailability(product01, BigDecimal.ZERO);
              logger.info("result: {}", result);
              logger.info("Post");
          }
          catch(Exception e){
              logger.error("ERROR BETA: {}", e.getMessage());
          }
  </code></pre>
  
  <p>With shows the Console, part in the result output</p>
  
  <pre><code>20:16:57,337 DEBUG ctory.support.DefaultListableBeanFactory: 449 - Creating instance of bean 'warehouseServiceImpl'
  20:16:57,337 DEBUG ctory.support.DefaultListableBeanFactory: 249 - Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
  20:16:57,338 DEBUG xy.InfrastructureAdvisorAutoProxyCreator: 593 - Creating implicit proxy for bean 'warehouseServiceImpl' with 0 common interceptors and 1 specific interceptors
  20:16:57,338 DEBUG amework.aop.framework.JdkDynamicAopProxy: 117 - Creating JDK dynamic proxy: target source is SingletonTargetSource for target object [com.manuel.jordan.model.service.support.impl.WarehouseServiceImpl@23f5b5dc]
  20:16:57,338 DEBUG ctory.support.DefaultListableBeanFactory: 477 - Finished creating instance of bean 'warehouseServiceImpl'
  20:16:57,338  INFO          com.manuel.jordan.main.MainTest: 102 - Pre
  20:16:57,338 DEBUG ion.AnnotationTransactionAttributeSource: 108 - Adding transactional method 'WarehouseServiceImpl.checkStockAvailability' with attribute: PROPAGATION_REQUIRES_NEW,ISOLATION_DEFAULT,timeout_0; ''
  20:16:57,338 DEBUG ctory.support.DefaultListableBeanFactory: 249 - Returning cached instance of singleton bean 'transactionManager'
  20:16:57,339 DEBUG .datasource.DataSourceTransactionManager: 367 - Creating new transaction with name [com.manuel.jordan.model.service.support.impl.WarehouseServiceImpl.checkStockAvailability]: PROPAGATION_REQUIRES_NEW,ISOLATION_DEFAULT,timeout_0; ''
  20:16:57,339 DEBUG k.jdbc.datasource.SimpleDriverDataSource: 138 - Creating new JDBC Driver Connection to [jdbc:hsqldb:mem:testdb]
  20:16:57,339 DEBUG .datasource.DataSourceTransactionManager: 206 - Acquired Connection [org.hsqldb.jdbc.JDBCConnection@34bde49d] for JDBC transaction
  20:16:57,339 DEBUG .datasource.DataSourceTransactionManager: 223 - Switching JDBC Connection [org.hsqldb.jdbc.JDBCConnection@34bde49d] to manual commit
  20:16:57,339 DEBUG .datasource.DataSourceTransactionManager: 755 - Initiating transaction commit
  20:16:57,339 DEBUG .datasource.DataSourceTransactionManager: 266 - Committing JDBC transaction on Connection [org.hsqldb.jdbc.JDBCConnection@34bde49d]
  20:16:57,339 DEBUG .datasource.DataSourceTransactionManager: 324 - Releasing JDBC Connection [org.hsqldb.jdbc.JDBCConnection@34bde49d] after transaction
  20:16:57,339 DEBUG ramework.jdbc.datasource.DataSourceUtils: 327 - Returning JDBC Connection to DataSource
  20:16:57,339  INFO          com.manuel.jordan.main.MainTest: 104 - result: true
  20:16:57,339  INFO          com.manuel.jordan.main.MainTest: 105 - Post
  </code></pre>
  
  <p>The error was not thrown how it was expected..</p>
  
  <p><strong>Omicron</strong></p>
  
  <p>New updated code:</p>
  
  <pre><code>@Service
  @Transactional
  @Scope("prototype")
  public class WarehouseServiceImpl implements WarehouseService {
  
      private static final Logger logger = LoggerFactory.getLogger(WarehouseServiceImpl.class);
  
      private ProductService productService;
  
      @Autowired
      public WarehouseServiceImpl(ProductService productService){
          this.productService = productService;
      }
  
      @Override
      @Transactional(propagation = Propagation.REQUIRES_NEW, timeout=0)
      public boolean checkStockAvailability(Product product, BigDecimal quantity) {
  
          logger.info("Amount: {}", this.productService.getAmountProducts());
          ...     
          return true;
  
      }
  
  }
  </code></pre>
  
  <p>The code shown above is the same for the two projects, for one working with JdbcTemplate, all OK, the expected error is thrown, but the other project working with Hibernate doesn't throws the expected error. Below the result output.</p>
  
  <pre><code>08:27:06,782  INFO          com.manuel.jordan.main.MainTest: 102 - Pre
  08:27:06,782 DEBUG ctory.support.DefaultListableBeanFactory: 249 - Returning cached instance of singleton bean 'transactionManager'
  08:27:06,782 DEBUG m.hibernate4.HibernateTransactionManager: 367 - Creating new transaction with name [com.manuel.jordan.model.service.support.impl.WarehouseServiceImpl.checkStockAvailability]: PROPAGATION_REQUIRES_NEW,ISOLATION_DEFAULT,timeout_0; ''
  08:27:06,783 DEBUG m.hibernate4.HibernateTransactionManager: 417 - Opened new Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=org.hibernate.engine.spi.ExecutableList@57ce634f updates=org.hibernate.engine.spi.ExecutableList@b8a7e43 deletions=org.hibernate.engine.spi.ExecutableList@35835fa orphanRemovals=org.hibernate.engine.spi.ExecutableList@56f71edb collectionCreations=org.hibernate.engine.spi.ExecutableList@7207cb51 collectionRemovals=org.hibernate.engine.spi.ExecutableList@2a27cb34 collectionUpdates=org.hibernate.engine.spi.ExecutableList@6892cc6f collectionQueuedOps=org.hibernate.engine.spi.ExecutableList@6fd1660 unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])] for Hibernate transaction
  08:27:06,783 DEBUG m.hibernate4.HibernateTransactionManager: 427 - Preparing JDBC Connection of Hibernate Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=org.hibernate.engine.spi.ExecutableList@57ce634f updates=org.hibernate.engine.spi.ExecutableList@b8a7e43 deletions=org.hibernate.engine.spi.ExecutableList@35835fa orphanRemovals=org.hibernate.engine.spi.ExecutableList@56f71edb collectionCreations=org.hibernate.engine.spi.ExecutableList@7207cb51 collectionRemovals=org.hibernate.engine.spi.ExecutableList@2a27cb34 collectionUpdates=org.hibernate.engine.spi.ExecutableList@6892cc6f collectionQueuedOps=org.hibernate.engine.spi.ExecutableList@6fd1660 unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])]
  08:27:06,783 DEBUG gine.jdbc.internal.LogicalConnectionImpl: 226 - Obtaining JDBC connection
  08:27:06,783 DEBUG k.jdbc.datasource.SimpleDriverDataSource: 138 - Creating new JDBC Driver Connection to [jdbc:hsqldb:mem:testdb]
  08:27:06,783 DEBUG gine.jdbc.internal.LogicalConnectionImpl: 232 - Obtained JDBC connection
  08:27:06,783 DEBUG .transaction.spi.AbstractTransactionImpl: 160 - begin
  08:27:06,783 DEBUG ransaction.internal.jdbc.JdbcTransaction:  69 - initial autocommit status: true
  08:27:06,783 DEBUG ransaction.internal.jdbc.JdbcTransaction:  71 - disabling autocommit
  08:27:06,784 DEBUG m.hibernate4.HibernateTransactionManager: 488 - Exposing Hibernate transaction as JDBC transaction [org.hsqldb.jdbc.JDBCConnection@4a6c18ad]
  08:27:06,784 DEBUG ctory.support.DefaultListableBeanFactory: 249 - Returning cached instance of singleton bean 'transactionManager'
  08:27:06,784 DEBUG m.hibernate4.HibernateTransactionManager: 362 - Found thread-bound Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=org.hibernate.engine.spi.ExecutableList@57ce634f updates=org.hibernate.engine.spi.ExecutableList@b8a7e43 deletions=org.hibernate.engine.spi.ExecutableList@35835fa orphanRemovals=org.hibernate.engine.spi.ExecutableList@56f71edb collectionCreations=org.hibernate.engine.spi.ExecutableList@7207cb51 collectionRemovals=org.hibernate.engine.spi.ExecutableList@2a27cb34 collectionUpdates=org.hibernate.engine.spi.ExecutableList@6892cc6f collectionQueuedOps=org.hibernate.engine.spi.ExecutableList@6fd1660 unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])] for Hibernate transaction
  08:27:06,784 DEBUG m.hibernate4.HibernateTransactionManager: 472 - Participating in existing transaction
  08:27:06,784 DEBUG ctory.support.DefaultListableBeanFactory: 249 - Returning cached instance of singleton bean 'transactionManager'
  08:27:06,784 DEBUG m.hibernate4.HibernateTransactionManager: 362 - Found thread-bound Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=org.hibernate.engine.spi.ExecutableList@57ce634f updates=org.hibernate.engine.spi.ExecutableList@b8a7e43 deletions=org.hibernate.engine.spi.ExecutableList@35835fa orphanRemovals=org.hibernate.engine.spi.ExecutableList@56f71edb collectionCreations=org.hibernate.engine.spi.ExecutableList@7207cb51 collectionRemovals=org.hibernate.engine.spi.ExecutableList@2a27cb34 collectionUpdates=org.hibernate.engine.spi.ExecutableList@6892cc6f collectionQueuedOps=org.hibernate.engine.spi.ExecutableList@6fd1660 unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])] for Hibernate transaction
  08:27:06,784 DEBUG m.hibernate4.HibernateTransactionManager: 472 - Participating in existing transaction
  08:27:06,785 DEBUG                        org.hibernate.SQL: 109 - select count(*) as col_0_0_ from product product0_
  08:27:06,785 DEBUG              org.hibernate.loader.Loader: 951 - Result set row: 0
  08:27:06,786 DEBUG              org.hibernate.loader.Loader:1485 - Result row: 
  08:27:06,786  INFO ervice.support.impl.WarehouseServiceImpl:  45 - Amount: 6
  08:27:06,786 DEBUG m.hibernate4.HibernateTransactionManager: 755 - Initiating transaction commit
  08:27:06,786 DEBUG m.hibernate4.HibernateTransactionManager: 551 - Committing Hibernate transaction on Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=org.hibernate.engine.spi.ExecutableList@57ce634f updates=org.hibernate.engine.spi.ExecutableList@b8a7e43 deletions=org.hibernate.engine.spi.ExecutableList@35835fa orphanRemovals=org.hibernate.engine.spi.ExecutableList@56f71edb collectionCreations=org.hibernate.engine.spi.ExecutableList@7207cb51 collectionRemovals=org.hibernate.engine.spi.ExecutableList@2a27cb34 collectionUpdates=org.hibernate.engine.spi.ExecutableList@6892cc6f collectionQueuedOps=org.hibernate.engine.spi.ExecutableList@6fd1660 unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])]
  08:27:06,786 DEBUG .transaction.spi.AbstractTransactionImpl: 175 - committing
  08:27:06,786 DEBUG ransaction.internal.jdbc.JdbcTransaction: 113 - committed JDBC Connection
  08:27:06,786 DEBUG ransaction.internal.jdbc.JdbcTransaction: 126 - re-enabling autocommit
  08:27:06,787 DEBUG m.hibernate4.HibernateTransactionManager: 633 - Closing Hibernate Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=org.hibernate.engine.spi.ExecutableList@57ce634f updates=org.hibernate.engine.spi.ExecutableList@b8a7e43 deletions=org.hibernate.engine.spi.ExecutableList@35835fa orphanRemovals=org.hibernate.engine.spi.ExecutableList@56f71edb collectionCreations=org.hibernate.engine.spi.ExecutableList@7207cb51 collectionRemovals=org.hibernate.engine.spi.ExecutableList@2a27cb34 collectionUpdates=org.hibernate.engine.spi.ExecutableList@6892cc6f collectionQueuedOps=org.hibernate.engine.spi.ExecutableList@6fd1660 unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])] after transaction
  08:27:06,787 DEBUG gine.jdbc.internal.LogicalConnectionImpl: 246 - Releasing JDBC connection
  08:27:06,787 DEBUG gine.jdbc.internal.LogicalConnectionImpl: 264 - Released JDBC connection
  08:27:06,787  INFO          com.manuel.jordan.main.MainTest: 104 - result: true
  08:27:06,787  INFO          com.manuel.jordan.main.MainTest: 105 - Post
  </code></pre>
  
  <p>Some clue? DataAccess exists of course...</p>