|
|
|
@ -16,14 +16,10 @@ |
|
|
|
|
|
|
|
|
|
|
|
package org.springframework.transaction.aspectj; |
|
|
|
package org.springframework.transaction.aspectj; |
|
|
|
|
|
|
|
|
|
|
|
import java.lang.reflect.Method; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import org.junit.Before; |
|
|
|
import org.junit.Before; |
|
|
|
import org.junit.Test; |
|
|
|
import org.junit.Test; |
|
|
|
|
|
|
|
|
|
|
|
import org.springframework.tests.transaction.CallCountingTransactionManager; |
|
|
|
import org.springframework.tests.transaction.CallCountingTransactionManager; |
|
|
|
import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource; |
|
|
|
|
|
|
|
import org.springframework.transaction.interceptor.TransactionAttribute; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import static org.junit.Assert.*; |
|
|
|
import static org.junit.Assert.*; |
|
|
|
|
|
|
|
|
|
|
|
@ -65,7 +61,7 @@ public class TransactionAspectTests { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
@Test |
|
|
|
public void testCommitOnAnnotatedProtectedMethod() throws Throwable { |
|
|
|
public void commitOnAnnotatedProtectedMethod() throws Throwable { |
|
|
|
txManager.clear(); |
|
|
|
txManager.clear(); |
|
|
|
assertEquals(0, txManager.begun); |
|
|
|
assertEquals(0, txManager.begun); |
|
|
|
beanWithAnnotatedProtectedMethod.doInTransaction(); |
|
|
|
beanWithAnnotatedProtectedMethod.doInTransaction(); |
|
|
|
@ -73,7 +69,7 @@ public class TransactionAspectTests { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
@Test |
|
|
|
public void testCommitOnAnnotatedPrivateMethod() throws Throwable { |
|
|
|
public void commitOnAnnotatedPrivateMethod() throws Throwable { |
|
|
|
txManager.clear(); |
|
|
|
txManager.clear(); |
|
|
|
assertEquals(0, txManager.begun); |
|
|
|
assertEquals(0, txManager.begun); |
|
|
|
beanWithAnnotatedPrivateMethod.doSomething(); |
|
|
|
beanWithAnnotatedPrivateMethod.doSomething(); |
|
|
|
@ -81,15 +77,15 @@ public class TransactionAspectTests { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
@Test |
|
|
|
public void testNoCommitOnNonAnnotatedNonPublicMethodInTransactionalType() throws Throwable { |
|
|
|
public void commitOnNonAnnotatedNonPublicMethodInTransactionalType() throws Throwable { |
|
|
|
txManager.clear(); |
|
|
|
txManager.clear(); |
|
|
|
assertEquals(0,txManager.begun); |
|
|
|
assertEquals(0, txManager.begun); |
|
|
|
annotationOnlyOnClassWithNoInterface.nonTransactionalMethod(); |
|
|
|
annotationOnlyOnClassWithNoInterface.nonTransactionalMethod(); |
|
|
|
assertEquals(0,txManager.begun); |
|
|
|
assertEquals(0, txManager.begun); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
@Test |
|
|
|
public void testCommitOnAnnotatedMethod() throws Throwable { |
|
|
|
public void commitOnAnnotatedMethod() throws Throwable { |
|
|
|
txManager.clear(); |
|
|
|
txManager.clear(); |
|
|
|
assertEquals(0, txManager.begun); |
|
|
|
assertEquals(0, txManager.begun); |
|
|
|
methodAnnotationOnly.echo(null); |
|
|
|
methodAnnotationOnly.echo(null); |
|
|
|
@ -97,7 +93,7 @@ public class TransactionAspectTests { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
@Test |
|
|
|
public void testNotTransactional() throws Throwable { |
|
|
|
public void notTransactional() throws Throwable { |
|
|
|
txManager.clear(); |
|
|
|
txManager.clear(); |
|
|
|
assertEquals(0, txManager.begun); |
|
|
|
assertEquals(0, txManager.begun); |
|
|
|
new NotTransactional().noop(); |
|
|
|
new NotTransactional().noop(); |
|
|
|
@ -105,15 +101,10 @@ public class TransactionAspectTests { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
@Test |
|
|
|
public void testDefaultCommitOnAnnotatedClass() throws Throwable { |
|
|
|
public void defaultCommitOnAnnotatedClass() throws Throwable { |
|
|
|
final Exception ex = new Exception(); |
|
|
|
final Exception ex = new Exception(); |
|
|
|
try { |
|
|
|
try { |
|
|
|
testRollback(new TransactionOperationCallback() { |
|
|
|
testRollback(() -> annotationOnlyOnClassWithNoInterface.echo(ex), false); |
|
|
|
@Override |
|
|
|
|
|
|
|
public Object performTransactionalOperation() throws Throwable { |
|
|
|
|
|
|
|
return annotationOnlyOnClassWithNoInterface.echo(ex); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}, false); |
|
|
|
|
|
|
|
fail("Should have thrown Exception"); |
|
|
|
fail("Should have thrown Exception"); |
|
|
|
} |
|
|
|
} |
|
|
|
catch (Exception ex2) { |
|
|
|
catch (Exception ex2) { |
|
|
|
@ -122,15 +113,10 @@ public class TransactionAspectTests { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
@Test |
|
|
|
public void testDefaultRollbackOnAnnotatedClass() throws Throwable { |
|
|
|
public void defaultRollbackOnAnnotatedClass() throws Throwable { |
|
|
|
final RuntimeException ex = new RuntimeException(); |
|
|
|
final RuntimeException ex = new RuntimeException(); |
|
|
|
try { |
|
|
|
try { |
|
|
|
testRollback(new TransactionOperationCallback() { |
|
|
|
testRollback(() -> annotationOnlyOnClassWithNoInterface.echo(ex), true); |
|
|
|
@Override |
|
|
|
|
|
|
|
public Object performTransactionalOperation() throws Throwable { |
|
|
|
|
|
|
|
return annotationOnlyOnClassWithNoInterface.echo(ex); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}, true); |
|
|
|
|
|
|
|
fail("Should have thrown RuntimeException"); |
|
|
|
fail("Should have thrown RuntimeException"); |
|
|
|
} |
|
|
|
} |
|
|
|
catch (RuntimeException ex2) { |
|
|
|
catch (RuntimeException ex2) { |
|
|
|
@ -139,15 +125,10 @@ public class TransactionAspectTests { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
@Test |
|
|
|
public void testDefaultCommitOnSubclassOfAnnotatedClass() throws Throwable { |
|
|
|
public void defaultCommitOnSubclassOfAnnotatedClass() throws Throwable { |
|
|
|
final Exception ex = new Exception(); |
|
|
|
final Exception ex = new Exception(); |
|
|
|
try { |
|
|
|
try { |
|
|
|
testRollback(new TransactionOperationCallback() { |
|
|
|
testRollback(() -> new SubclassOfClassWithTransactionalAnnotation().echo(ex), false); |
|
|
|
@Override |
|
|
|
|
|
|
|
public Object performTransactionalOperation() throws Throwable { |
|
|
|
|
|
|
|
return new SubclassOfClassWithTransactionalAnnotation().echo(ex); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}, false); |
|
|
|
|
|
|
|
fail("Should have thrown Exception"); |
|
|
|
fail("Should have thrown Exception"); |
|
|
|
} |
|
|
|
} |
|
|
|
catch (Exception ex2) { |
|
|
|
catch (Exception ex2) { |
|
|
|
@ -156,15 +137,10 @@ public class TransactionAspectTests { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
@Test |
|
|
|
public void testDefaultCommitOnSubclassOfClassWithTransactionalMethodAnnotated() throws Throwable { |
|
|
|
public void defaultCommitOnSubclassOfClassWithTransactionalMethodAnnotated() throws Throwable { |
|
|
|
final Exception ex = new Exception(); |
|
|
|
final Exception ex = new Exception(); |
|
|
|
try { |
|
|
|
try { |
|
|
|
testRollback(new TransactionOperationCallback() { |
|
|
|
testRollback(() -> new SubclassOfClassWithTransactionalMethodAnnotation().echo(ex), false); |
|
|
|
@Override |
|
|
|
|
|
|
|
public Object performTransactionalOperation() throws Throwable { |
|
|
|
|
|
|
|
return new SubclassOfClassWithTransactionalMethodAnnotation().echo(ex); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}, false); |
|
|
|
|
|
|
|
fail("Should have thrown Exception"); |
|
|
|
fail("Should have thrown Exception"); |
|
|
|
} |
|
|
|
} |
|
|
|
catch (Exception ex2) { |
|
|
|
catch (Exception ex2) { |
|
|
|
@ -173,41 +149,19 @@ public class TransactionAspectTests { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
@Test |
|
|
|
public void testDefaultCommitOnImplementationOfAnnotatedInterface() throws Throwable { |
|
|
|
public void noCommitOnImplementationOfAnnotatedInterface() throws Throwable { |
|
|
|
final Exception ex = new Exception(); |
|
|
|
final Exception ex = new Exception(); |
|
|
|
testNotTransactional(new TransactionOperationCallback() { |
|
|
|
testNotTransactional(() -> new ImplementsAnnotatedInterface().echo(ex), ex); |
|
|
|
@Override |
|
|
|
|
|
|
|
public Object performTransactionalOperation() throws Throwable { |
|
|
|
|
|
|
|
return new ImplementsAnnotatedInterface().echo(ex); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}, ex); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Note: resolution does not occur. Thus we can't make a class transactional if |
|
|
|
|
|
|
|
* it implements a transactionally annotated interface. This behavior could only |
|
|
|
|
|
|
|
* be changed in AbstractFallbackTransactionAttributeSource in Spring proper. |
|
|
|
|
|
|
|
* See SPR-14322. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
@Test |
|
|
|
@Test |
|
|
|
public void testDoesNotResolveTxAnnotationOnMethodFromClassImplementingAnnotatedInterface() throws Exception { |
|
|
|
public void noRollbackOnImplementationOfAnnotatedInterface() throws Throwable { |
|
|
|
AnnotationTransactionAttributeSource atas = new AnnotationTransactionAttributeSource(); |
|
|
|
|
|
|
|
Method method = ImplementsAnnotatedInterface.class.getMethod("echo", Throwable.class); |
|
|
|
|
|
|
|
TransactionAttribute ta = atas.getTransactionAttribute(method, ImplementsAnnotatedInterface.class); |
|
|
|
|
|
|
|
assertNull(ta); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
|
|
|
public void testDefaultRollbackOnImplementationOfAnnotatedInterface() throws Throwable { |
|
|
|
|
|
|
|
final Exception rollbackProvokingException = new RuntimeException(); |
|
|
|
final Exception rollbackProvokingException = new RuntimeException(); |
|
|
|
testNotTransactional(new TransactionOperationCallback() { |
|
|
|
testNotTransactional(() -> new ImplementsAnnotatedInterface().echo(rollbackProvokingException), |
|
|
|
@Override |
|
|
|
rollbackProvokingException); |
|
|
|
public Object performTransactionalOperation() throws Throwable { |
|
|
|
|
|
|
|
return new ImplementsAnnotatedInterface().echo(rollbackProvokingException); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}, rollbackProvokingException); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected void testRollback(TransactionOperationCallback toc, boolean rollback) throws Throwable { |
|
|
|
protected void testRollback(TransactionOperationCallback toc, boolean rollback) throws Throwable { |
|
|
|
txManager.clear(); |
|
|
|
txManager.clear(); |
|
|
|
assertEquals(0, txManager.begun); |
|
|
|
assertEquals(0, txManager.begun); |
|
|
|
|