title: Spring + Hibernate manually creating transactions, PROPAGATION_REQUIRED fails. BUG?
body: <p><strong>PLEASE DO NOT RECOMMEND THAT I USE TRANSACTION ANNOTAIONS FOR THIS.</strong></p>
  
  <p>I have run into what appears to be a bug, related to Spring handling of transactions. </p>
  
  <p>Please have a look at these two test cases, comments are in the code: </p>
  
  <p>Entity class for example: </p>
  
  <pre><code>@Entity
  public class Person{
      @Id
      String name;
  }
  </code></pre>
  
  <p>Some methods used:</p>
  
  <pre><code>public TransactionStatus requireTransaction() {
          TransactionTemplate template = new TransactionTemplate();
          template.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
          return getTransactionManager().getTransaction(template);
  }
  
  public Session session() {
          return getRepository().session();
  }
  
  public PlatformTransactionManager getTransactionManager() {
          return getRepository().getTransactionManager();
  }
  </code></pre>
  
  <p>Here is the first test, testA();</p>
  
  <pre><code>@Test
  public void testA() throws InterruptedException {
          // We create the first transaction
          TransactionStatus statusOne = requireTransaction();
  
          // Create person one
          Person pOne = new Person();
          pOne.name = "PersonOne";
          session().persist(pOne);
  
          // ---&gt; 111) NOTE! We do not commit! Intentionally!
  
          // We requireTransaction again. We should be getting the same transaction status.
  
          TransactionStatus statusTwo = requireTransaction();
          if ( !statusTwo.isNewTransaction() ) {
                  System.out.println("isNewTransaction: false! As expected! Meaning we are getting the original transaction status!");
          }
  
  
          // Create person two
          Person pTwo = new Person();
          pTwo.name = "PersonTwo";
          session().persist(pTwo);
  
          // We will now be committing statusTwo which should actually be the first one, statusOne,
          // since we are using propagation required and the previous transaction was never committed
          // or rolledback or completed in any other fashion!
  
          getTransactionManager().commit(statusTwo);
  
          // !!!!!!! However !!!!!! Nothing is actually written to the database here!
  
          // This must be a bug. It existed on Spring 4.0.4 and I have upgraded to 4.2.0 and still the same thing happens!
  
          // Lets go on to the next test. testB() below.
  
          // If we now, at 111) instead do, let me repeat the entire logic:
  }
  </code></pre>
  
  <p>Here is the second test, testA();</p>
  
  <pre><code>@Test
  public void testB() throws InterruptedException {
          // We create the first transaction
          TransactionStatus statusOne = requireTransaction();
  
          Person pOne = new Person();
          pOne.name = "PersonOne";
          session().persist(pOne);
  
          // -----&gt; 111) NOW WE ARE COMMITTING INSTEAD, SINCE WE ARE ALMOST FORCED TO BUT DO NOT WANT TO
          getTransactionManager().commit(statusOne);
  
          // ----&gt; 222) HOWEVER, NOW WE WILL NOT BE ABLE TO ROLLBACK THIS AT A LATER POINT
  
          // We requireTransaction again. We should be getting A NEW transaction status.
  
          TransactionStatus statusTwo = requireTransaction();
          if ( statusTwo.isNewTransaction() ) {
                  System.out.println("isNewTransaction: true! As expected! Meaning we are getting a new transaction status!");
          }
  
          Person pTwo = new Person();
          pTwo.name = "PersonTwo";
          session().persist(pTwo);
  
          getTransactionManager().commit(statusTwo);
  
          // Now we will have two instances in the database, as expected.
  
          // If we instead of committing statusTwo would have done:
          // getTransactionManager().rollback(statusTwo)
          // then only the last one will be rolledback which is not desired!
  
          // Why are we forced to commit the first one to have any effect on future transactions!
          // Delegation will not work like this!
  }
  </code></pre>
  
  <p>Was that clear? </p>
  
  <p>This is obviously a bug, is it not? </p>
  
  <p>Why purpose would requireTransaction with PROPAGATION_REQUIRED have other than destroy future commits by the same thread? </p>
  
  <p>Why is the commit on <strong>statusTwo</strong> in <strong>testA()</strong> not sufficient to commit the work on the first one as well?</p>
  
  <p>Should this be done some other way? I think not, right? Bug!</p>
  
  <p><strong>EDIT</strong>
  For those that suggest that I use execute method, fine: </p>
  
  <pre><code>public PlatformTransactionManager getTransactionManager() {
              return /** implement this **/ ; 
  }
  
  @Test
  public void testAA() throws InterruptedException {
          insertPerson1();
          insertPerson2();
  }
  
  public void requireTransaction(TransactionCallback&lt;Object&gt; action) {
          TransactionTemplate template = new TransactionTemplate(getTransactionManager());
          template.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);        
          template.execute(action);
  }
  
  
  public void insertPerson1() {
          requireTransaction(new TransactionCallback&lt;Object&gt;() {
                  @Override
                  public Object doInTransaction(TransactionStatus status) {
                          Person pOne = new Person();
                          pOne.name = "PersonOne";
                          session().persist(pOne);
  
                          return null;
                  }
          });
  }
  
  public void insertPerson2() {
          requireTransaction(new TransactionCallback&lt;Object&gt;() {
                  @Override
                  public Object doInTransaction(TransactionStatus status) {
                          Person pTwo = new Person();
                          pTwo.name = "PersonTwo";
                          session().persist(pTwo);
  
                          if ( true ) {
                                  status.setRollbackOnly();
                                  // throw new RuntimeException("aaaaaaa");
                          }
  
                          return null;
                  }
          });
  }
  </code></pre>
  
  <p>On insertPerson2, even if I set to rollback, or throw an exception the <strong>first person is still inserted!</strong></p>
  
  <p>That means, not one shared transaction, but actually two separate ones. </p>