diff --git a/.github/workflows/integration.yaml b/.github/workflows/integration.yaml index 35328cf9..5b8b09fb 100644 --- a/.github/workflows/integration.yaml +++ b/.github/workflows/integration.yaml @@ -10,6 +10,8 @@ jobs: strategy: matrix: version: + - '3.1.5' + - '3.1.6-SNAPSHOT' - '3.2.0-SNAPSHOT' name: Build against Boot ${{ matrix.version }} runs-on: ubuntu-latest 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 a1b47f14..020c4610 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 @@ -15,6 +15,7 @@ */ package org.springframework.modulith.events.support; +import java.lang.reflect.Method; import java.time.Duration; import java.util.Collection; import java.util.List; @@ -45,6 +46,7 @@ import org.springframework.modulith.events.core.TargetEventPublication; import org.springframework.transaction.event.TransactionPhase; import org.springframework.transaction.event.TransactionalApplicationListener; import org.springframework.util.Assert; +import org.springframework.util.ReflectionUtils; /** * An {@link org.springframework.context.event.ApplicationEventMulticaster} to register {@link EventPublication}s in an @@ -61,12 +63,23 @@ public class PersistentApplicationEventMulticaster extends AbstractApplicationEv implements IncompleteEventPublications, SmartInitializingSingleton { private static final Logger LOGGER = LoggerFactory.getLogger(PersistentApplicationEventMulticaster.class); + private static final Method LEGACY_SHOULD_HANDLE = ReflectionUtils.findMethod(ApplicationListenerMethodAdapter.class, + "shouldHandle", ApplicationEvent.class, Object[].class); + private static final Method SHOULD_HANDLE = ReflectionUtils.findMethod(ApplicationListenerMethodAdapter.class, + "shouldHandle", ApplicationEvent.class); static final String REPUBLISH_ON_RESTART = "spring.modulith.republish-outstanding-events-on-restart"; private final @NonNull Supplier registry; private final @NonNull Supplier environment; + static { + + if (SHOULD_HANDLE == null) { + ReflectionUtils.makeAccessible(LEGACY_SHOULD_HANDLE); + } + } + /** * Creates a new {@link PersistentApplicationEventMulticaster} for the given {@link EventPublicationRegistry}. * @@ -222,9 +235,7 @@ public class PersistentApplicationEventMulticaster extends AbstractApplicationEv private static boolean matches(ApplicationEvent event, Object payload, ApplicationListener listener) { // Verify general listener matching by eagerly evaluating the condition - if (ApplicationListenerMethodAdapter.class.isInstance(listener) - && !((ApplicationListenerMethodAdapter) listener).shouldHandle(event)) { - + if (!invokeShouldHandle(listener, event, payload)) { return false; } @@ -233,6 +244,27 @@ public class PersistentApplicationEventMulticaster extends AbstractApplicationEv : true; } + /** + * Invokes {@link ApplicationListenerMethodAdapter#shouldHandle(ApplicationEvent)} in case the given candidate is one + * in the first place but falls back to call {@code shouldHandle(ApplicationEvent, Object)} reflectively as fallback. + * + * @param candidate the listener to test, must not be {@literal null}. + * @param event the event to publish, must not be {@literal null}. + * @param payload the actual payload, must not be {@literal null}. + * @return whether the event should be handled by the given candidate. + */ + @SuppressWarnings("null") + private static boolean invokeShouldHandle(ApplicationListener candidate, ApplicationEvent event, Object payload) { + + if (!(candidate instanceof ApplicationListenerMethodAdapter listener)) { + return true; + } + + return SHOULD_HANDLE != null + ? listener.shouldHandle(event) + : (boolean) ReflectionUtils.invokeMethod(LEGACY_SHOULD_HANDLE, candidate, event, new Object[] { payload }); + } + private static String getConfirmationMessage(Collection publications) { var size = publications.size();