diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/reactor/netty/ReactorNettyConfigurationProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/reactor/netty/ReactorNettyConfigurationProperties.java new file mode 100644 index 00000000000..b7e68516a61 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/reactor/netty/ReactorNettyConfigurationProperties.java @@ -0,0 +1,45 @@ +/* + * Copyright 2012-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.boot.autoconfigure.reactor.netty; + +import java.time.Duration; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * Configuration properties for Reactor Netty configuration. + * + * @author Moritz Halbritter + * @since 2.7.9 + */ +@ConfigurationProperties(prefix = "spring.reactor.netty") +public class ReactorNettyConfigurationProperties { + + /** + * Configure the amount of time to wait before shutting down resources. + */ + private Duration shutdownQuietPeriod; + + public Duration getShutdownQuietPeriod() { + return this.shutdownQuietPeriod; + } + + public void setShutdownQuietPeriod(Duration shutdownQuietPeriod) { + this.shutdownQuietPeriod = shutdownQuietPeriod; + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/reactor/netty/ReactorNettyConfigurations.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/reactor/netty/ReactorNettyConfigurations.java new file mode 100644 index 00000000000..64246cb36f3 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/reactor/netty/ReactorNettyConfigurations.java @@ -0,0 +1,53 @@ +/* + * Copyright 2012-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.boot.autoconfigure.reactor.netty; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.reactive.ReactorResourceFactory; + +/** + * Configurations for Reactor Netty. Those should be {@code @Import} in a regular + * auto-configuration class. + * + * @author Moritz Halbritter + * @since 2.7.9 + */ +public final class ReactorNettyConfigurations { + + private ReactorNettyConfigurations() { + } + + @Configuration(proxyBeanMethods = false) + @EnableConfigurationProperties(ReactorNettyConfigurationProperties.class) + public static class ReactorResourceFactoryConfiguration { + + @Bean + @ConditionalOnMissingBean + ReactorResourceFactory reactorResourceFactory(ReactorNettyConfigurationProperties configurationProperties) { + ReactorResourceFactory reactorResourceFactory = new ReactorResourceFactory(); + if (configurationProperties.getShutdownQuietPeriod() != null) { + reactorResourceFactory.setShutdownQuietPeriod(configurationProperties.getShutdownQuietPeriod()); + } + return reactorResourceFactory; + } + + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/reactor/netty/package-info.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/reactor/netty/package-info.java new file mode 100644 index 00000000000..e9842ee9fc0 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/reactor/netty/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-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. + */ + +/** + * Auto-configuration for Reactor Netty. + */ +package org.springframework.boot.autoconfigure.reactor.netty; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/rsocket/RSocketServerAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/rsocket/RSocketServerAutoConfiguration.java index ff7aef026fc..70bbb45ac03 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/rsocket/RSocketServerAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/rsocket/RSocketServerAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-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. @@ -30,6 +30,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.boot.autoconfigure.reactor.netty.ReactorNettyConfigurations; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.boot.rsocket.context.RSocketServerBootstrap; @@ -39,6 +40,7 @@ import org.springframework.boot.rsocket.server.RSocketServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; import org.springframework.core.io.buffer.NettyDataBufferFactory; import org.springframework.http.client.reactive.ReactorResourceFactory; import org.springframework.messaging.rsocket.RSocketStrategies; @@ -77,14 +79,9 @@ public class RSocketServerAutoConfiguration { @ConditionalOnProperty(prefix = "spring.rsocket.server", name = "port") @ConditionalOnClass(ReactorResourceFactory.class) @Configuration(proxyBeanMethods = false) + @Import(ReactorNettyConfigurations.ReactorResourceFactoryConfiguration.class) static class EmbeddedServerConfiguration { - @Bean - @ConditionalOnMissingBean - ReactorResourceFactory reactorResourceFactory() { - return new ReactorResourceFactory(); - } - @Bean @ConditionalOnMissingBean RSocketServerFactory rSocketServerFactory(RSocketProperties properties, ReactorResourceFactory resourceFactory, diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/ReactiveWebServerFactoryConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/ReactiveWebServerFactoryConfiguration.java index b14d1acd3cc..2d92ced3d6e 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/ReactiveWebServerFactoryConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/ReactiveWebServerFactoryConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-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. @@ -23,6 +23,7 @@ import reactor.netty.http.server.HttpServer; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.reactor.netty.ReactorNettyConfigurations; import org.springframework.boot.web.embedded.jetty.JettyReactiveWebServerFactory; import org.springframework.boot.web.embedded.jetty.JettyServerCustomizer; import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory; @@ -37,6 +38,7 @@ import org.springframework.boot.web.embedded.undertow.UndertowReactiveWebServerF import org.springframework.boot.web.reactive.server.ReactiveWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; import org.springframework.http.client.reactive.JettyResourceFactory; import org.springframework.http.client.reactive.ReactorResourceFactory; @@ -55,14 +57,9 @@ abstract class ReactiveWebServerFactoryConfiguration { @Configuration(proxyBeanMethods = false) @ConditionalOnMissingBean(ReactiveWebServerFactory.class) @ConditionalOnClass({ HttpServer.class }) + @Import(ReactorNettyConfigurations.ReactorResourceFactoryConfiguration.class) static class EmbeddedNetty { - @Bean - @ConditionalOnMissingBean - ReactorResourceFactory reactorServerResourceFactory() { - return new ReactorResourceFactory(); - } - @Bean NettyReactiveWebServerFactory nettyReactiveWebServerFactory(ReactorResourceFactory resourceFactory, ObjectProvider routes, ObjectProvider serverCustomizers) { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/function/client/ClientHttpConnectorConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/function/client/ClientHttpConnectorConfiguration.java index c507af639ac..68e1e4b4a8d 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/function/client/ClientHttpConnectorConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/function/client/ClientHttpConnectorConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-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. @@ -26,8 +26,10 @@ import org.eclipse.jetty.util.ssl.SslContextFactory; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.reactor.netty.ReactorNettyConfigurations; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Lazy; import org.springframework.http.client.reactive.ClientHttpConnector; import org.springframework.http.client.reactive.HttpComponentsClientHttpConnector; @@ -51,14 +53,9 @@ class ClientHttpConnectorConfiguration { @Configuration(proxyBeanMethods = false) @ConditionalOnClass(reactor.netty.http.client.HttpClient.class) @ConditionalOnMissingBean(ClientHttpConnector.class) + @Import(ReactorNettyConfigurations.ReactorResourceFactoryConfiguration.class) static class ReactorNetty { - @Bean - @ConditionalOnMissingBean - ReactorResourceFactory reactorClientResourceFactory() { - return new ReactorResourceFactory(); - } - @Bean @Lazy ReactorClientHttpConnector reactorClientHttpConnector(ReactorResourceFactory reactorResourceFactory, diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/function/client/ClientHttpConnectorAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/function/client/ClientHttpConnectorAutoConfigurationTests.java index d110b1e1268..b2432541fc6 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/function/client/ClientHttpConnectorAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/function/client/ClientHttpConnectorAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-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. @@ -57,7 +57,7 @@ class ClientHttpConnectorAutoConfigurationTests { BeanDefinition connectorDefinition = context.getBeanFactory() .getBeanDefinition("reactorClientHttpConnector"); assertThat(connectorDefinition.isLazyInit()).isTrue(); - assertThat(context).hasBean("reactorClientResourceFactory"); + assertThat(context).hasSingleBean(ReactorResourceFactory.class); }); } diff --git a/spring-boot-project/spring-boot-devtools/src/main/resources/org/springframework/boot/devtools/env/devtools-property-defaults.properties b/spring-boot-project/spring-boot-devtools/src/main/resources/org/springframework/boot/devtools/env/devtools-property-defaults.properties index 053817b051d..c6913287099 100644 --- a/spring-boot-project/spring-boot-devtools/src/main/resources/org/springframework/boot/devtools/env/devtools-property-defaults.properties +++ b/spring-boot-project/spring-boot-devtools/src/main/resources/org/springframework/boot/devtools/env/devtools-property-defaults.properties @@ -13,3 +13,4 @@ spring.template.provider.cache=false spring.thymeleaf.cache=false spring.web.resources.cache.period=0 spring.web.resources.chain.cache=false +spring.reactor.netty.shutdown-quiet-period=0s