TransactionalInterceptor implements MethodInterceptor { public Object invoke(MethodInvocation invocation) throws Throwable { final Method method = invocation.getMethod(); if(method == null) { return null; } Transactional txa = method.getAnnotation(Transactional.class); if (txa == null) { return invocation.proceed(); } Transaction tx = manager.getCurrentTransaction(); final boolean transactionStarted; if (tx == null || !txa.propagationRequired()) { tx = manager.beginTransaction(txa.isolated()); transactionStarted = true; } else { transactionStarted = false; } try { Object obj = invocation.proceed(); if (transactionStarted) { tx.commit(); } return obj; } catch (Exception ex) { if (transactionStarted) { tx.rollback(); } throw ex; } }  Object invoke(MethodInvocation invocation);  }
@Test public void testNullMethod() throws Throwable { final MethodInvocation invocation = mockery.mock(MethodInvocation.class); mockery.checking(new Expectations() { { exactly(1).of(invocation).getMethod(); will(returnValue(null)); } }); interceptor.invoke(invocation); mockery.assertIsSatisfied(); }
@Test public void testNullAnnotation() throws Throwable { final MethodInvocation invocation = mockery.mock(MethodInvocation.class); mockery.checking(new Expectations() { { exactly(1).of(invocation).getMethod(); will(returnValue(nonTransaction)); exactly(1).of(invocation).proceed(); will(returnValue(sampleService)); } }); Assert.assertSame(sampleService, interceptor.invoke(invocation)); mockery.assertIsSatisfied(); }
@Test public void testNewTransactionWithSuccess() throws Throwable { final MethodInvocation invocation = mockery.mock(MethodInvocation.class); mockery.checking(new Expectations() { { Sequence seq = mockery.sequence("newTx"); exactly(1).of(invocation).getMethod(); will(returnValue(propagtedIsolatedTransaction)); inSequence(seq); exactly(1).of(mockManager).getCurrentTransaction(); will(returnValue(null)); inSequence(seq); Transaction tx = mockery.mock(Transaction.class); exactly(1).of(mockManager).beginTransaction(true); will(returnValue(tx)); inSequence(seq); exactly(1).of(invocation).proceed(); will(returnValue(sampleService)); inSequence(seq); exactly(1).of(tx).commit(); inSequence(seq); } }); Assert.assertSame(sampleService, interceptor.invoke(invocation)); mockery.assertIsSatisfied(); }
@Test(expected = TransactionException.class) public void testNewTransactionWithError() throws Throwable { final MethodInvocation invocation = mockery.mock(MethodInvocation.class); mockery.checking(new Expectations() { { Sequence seq = mockery.sequence("newTxWithError"); exactly(1).of(invocation).getMethod(); will(returnValue(propagtedIsolatedTransaction)); inSequence(seq); exactly(1).of(mockManager).getCurrentTransaction(); will(returnValue(null)); inSequence(seq); Transaction tx = mockery.mock(Transaction.class); exactly(1).of(mockManager).beginTransaction(true); will(returnValue(tx)); inSequence(seq); exactly(1).of(invocation).proceed(); will(throwException(new TransactionException(new NullPointerException()))); inSequence(seq); exactly(1).of(tx).rollback(); inSequence(seq); } }); try { interceptor.invoke(invocation); } finally { mockery.assertIsSatisfied(); } }
@Test public void testNewNonIsolatedTransactionWithSuccess() throws Throwable { final MethodInvocation invocation = mockery.mock(MethodInvocation.class); mockery.checking(new Expectations() { { Sequence seq = mockery.sequence("newTx"); exactly(1).of(invocation).getMethod(); will(returnValue(propagtedNonIsolatedTransaction)); inSequence(seq); exactly(1).of(mockManager).getCurrentTransaction(); will(returnValue(null)); inSequence(seq); Transaction tx = mockery.mock(Transaction.class); exactly(1).of(mockManager).beginTransaction(false); will(returnValue(tx)); inSequence(seq); exactly(1).of(invocation).proceed(); will(returnValue(sampleService)); inSequence(seq); exactly(1).of(tx).commit(); inSequence(seq); } }); Assert.assertSame(sampleService, interceptor.invoke(invocation)); mockery.assertIsSatisfied(); }
@Test public void testNestedTransactionWithoutPropagationWithSuccess() throws Throwable { final MethodInvocation invocation = mockery.mock(MethodInvocation.class); mockery.checking(new Expectations() { { Sequence seq = mockery.sequence("newTx"); Transaction tx = mockery.mock(Transaction.class, "tx0"); exactly(1).of(mockManager).beginTransaction(true); will(returnValue(tx)); inSequence(seq); exactly(1).of(invocation).getMethod(); will(returnValue(nonPropagtedIsolatedNestedTransaction)); inSequence(seq); exactly(1).of(mockManager).getCurrentTransaction(); will(returnValue(tx)); inSequence(seq); Transaction tx1 = mockery.mock(Transaction.class, "tx1"); exactly(1).of(mockManager).beginTransaction(true); will(returnValue(tx1)); inSequence(seq); exactly(1).of(invocation).proceed(); will(returnValue(sampleService)); inSequence(seq); exactly(1).of(tx1).commit(); inSequence(seq); exactly(1).of(tx).commit(); inSequence(seq); } }); TransactionManager manager = injector.getInstance(TransactionManager.class); Transaction tx = manager.beginTransaction(true); try { Assert.assertSame(sampleService, interceptor.invoke(invocation)); } finally { tx.commit(); } mockery.assertIsSatisfied(); }
@Test public void testNestedTransactionWithPropagationWithSuccess() throws Throwable { final MethodInvocation invocation = mockery.mock(MethodInvocation.class); mockery.checking(new Expectations() { { Sequence seq = mockery.sequence("newTx"); Transaction tx = mockery.mock(Transaction.class, "tx0"); exactly(1).of(mockManager).beginTransaction(true); will(returnValue(tx)); inSequence(seq); exactly(1).of(invocation).getMethod(); will(returnValue(propagtedIsolatedNestedTransaction)); inSequence(seq); exactly(1).of(mockManager).getCurrentTransaction(); will(returnValue(tx)); inSequence(seq); exactly(1).of(invocation).proceed(); will(returnValue(sampleService)); inSequence(seq); exactly(1).of(tx).commit(); inSequence(seq); } }); TransactionManager manager = injector.getInstance(TransactionManager.class); Transaction tx = manager.beginTransaction(true); try { Assert.assertSame(sampleService, interceptor.invoke(invocation)); } finally { tx.commit(); } mockery.assertIsSatisfied(); }