GH-732 - Only create event publication registry entries for after commit listeners.

This commit is contained in:
Oliver Drotbohm
2024-07-14 19:10:55 +02:00
parent d3b5f783d0
commit 61bcafeaed
2 changed files with 21 additions and 24 deletions

View File

@@ -187,7 +187,8 @@ public class PersistentApplicationEventMulticaster extends AbstractApplicationEv
.map(it -> executeListenerWithCompletion(publication, it)) //
.orElseGet(() -> {
LOGGER.error("Listener {} not found! Skipping invocation and leaving event publication {} incomplete.", publication.getTargetIdentifier(), publication.getIdentifier());
LOGGER.error("Listener {} not found! Skipping invocation and leaving event publication {} incomplete.",
publication.getTargetIdentifier(), publication.getIdentifier());
return null;
});
}
@@ -195,7 +196,7 @@ public class PersistentApplicationEventMulticaster extends AbstractApplicationEv
private void doResubmitUncompletedPublicationsOlderThan(@Nullable Duration duration,
Predicate<EventPublication> filter) {
var message = duration != null ? " older than %s".formatted(duration): "";;
var message = duration != null ? " older than %s".formatted(duration) : "";
var registry = this.registry.get();
LOGGER.debug("Looking up incomplete event publications {}… ", message);
@@ -317,32 +318,11 @@ public class PersistentApplicationEventMulticaster extends AbstractApplicationEv
this.listeners = (List) listeners.stream()
.filter(TransactionalApplicationListener.class::isInstance)
.map(TransactionalApplicationListener.class::cast)
.filter(it -> it.getTransactionPhase().equals(TransactionPhase.AFTER_COMMIT))
.sorted(AnnotationAwareOrderComparator.INSTANCE)
.toList();
}
private TransactionalEventListeners(
List<TransactionalApplicationListener<ApplicationEvent>> listeners) {
this.listeners = listeners;
}
/**
* Returns all {@link TransactionalEventListeners} for the given {@link TransactionPhase}.
*
* @param phase must not be {@literal null}.
* @return will never be {@literal null}.
*/
public TransactionalEventListeners forPhase(TransactionPhase phase) {
Assert.notNull(phase, "TransactionPhase must not be null!");
List<TransactionalApplicationListener<ApplicationEvent>> collect = listeners.stream()
.filter(it -> it.getTransactionPhase().equals(phase))
.toList();
return new TransactionalEventListeners(collect);
}
/**
* Invokes the given {@link Consumer} for all transactional event listeners.
*

View File

@@ -20,6 +20,7 @@ import static org.mockito.Mockito.*;
import lombok.AllArgsConstructor;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.BeforeEach;
@@ -33,6 +34,8 @@ import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.modulith.events.core.EventPublicationRegistry;
import org.springframework.stereotype.Component;
import org.springframework.transaction.event.TransactionPhase;
import org.springframework.transaction.event.TransactionalApplicationListener;
import org.springframework.transaction.event.TransactionalEventListener;
/**
@@ -87,6 +90,20 @@ class PersistentApplicationEventMulticasterUnitTests {
}
}
@Test // GH-726
void onlyConsidersAfterCommitListeners() {
var afterCommitListener = TransactionalApplicationListener.forPayload(TransactionPhase.AFTER_COMMIT, __ -> {});
var beforeCommitListener = TransactionalApplicationListener.forPayload(TransactionPhase.BEFORE_COMMIT, __ -> {});
var eventListeners = new PersistentApplicationEventMulticaster.TransactionalEventListeners(
List.of(afterCommitListener, beforeCommitListener));
assertThat(eventListeners.stream())
.hasSize(1)
.element(0).isEqualTo(afterCommitListener);
}
private void assertListenerSelected(SampleEvent event, boolean expected) {
var listeners = multicaster.getApplicationListeners(new PayloadApplicationEvent<>(this, event),