From 2d22b24de48e2cc24156a2b042660d2b8e5778c7 Mon Sep 17 00:00:00 2001 From: Oliver Drotbohm Date: Sun, 19 Nov 2023 21:44:37 +0100 Subject: [PATCH] GH-381 - Propagate original exception from CompletionRegisteringAdvisor. We now propagate potentially occurring exceptions in CompletionRegisteringAdvisor to make sure the standard exception handling facilities kick in, both for synchronous and asynchronous listener invocations. --- .../support/CompletionRegisteringAdvisor.java | 7 +++---- .../PersistentApplicationEventMulticaster.java | 18 +++++++++++------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/spring-modulith-events/spring-modulith-events-core/src/main/java/org/springframework/modulith/events/support/CompletionRegisteringAdvisor.java b/spring-modulith-events/spring-modulith-events-core/src/main/java/org/springframework/modulith/events/support/CompletionRegisteringAdvisor.java index aaa669b1..36054b8a 100644 --- a/spring-modulith-events/spring-modulith-events-core/src/main/java/org/springframework/modulith/events/support/CompletionRegisteringAdvisor.java +++ b/spring-modulith-events/spring-modulith-events-core/src/main/java/org/springframework/modulith/events/support/CompletionRegisteringAdvisor.java @@ -23,7 +23,6 @@ import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.aop.Advisor; import org.springframework.aop.MethodMatcher; import org.springframework.aop.Pointcut; import org.springframework.aop.support.AbstractPointcutAdvisor; @@ -41,8 +40,8 @@ import org.springframework.util.Assert; import org.springframework.util.ConcurrentLruCache; /** - * An {@link Advisor} to decorate {@link TransactionalEventListener} annotated methods to mark the previously registered - * event publications as completed on successful method execution. + * An {@link org.springframework.aop.Advisor} to decorate {@link TransactionalEventListener} annotated methods to mark + * the previously registered event publications as completed on successful method execution. * * @author Oliver Drotbohm */ @@ -177,7 +176,7 @@ public class CompletionRegisteringAdvisor extends AbstractPointcutAdvisor { method, o_O.getMessage()); } - return result; + throw o_O; } // Mark publication complete if the method is a transactional event listener. diff --git a/spring-modulith-events/spring-modulith-events-core/src/main/java/org/springframework/modulith/events/support/PersistentApplicationEventMulticaster.java b/spring-modulith-events/spring-modulith-events-core/src/main/java/org/springframework/modulith/events/support/PersistentApplicationEventMulticaster.java index d3748b45..0001cd1b 100644 --- a/spring-modulith-events/spring-modulith-events-core/src/main/java/org/springframework/modulith/events/support/PersistentApplicationEventMulticaster.java +++ b/spring-modulith-events/spring-modulith-events-core/src/main/java/org/springframework/modulith/events/support/PersistentApplicationEventMulticaster.java @@ -29,7 +29,6 @@ import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; import org.springframework.context.PayloadApplicationEvent; import org.springframework.context.event.AbstractApplicationEventMulticaster; -import org.springframework.context.event.ApplicationEventMulticaster; import org.springframework.context.event.ApplicationListenerMethodAdapter; import org.springframework.core.ResolvableType; import org.springframework.core.annotation.AnnotationAwareOrderComparator; @@ -41,14 +40,13 @@ import org.springframework.modulith.events.core.EventPublicationRegistry; import org.springframework.modulith.events.core.PublicationTargetIdentifier; import org.springframework.transaction.event.TransactionPhase; import org.springframework.transaction.event.TransactionalApplicationListener; -import org.springframework.transaction.event.TransactionalEventListener; import org.springframework.util.Assert; import org.springframework.util.ReflectionUtils; /** - * An {@link ApplicationEventMulticaster} to register {@link EventPublication}s in an {@link EventPublicationRegistry} - * so that potentially failing transactional event listeners can get re-invoked upon application restart or via a - * schedule. + * An {@link org.springframework.context.event.ApplicationEventMulticaster} to register {@link EventPublication}s in an + * {@link EventPublicationRegistry} so that potentially failing transactional event listeners can get re-invoked upon + * application restart or via a schedule. *

* Republication is handled in {@link #afterSingletonsInstantiated()} inspecting the {@link EventPublicationRegistry} * for incomplete publications and @@ -174,7 +172,13 @@ public class PersistentApplicationEventMulticaster extends AbstractApplicationEv private ApplicationListener executeListenerWithCompletion(EventPublication publication, TransactionalApplicationListener listener) { - listener.processEvent(publication.getApplicationEvent()); + try { + listener.processEvent(publication.getApplicationEvent()); + } catch (Exception o_O) { + if (LOGGER.isErrorEnabled()) { + LOGGER.error("Error republishing event publication " + publication, o_O); + } + } return listener; } @@ -212,7 +216,7 @@ public class PersistentApplicationEventMulticaster extends AbstractApplicationEv * implement {@link TransactionalApplicationListener}. * * @author Oliver Drotbohm - * @see TransactionalEventListener + * @see org.springframework.transaction.event.TransactionalEventListener * @see TransactionalApplicationListener */ static class TransactionalEventListeners {