Skip to content

Commit

Permalink
feat: Implemented to throw a runtime error if a class has @transactional
Browse files Browse the repository at this point in the history
  • Loading branch information
Jaeyoung22 authored and jhoeller committed Sep 27, 2024
1 parent e3cf23d commit cc3948e
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ public class RestrictedTransactionalEventListenerFactory extends TransactionalEv
@Override
public ApplicationListener<?> createApplicationListener(String beanName, Class<?> type, Method method) {
Transactional txAnn = AnnotatedElementUtils.findMergedAnnotation(method, Transactional.class);

if (txAnn == null) {
txAnn = AnnotatedElementUtils.findMergedAnnotation(type, Transactional.class);
}

if (txAnn != null) {
Propagation propagation = txAnn.propagation();
if (propagation != Propagation.REQUIRES_NEW && propagation != Propagation.NOT_SUPPORTED) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.RestrictedTransactionalEventListenerFactory;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.event.TransactionalApplicationListenerMethodAdapterTests.SampleEvents.SampleEventsWithTransactionalAnnotation;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.ClassUtils;
Expand Down Expand Up @@ -157,6 +158,34 @@ void withAsyncTransactionalAnnotation() {
assertThatNoException().isThrownBy(() -> factory.createApplicationListener("test", SampleEvents.class, m));
}

@Test
void withTransactionalAnnotationOnEnclosingClass() {
RestrictedTransactionalEventListenerFactory factory = new RestrictedTransactionalEventListenerFactory();
Method m = ReflectionUtils.findMethod(SampleEvents.SampleEventsWithTransactionalAnnotation.class, "defaultPhase", String.class);
assertThatIllegalStateException().isThrownBy(() -> factory.createApplicationListener("test", SampleEvents.SampleEventsWithTransactionalAnnotation.class, m));
}

@Test
void withTransactionalRequiresNewAnnotationAndTransactionalAnnotationOnEnclosingClass() {
RestrictedTransactionalEventListenerFactory factory = new RestrictedTransactionalEventListenerFactory();
Method m = ReflectionUtils.findMethod(SampleEvents.SampleEventsWithTransactionalAnnotation.class, "withTransactionalRequiresNewAnnotation", String.class);
assertThatNoException().isThrownBy(() -> factory.createApplicationListener("test", SampleEvents.SampleEventsWithTransactionalAnnotation.class, m));
}

@Test
void withTransactionalNotSupportedAnnotationAndTransactionalAnnotationOnEnclosingClass() {
RestrictedTransactionalEventListenerFactory factory = new RestrictedTransactionalEventListenerFactory();
Method m = ReflectionUtils.findMethod(SampleEvents.SampleEventsWithTransactionalAnnotation.class, "withTransactionalNotSupportedAnnotation", String.class);
assertThatNoException().isThrownBy(() -> factory.createApplicationListener("test", SampleEvents.SampleEventsWithTransactionalAnnotation.class, m));
}

@Test
void withAsyncTransactionalAnnotationAndTransactionalAnnotationOnEnclosingClass() {
RestrictedTransactionalEventListenerFactory factory = new RestrictedTransactionalEventListenerFactory();
Method m = ReflectionUtils.findMethod(SampleEvents.SampleEventsWithTransactionalAnnotation.class, "withAsyncTransactionalAnnotation", String.class);
assertThatNoException().isThrownBy(() -> factory.createApplicationListener("test", SampleEvents.SampleEventsWithTransactionalAnnotation.class, m));
}


private static void assertPhase(Method method, TransactionPhase expected) {
assertThat(method).as("Method must not be null").isNotNull();
Expand Down Expand Up @@ -248,6 +277,29 @@ public void withTransactionalNotSupportedAnnotation(String data) {
@Async @Transactional(propagation = Propagation.REQUIRES_NEW)
public void withAsyncTransactionalAnnotation(String data) {
}

@Transactional
static class SampleEventsWithTransactionalAnnotation {

@TransactionalEventListener
public void defaultPhase(String data) {
}

@TransactionalEventListener
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void withTransactionalRequiresNewAnnotation(String data) {
}

@TransactionalEventListener
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void withTransactionalNotSupportedAnnotation(String data) {
}

@TransactionalEventListener
@Async @Transactional(propagation = Propagation.REQUIRES_NEW)
public void withAsyncTransactionalAnnotation(String data) {
}
}
}

}

0 comments on commit cc3948e

Please sign in to comment.