diff --git a/spring-tx/src/main/java/org/springframework/transaction/event/TransactionalApplicationListenerMethodAdapter.java b/spring-tx/src/main/java/org/springframework/transaction/event/TransactionalApplicationListenerMethodAdapter.java index fee049cacc..bca785fd90 100644 --- a/spring-tx/src/main/java/org/springframework/transaction/event/TransactionalApplicationListenerMethodAdapter.java +++ b/spring-tx/src/main/java/org/springframework/transaction/event/TransactionalApplicationListenerMethodAdapter.java @@ -26,6 +26,7 @@ import org.springframework.context.event.EventListener; import org.springframework.context.event.GenericApplicationListener; import org.springframework.core.annotation.AnnotatedElementUtils; import org.springframework.scheduling.annotation.Async; +import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.util.Assert; @@ -65,18 +66,19 @@ public class TransactionalApplicationListenerMethodAdapter extends ApplicationLi */ public TransactionalApplicationListenerMethodAdapter(String beanName, Class targetClass, Method method) { super(beanName, targetClass, method); - TransactionalEventListener ann = + TransactionalEventListener eventAnn = AnnotatedElementUtils.findMergedAnnotation(method, TransactionalEventListener.class); - if (ann == null) { + if (eventAnn == null) { throw new IllegalStateException("No TransactionalEventListener annotation found on method: " + method); } - if (AnnotatedElementUtils.hasAnnotation(method, Transactional.class) && + Transactional txAnn = AnnotatedElementUtils.findMergedAnnotation(method, Transactional.class); + if (txAnn != null && txAnn.propagation() != Propagation.REQUIRES_NEW && !AnnotatedElementUtils.hasAnnotation(method, Async.class)) { - throw new IllegalStateException("@TransactionalEventListener method must not be annotated " + - "with @Transactional, unless when declared as @Async: " + method); + throw new IllegalStateException("@TransactionalEventListener method must not be annotated with " + + "@Transactional unless when marked as REQUIRES_NEW or declared as @Async: " + method); } - this.annotation = ann; - this.transactionPhase = ann.phase(); + this.annotation = eventAnn; + this.transactionPhase = eventAnn.phase(); } diff --git a/spring-tx/src/test/java/org/springframework/transaction/event/TransactionalApplicationListenerMethodAdapterTests.java b/spring-tx/src/test/java/org/springframework/transaction/event/TransactionalApplicationListenerMethodAdapterTests.java index 89ca5af442..9e338b3630 100644 --- a/spring-tx/src/test/java/org/springframework/transaction/event/TransactionalApplicationListenerMethodAdapterTests.java +++ b/spring-tx/src/test/java/org/springframework/transaction/event/TransactionalApplicationListenerMethodAdapterTests.java @@ -25,6 +25,7 @@ import org.springframework.context.event.ApplicationListenerMethodAdapter; import org.springframework.core.ResolvableType; import org.springframework.core.annotation.AnnotatedElementUtils; import org.springframework.scheduling.annotation.Async; +import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.support.TransactionSynchronization; import org.springframework.transaction.support.TransactionSynchronizationManager; @@ -132,6 +133,13 @@ public class TransactionalApplicationListenerMethodAdapterTests { assertThatIllegalStateException().isThrownBy(() -> createTestInstance(m)); } + @Test + public void withTransactionalRequiresNewAnnotation() { + Method m = ReflectionUtils.findMethod(SampleEvents.class, "withTransactionalRequiresNewAnnotation", String.class); + supportsEventType(true, m, createGenericEventType(String.class)); + supportsEventType(false, m, createGenericEventType(Double.class)); + } + @Test public void withAsyncTransactionalAnnotation() { Method m = ReflectionUtils.findMethod(SampleEvents.class, "withAsyncTransactionalAnnotation", String.class); @@ -216,6 +224,11 @@ public class TransactionalApplicationListenerMethodAdapterTests { public void withTransactionalAnnotation(String data) { } + @TransactionalEventListener + @Transactional(propagation = Propagation.REQUIRES_NEW) + public void withTransactionalRequiresNewAnnotation(String data) { + } + @TransactionalEventListener @Async @Transactional public void withAsyncTransactionalAnnotation(String data) {