diff --git a/extensions/persist/src/com/google/inject/persist/jpa/JpaLocalTxnInterceptor.java b/extensions/persist/src/com/google/inject/persist/jpa/JpaLocalTxnInterceptor.java index 7fe6982505..db55de2e7f 100644 --- a/extensions/persist/src/com/google/inject/persist/jpa/JpaLocalTxnInterceptor.java +++ b/extensions/persist/src/com/google/inject/persist/jpa/JpaLocalTxnInterceptor.java @@ -82,7 +82,13 @@ public Object invoke(MethodInvocation methodInvocation) throws Throwable { //everything was normal so commit the txn (do not move into try block above as it // interferes with the advised method's throwing semantics) try { - txn.commit(); + if (txn.isActive()) { + if (txn.getRollbackOnly()) { + txn.rollback(); + } else { + txn.commit(); + } + } } finally { //close the em if necessary if (null != didWeStartWork.get()) { diff --git a/extensions/persist/test/com/google/inject/persist/jpa/ManagedLocalTransactionsTest.java b/extensions/persist/test/com/google/inject/persist/jpa/ManagedLocalTransactionsTest.java index 167d6a4c14..0db032ad8b 100644 --- a/extensions/persist/test/com/google/inject/persist/jpa/ManagedLocalTransactionsTest.java +++ b/extensions/persist/test/com/google/inject/persist/jpa/ManagedLocalTransactionsTest.java @@ -22,14 +22,18 @@ import com.google.inject.persist.PersistService; import com.google.inject.persist.Transactional; import com.google.inject.persist.UnitOfWork; + import java.io.IOException; import java.util.Date; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.NoResultException; + import junit.framework.TestCase; -/** @author Dhanji R. Prasanna (dhanji@gmail.com) */ +/** + * @author Dhanji R. Prasanna (dhanji@gmail.com) + */ public class ManagedLocalTransactionsTest extends TestCase { private Injector injector; @@ -146,6 +150,53 @@ public void testSimpleTransactionRollbackOnUnchecked() { } } + public void testSimpleTransactionRollbackPerformedManuallyWithoutException() { + try { + injector.getInstance(TransactionalObject.class).runOperationInTxnWithManualRollback(); + } catch (RuntimeException re) { + fail("finishing the transactional resulted in an exception"); + } + + EntityManager em = injector.getInstance(EntityManager.class); + assertFalse( + "Session was not closed by transactional service (rollback didnt happen?)", + em.getTransaction().isActive()); + + try { + Object result = + em.createQuery("from JpaTestEntity where text = :text") + .setParameter("text", TRANSIENT_UNIQUE_TEXT) + .getSingleResult(); + injector.getInstance(UnitOfWork.class).end(); + fail("a result was returned! rollback sure didnt happen!!!"); + } catch (NoResultException e) { + } + } + + public void testSimpleTransactionRollbackOnlySetWithoutException() { + try { + injector.getInstance(TransactionalObject.class).runOperationInTxnWithRollbackOnlySet(); + } catch (RuntimeException re) { + fail("finishing the transactional resulted in an exception"); + } + + EntityManager em = injector.getInstance(EntityManager.class); + assertFalse( + "Session was not closed by transactional service (rollback didnt happen?)", + em.getTransaction().isActive()); + + try { + Object result = + em.createQuery("from JpaTestEntity where text = :text") + .setParameter("text", TRANSIENT_UNIQUE_TEXT) + .getSingleResult(); + injector.getInstance(UnitOfWork.class).end(); + fail("a result was returned! rollback sure didnt happen!!!"); + } catch (NoResultException e) { + } + } + + public static class TransactionalObject { private final EntityManager em; @@ -185,5 +236,23 @@ public void runOperationInTxnThrowingUnchecked() { throw new IllegalStateException(); } + + @Transactional + public void runOperationInTxnWithManualRollback() { + JpaTestEntity entity = new JpaTestEntity(); + entity.setText(TRANSIENT_UNIQUE_TEXT); + em.persist(entity); + + em.getTransaction().rollback(); + } + + @Transactional + public void runOperationInTxnWithRollbackOnlySet() { + JpaTestEntity entity = new JpaTestEntity(); + entity.setText(TRANSIENT_UNIQUE_TEXT); + em.persist(entity); + + em.getTransaction().setRollbackOnly(); + } } }