GH-240 - Republication of outstanding events can now be disabled.

Via the spring.modulith.republish-outstanding-events-on-restart (boolean) property.
This commit is contained in:
Oliver Drotbohm
2023-07-17 13:35:45 +02:00
parent ff32c609fc
commit 2270ff39ec
4 changed files with 86 additions and 3 deletions

View File

@@ -62,8 +62,10 @@ class EventPublicationConfiguration {
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
static PersistentApplicationEventMulticaster applicationEventMulticaster(
ObjectFactory<EventPublicationRegistry> eventPublicationRegistry) {
return new PersistentApplicationEventMulticaster(() -> eventPublicationRegistry.getObject());
ObjectFactory<EventPublicationRegistry> eventPublicationRegistry, ObjectFactory<Environment> environment) {
return new PersistentApplicationEventMulticaster(() -> eventPublicationRegistry.getObject(),
() -> environment.getObject());
}
@Bean

View File

@@ -33,6 +33,7 @@ import org.springframework.context.event.ApplicationEventMulticaster;
import org.springframework.context.event.ApplicationListenerMethodAdapter;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.env.Environment;
import org.springframework.lang.NonNull;
import org.springframework.modulith.events.EventPublication;
import org.springframework.modulith.events.EventPublicationRegistry;
@@ -60,8 +61,10 @@ public class PersistentApplicationEventMulticaster extends AbstractApplicationEv
private static final Logger LOGGER = LoggerFactory.getLogger(PersistentApplicationEventMulticaster.class);
private static final Field DECLARED_EVENT_TYPES_FIELD = ReflectionUtils
.findField(ApplicationListenerMethodAdapter.class, "declaredEventTypes");
static final String REPUBLISH_ON_RESTART = "spring.modulith.republish-outstanding-events-on-restart";
private final @NonNull Supplier<EventPublicationRegistry> registry;
private final @NonNull Supplier<Environment> environment;
static {
ReflectionUtils.makeAccessible(DECLARED_EVENT_TYPES_FIELD);
@@ -71,12 +74,16 @@ public class PersistentApplicationEventMulticaster extends AbstractApplicationEv
* Creates a new {@link PersistentApplicationEventMulticaster} for the given {@link EventPublicationRegistry}.
*
* @param registry must not be {@literal null}.
* @param environment must not be {@literal null}.
*/
public PersistentApplicationEventMulticaster(Supplier<EventPublicationRegistry> registry) {
public PersistentApplicationEventMulticaster(Supplier<EventPublicationRegistry> registry,
Supplier<Environment> environment) {
Assert.notNull(registry, "EventPublicationRegistry must not be null!");
Assert.notNull(environment, "Environment must not be null!");
this.registry = registry;
this.environment = environment;
}
/*
@@ -118,6 +125,10 @@ public class PersistentApplicationEventMulticaster extends AbstractApplicationEv
@Override
public void afterSingletonsInstantiated() {
if (Boolean.FALSE.equals(environment.get().getProperty(REPUBLISH_ON_RESTART, Boolean.class))) {
return;
}
LOGGER.debug("Looking up previously pending event publications…");
var publications = registry.get().findIncompletePublications();

View File

@@ -5,6 +5,12 @@
"type": "java.lang.boolean",
"description": "Whether to configure defaults for the async processing termination, namely to wait for task completion for 2 seconds. See TaskExecutionProperties for details.",
"defaultValue": "true"
},
{
"name": "spring.modulith.republish-outstanding-events-on-restart",
"type": "java.lang.boolean",
"description": "Whether to republish outstanding event publications on restarts of the application.",
"defaultValue": "true"
}
]
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright 2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.modulith.events.support;
import static org.mockito.Mockito.*;
import java.util.Map;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.modulith.events.EventPublicationRegistry;
/**
* Unit tests for {@link PersistentApplicationEventMulticaster}.
*
* @author Oliver Drotbohm
*/
class PersistentApplicationEventMulticasterUnitTests {
PersistentApplicationEventMulticaster multicaster;
StandardEnvironment environment = new StandardEnvironment();
EventPublicationRegistry registry = mock(EventPublicationRegistry.class);
@BeforeEach
void setUp() {
this.multicaster = new PersistentApplicationEventMulticaster(() -> registry, () -> environment);
}
@Test // GH-240
void doesNotRepublishEventsOnRestartIfExplicitlyDisabled() {
var source = new MapPropertySource("test",
Map.of(PersistentApplicationEventMulticaster.REPUBLISH_ON_RESTART, "false"));
environment.getPropertySources().addFirst(source);
multicaster.afterSingletonsInstantiated();
verify(registry, never()).findIncompletePublications();
}
@Test // GH-240
void triggersRepublicationIfExplicitlyEnabled() {
multicaster.afterSingletonsInstantiated();
verify(registry).findIncompletePublications();
}
}