diff --git a/spring-modulith-events/spring-modulith-events-core/src/main/java/org/springframework/modulith/events/config/EventPublicationAutoConfiguration.java b/spring-modulith-events/spring-modulith-events-core/src/main/java/org/springframework/modulith/events/config/EventPublicationAutoConfiguration.java new file mode 100644 index 00000000..fc4d47ab --- /dev/null +++ b/spring-modulith-events/spring-modulith-events-core/src/main/java/org/springframework/modulith/events/config/EventPublicationAutoConfiguration.java @@ -0,0 +1,139 @@ +/* + * Copyright 2017-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.config; + +import java.time.Clock; +import java.time.Duration; +import java.util.Arrays; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.ObjectFactory; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.task.TaskExecutionProperties; +import org.springframework.boot.autoconfigure.task.TaskExecutionProperties.Shutdown; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; +import org.springframework.context.annotation.Role; +import org.springframework.core.env.Environment; +import org.springframework.modulith.events.config.EventPublicationAutoConfiguration.AsyncEnablingConfiguration; +import org.springframework.modulith.events.core.EventPublicationRegistry; +import org.springframework.modulith.events.core.EventPublicationRepository; +import org.springframework.modulith.events.support.CompletionRegisteringAdvisor; +import org.springframework.modulith.events.support.PersistentApplicationEventMulticaster; +import org.springframework.scheduling.annotation.AbstractAsyncConfiguration; +import org.springframework.scheduling.annotation.EnableAsync; + +/** + * Fundamental configuration for the {@link EventPublicationRegistry} support. + * + * @author Oliver Drotbohm + * @author Björn Kieling + * @author Dmitry Belyaev + */ +@AutoConfiguration +@Import(AsyncEnablingConfiguration.class) +public class EventPublicationAutoConfiguration extends EventPublicationConfiguration { + + @Override + @Bean + @Role(BeanDefinition.ROLE_INFRASTRUCTURE) + @ConditionalOnBean(EventPublicationRepository.class) + EventPublicationRegistry eventPublicationRegistry(EventPublicationRepository repository, + ObjectProvider clock) { + return super.eventPublicationRegistry(repository, clock); + } + + @Bean + @Role(BeanDefinition.ROLE_INFRASTRUCTURE) + @ConditionalOnBean(EventPublicationRegistry.class) + static PersistentApplicationEventMulticaster applicationEventMulticaster( + ObjectFactory eventPublicationRegistry, ObjectFactory environment) { + + return EventPublicationConfiguration.applicationEventMulticaster(eventPublicationRegistry, environment); + } + + @Bean + @Role(BeanDefinition.ROLE_INFRASTRUCTURE) + @ConditionalOnBean(EventPublicationRegistry.class) + static CompletionRegisteringAdvisor completionRegisteringAdvisor(ObjectFactory registry) { + return EventPublicationConfiguration.completionRegisteringAdvisor(registry); + } + + @Bean + @Role(BeanDefinition.ROLE_INFRASTRUCTURE) + @ConditionalOnProperty( + name = "spring.modulith.default-async-termination", + havingValue = "true", + matchIfMissing = true) + static AsyncPropertiesDefaulter asyncPropertiesDefaulter(Environment environment) { + return new AsyncPropertiesDefaulter(environment); + } + + @EnableAsync + @ConditionalOnMissingBean(AbstractAsyncConfiguration.class) + static class AsyncEnablingConfiguration {} + + static class AsyncPropertiesDefaulter implements BeanPostProcessor { + + private static final Logger LOGGER = LoggerFactory.getLogger(AsyncPropertiesDefaulter.class); + private static final String PROPERTY = "spring.task.execution.shutdown.await-termination"; + + private final Environment environment; + + AsyncPropertiesDefaulter(Environment environment) { + this.environment = environment; + } + + /* + * (non-Javadoc) + * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String) + */ + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + + if (!(bean instanceof TaskExecutionProperties p)) { + return bean; + } + + if (anyPropertyConfigured(PROPERTY, PROPERTY + "-period")) { + return bean; + } + + LOGGER.debug("Defaulting async shutdown to await termination in 2 seconds."); + + Shutdown shutdown = p.getShutdown(); + + shutdown.setAwaitTermination(true); + shutdown.setAwaitTerminationPeriod(Duration.ofSeconds(2)); + + return p; + } + + private boolean anyPropertyConfigured(String... properties) { + + return Arrays.stream(properties) + .anyMatch(it -> environment.containsProperty(it)); + } + } +} diff --git a/spring-modulith-events/spring-modulith-events-core/src/main/java/org/springframework/modulith/events/config/EventPublicationConfiguration.java b/spring-modulith-events/spring-modulith-events-core/src/main/java/org/springframework/modulith/events/config/EventPublicationConfiguration.java index 9d11d674..12988e2b 100644 --- a/spring-modulith-events/spring-modulith-events-core/src/main/java/org/springframework/modulith/events/config/EventPublicationConfiguration.java +++ b/spring-modulith-events/spring-modulith-events-core/src/main/java/org/springframework/modulith/events/config/EventPublicationConfiguration.java @@ -16,33 +16,19 @@ package org.springframework.modulith.events.config; import java.time.Clock; -import java.time.Duration; -import java.util.Arrays; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.BeansException; import org.springframework.beans.factory.ObjectFactory; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.autoconfigure.task.TaskExecutionProperties; -import org.springframework.boot.autoconfigure.task.TaskExecutionProperties.Shutdown; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Role; import org.springframework.core.env.Environment; -import org.springframework.modulith.events.config.EventPublicationConfiguration.AsyncEnablingConfiguration; import org.springframework.modulith.events.core.DefaultEventPublicationRegistry; import org.springframework.modulith.events.core.EventPublicationRegistry; import org.springframework.modulith.events.core.EventPublicationRepository; import org.springframework.modulith.events.support.CompletionRegisteringAdvisor; import org.springframework.modulith.events.support.PersistentApplicationEventMulticaster; -import org.springframework.scheduling.annotation.AbstractAsyncConfiguration; -import org.springframework.scheduling.annotation.EnableAsync; /** * Fundamental configuration for the {@link EventPublicationRegistry} support. @@ -52,7 +38,6 @@ import org.springframework.scheduling.annotation.EnableAsync; * @author Dmitry Belyaev */ @Configuration(proxyBeanMethods = false) -@Import(AsyncEnablingConfiguration.class) class EventPublicationConfiguration { @Bean @@ -76,61 +61,4 @@ class EventPublicationConfiguration { static CompletionRegisteringAdvisor completionRegisteringAdvisor(ObjectFactory registry) { return new CompletionRegisteringAdvisor(registry::getObject); } - - @Bean - @Role(BeanDefinition.ROLE_INFRASTRUCTURE) - @ConditionalOnProperty( - name = "spring.modulith.default-async-termination", - havingValue = "true", - matchIfMissing = true) - static AsyncPropertiesDefaulter asyncPropertiesDefaulter(Environment environment) { - return new AsyncPropertiesDefaulter(environment); - } - - @EnableAsync - @ConditionalOnMissingBean(AbstractAsyncConfiguration.class) - static class AsyncEnablingConfiguration {} - - static class AsyncPropertiesDefaulter implements BeanPostProcessor { - - private static final Logger LOGGER = LoggerFactory.getLogger(AsyncPropertiesDefaulter.class); - private static final String PROPERTY = "spring.task.execution.shutdown.await-termination"; - - private final Environment environment; - - AsyncPropertiesDefaulter(Environment environment) { - this.environment = environment; - } - - /* - * (non-Javadoc) - * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String) - */ - @Override - public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { - - if (!(bean instanceof TaskExecutionProperties p)) { - return bean; - } - - if (anyPropertyConfigured(PROPERTY, PROPERTY + "-period")) { - return bean; - } - - LOGGER.debug("Defaulting async shutdown to await termination in 2 seconds."); - - Shutdown shutdown = p.getShutdown(); - - shutdown.setAwaitTermination(true); - shutdown.setAwaitTerminationPeriod(Duration.ofSeconds(2)); - - return p; - } - - private boolean anyPropertyConfigured(String... properties) { - - return Arrays.stream(properties) - .anyMatch(it -> environment.containsProperty(it)); - } - } } diff --git a/spring-modulith-events/spring-modulith-events-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-modulith-events/spring-modulith-events-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 11cddd87..0e82e46e 100644 --- a/spring-modulith-events/spring-modulith-events-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/spring-modulith-events/spring-modulith-events-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1 +1 @@ -org.springframework.modulith.events.config.EventPublicationConfiguration +org.springframework.modulith.events.config.EventPublicationAutoConfiguration diff --git a/spring-modulith-events/spring-modulith-events-core/src/test/java/org/springframework/modulith/events/config/EventPublicationConfigurationIntegrationTests.java b/spring-modulith-events/spring-modulith-events-core/src/test/java/org/springframework/modulith/events/config/EventPublicationAutoConfigurationIntegrationTests.java similarity index 95% rename from spring-modulith-events/spring-modulith-events-core/src/test/java/org/springframework/modulith/events/config/EventPublicationConfigurationIntegrationTests.java rename to spring-modulith-events/spring-modulith-events-core/src/test/java/org/springframework/modulith/events/config/EventPublicationAutoConfigurationIntegrationTests.java index efc1f6d2..56459478 100644 --- a/spring-modulith-events/spring-modulith-events-core/src/test/java/org/springframework/modulith/events/config/EventPublicationConfigurationIntegrationTests.java +++ b/spring-modulith-events/spring-modulith-events-core/src/test/java/org/springframework/modulith/events/config/EventPublicationAutoConfigurationIntegrationTests.java @@ -35,7 +35,7 @@ import org.springframework.boot.test.context.assertj.AssertableApplicationContex import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ContextConsumer; import org.springframework.context.annotation.AdviceMode; -import org.springframework.modulith.events.config.EventPublicationConfiguration.AsyncPropertiesDefaulter; +import org.springframework.modulith.events.config.EventPublicationAutoConfiguration.AsyncPropertiesDefaulter; import org.springframework.modulith.events.core.EventPublicationRegistry; import org.springframework.modulith.events.core.EventPublicationRepository; import org.springframework.scheduling.annotation.EnableAsync; @@ -49,7 +49,7 @@ import org.springframework.test.util.ReflectionTestUtils; * @author Oliver Drotbohm */ @ExtendWith(MockitoExtension.class) -class EventPublicationConfigurationIntegrationTests { +class EventPublicationAutoConfigurationIntegrationTests { @Mock EventPublicationRepository repository; @@ -137,7 +137,7 @@ class EventPublicationConfigurationIntegrationTests { return new ApplicationContextRunner() .withConfiguration( - AutoConfigurations.of(EventPublicationConfiguration.class, TaskExecutionAutoConfiguration.class)) + AutoConfigurations.of(EventPublicationAutoConfiguration.class, TaskExecutionAutoConfiguration.class)) .withBean(EventPublicationRepository.class, () -> repository); } diff --git a/spring-modulith-events/spring-modulith-events-jdbc/src/main/java/org/springframework/modulith/events/jdbc/JdbcEventPublicationAutoConfiguration.java b/spring-modulith-events/spring-modulith-events-jdbc/src/main/java/org/springframework/modulith/events/jdbc/JdbcEventPublicationAutoConfiguration.java index 32b4b147..d7b4f6a5 100644 --- a/spring-modulith-events/spring-modulith-events-jdbc/src/main/java/org/springframework/modulith/events/jdbc/JdbcEventPublicationAutoConfiguration.java +++ b/spring-modulith-events/spring-modulith-events-jdbc/src/main/java/org/springframework/modulith/events/jdbc/JdbcEventPublicationAutoConfiguration.java @@ -17,12 +17,14 @@ package org.springframework.modulith.events.jdbc; import javax.sql.DataSource; +import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.jdbc.DatabaseDriver; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ResourceLoader; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.modulith.events.config.EventPublicationAutoConfiguration; import org.springframework.modulith.events.config.EventPublicationConfigurationExtension; import org.springframework.modulith.events.core.EventSerializer; @@ -32,6 +34,7 @@ import org.springframework.modulith.events.core.EventSerializer; * @author Oliver Drotbohm */ @Configuration(proxyBeanMethods = false) +@AutoConfigureBefore(EventPublicationAutoConfiguration.class) class JdbcEventPublicationAutoConfiguration implements EventPublicationConfigurationExtension { @Bean diff --git a/spring-modulith-events/spring-modulith-events-jpa/src/main/java/org/springframework/modulith/events/jpa/JpaEventPublicationAutoConfiguration.java b/spring-modulith-events/spring-modulith-events-jpa/src/main/java/org/springframework/modulith/events/jpa/JpaEventPublicationAutoConfiguration.java index c8073849..6fd1381c 100644 --- a/spring-modulith-events/spring-modulith-events-jpa/src/main/java/org/springframework/modulith/events/jpa/JpaEventPublicationAutoConfiguration.java +++ b/spring-modulith-events/spring-modulith-events-jpa/src/main/java/org/springframework/modulith/events/jpa/JpaEventPublicationAutoConfiguration.java @@ -15,10 +15,11 @@ */ package org.springframework.modulith.events.jpa; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurationPackage; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; -import org.springframework.context.annotation.Configuration; +import org.springframework.modulith.events.config.EventPublicationAutoConfiguration; /** * Auto-configuration for JPA based event publication. Registers this class' package as auto-configuration package, so @@ -26,7 +27,7 @@ import org.springframework.context.annotation.Configuration; * * @author Oliver Drotbohm */ -@Configuration(proxyBeanMethods = false) -@AutoConfigureBefore(HibernateJpaAutoConfiguration.class) +@AutoConfiguration +@AutoConfigureBefore({ HibernateJpaAutoConfiguration.class, EventPublicationAutoConfiguration.class }) @AutoConfigurationPackage -class JpaEventPublicationAutoConfiguration {} +class JpaEventPublicationAutoConfiguration extends JpaEventPublicationConfiguration {} diff --git a/spring-modulith-events/spring-modulith-events-jpa/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-modulith-events/spring-modulith-events-jpa/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index dc43aae2..4dc0fb5b 100644 --- a/spring-modulith-events/spring-modulith-events-jpa/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/spring-modulith-events/spring-modulith-events-jpa/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1,2 +1 @@ org.springframework.modulith.events.jpa.JpaEventPublicationAutoConfiguration -org.springframework.modulith.events.jpa.JpaEventPublicationConfiguration diff --git a/spring-modulith-events/spring-modulith-events-mongodb/src/main/java/org/springframework/modulith/events/mongodb/MongoDbEventPublicationAutoConfiguration.java b/spring-modulith-events/spring-modulith-events-mongodb/src/main/java/org/springframework/modulith/events/mongodb/MongoDbEventPublicationAutoConfiguration.java index 3df3a7c4..287d4504 100644 --- a/spring-modulith-events/spring-modulith-events-mongodb/src/main/java/org/springframework/modulith/events/mongodb/MongoDbEventPublicationAutoConfiguration.java +++ b/spring-modulith-events/spring-modulith-events-mongodb/src/main/java/org/springframework/modulith/events/mongodb/MongoDbEventPublicationAutoConfiguration.java @@ -15,9 +15,11 @@ */ package org.springframework.modulith.events.mongodb; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.modulith.events.config.EventPublicationAutoConfiguration; import org.springframework.modulith.events.config.EventPublicationConfigurationExtension; /** @@ -25,7 +27,8 @@ import org.springframework.modulith.events.config.EventPublicationConfigurationE * * @author Oliver Drotbohm */ -@Configuration(proxyBeanMethods = false) +@AutoConfiguration +@AutoConfigureBefore(EventPublicationAutoConfiguration.class) class MongoDbEventPublicationAutoConfiguration implements EventPublicationConfigurationExtension { @Bean