From b2facecb120fde2bcd1ca3d7b1ab6d6e1003c817 Mon Sep 17 00:00:00 2001 From: Guirong Hu Date: Wed, 22 Feb 2023 17:41:43 +0800 Subject: [PATCH 1/2] Disable embedded web auto-config when not using embedded web server See gh-34332 --- .../ConditionalOnNotWarDeployment.java | 41 ++++++++++ .../condition/OnWarDeploymentCondition.java | 7 +- ...verFactoryCustomizerAutoConfiguration.java | 4 +- .../ConditionalOnNotWarDeploymentTests.java | 77 +++++++++++++++++++ .../developing-auto-configuration.adoc | 2 +- 5 files changed, 127 insertions(+), 4 deletions(-) create mode 100644 spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionalOnNotWarDeployment.java create mode 100644 spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnNotWarDeploymentTests.java diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionalOnNotWarDeployment.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionalOnNotWarDeployment.java new file mode 100644 index 0000000000..507b1f9eb4 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionalOnNotWarDeployment.java @@ -0,0 +1,41 @@ +/* + * 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.condition; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.context.annotation.Conditional; + +/** + * {@link Conditional @Conditional} that only matches when the application is a not + * traditional WAR deployment. For applications with embedded servers, this condition will + * return true. + * + * @author Guirong Hu + * @since 2.7.10 + */ +@Target({ ElementType.TYPE, ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Conditional(OnWarDeploymentCondition.class) +public @interface ConditionalOnNotWarDeployment { + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnWarDeploymentCondition.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnWarDeploymentCondition.java index 529912ef73..0125896c83 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnWarDeploymentCondition.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnWarDeploymentCondition.java @@ -29,20 +29,23 @@ import org.springframework.web.context.WebApplicationContext; * deployment. * * @author Madhura Bhave + * @see ConditionalOnWarDeployment + * @see ConditionalOnNotWarDeployment */ class OnWarDeploymentCondition extends SpringBootCondition { @Override public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { + boolean required = metadata.isAnnotated(ConditionalOnWarDeployment.class.getName()); ResourceLoader resourceLoader = context.getResourceLoader(); if (resourceLoader instanceof WebApplicationContext) { WebApplicationContext applicationContext = (WebApplicationContext) resourceLoader; ServletContext servletContext = applicationContext.getServletContext(); if (servletContext != null) { - return ConditionOutcome.match("Application is deployed as a WAR file."); + return new ConditionOutcome(required, "Application is deployed as a WAR file."); } } - return ConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnWarDeployment.class) + return new ConditionOutcome(!required, ConditionMessage.forCondition(ConditionalOnWarDeployment.class) .because("the application is not deployed as a WAR file.")); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/EmbeddedWebServerFactoryCustomizerAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/EmbeddedWebServerFactoryCustomizerAutoConfiguration.java index 3abb0e73c1..eca465353d 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/EmbeddedWebServerFactoryCustomizerAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/embedded/EmbeddedWebServerFactoryCustomizerAutoConfiguration.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. @@ -28,6 +28,7 @@ import reactor.netty.http.server.HttpServer; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnNotWarDeployment; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -43,6 +44,7 @@ import org.springframework.core.env.Environment; * @since 2.0.0 */ @AutoConfiguration +@ConditionalOnNotWarDeployment @ConditionalOnWebApplication @EnableConfigurationProperties(ServerProperties.class) public class EmbeddedWebServerFactoryCustomizerAutoConfiguration { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnNotWarDeploymentTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnNotWarDeploymentTests.java new file mode 100644 index 0000000000..d713aa146b --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnNotWarDeploymentTests.java @@ -0,0 +1,77 @@ +/* + * 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.condition; + +import org.junit.jupiter.api.Test; + +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner; +import org.springframework.boot.test.context.runner.WebApplicationContextRunner; +import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link ConditionalOnNotWarDeployment @ConditionalOnNotWarDeployment}. + * + * @author Guirong Hu + */ +class ConditionalOnNotWarDeploymentTests { + + @Test + void nonWebApplicationShouldMatch() { + ApplicationContextRunner contextRunner = new ApplicationContextRunner(); + contextRunner.withUserConfiguration(NotWarDeploymentConfiguration.class) + .run((context) -> assertThat(context).hasBean("notForWar")); + } + + @Test + void reactiveWebApplicationShouldMatch() { + ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner(); + contextRunner.withUserConfiguration(NotWarDeploymentConfiguration.class) + .run((context) -> assertThat(context).hasBean("notForWar")); + } + + @Test + void embeddedServletWebApplicationShouldMatch() { + WebApplicationContextRunner contextRunner = new WebApplicationContextRunner( + AnnotationConfigServletWebApplicationContext::new); + contextRunner.withUserConfiguration(NotWarDeploymentConfiguration.class) + .run((context) -> assertThat(context).hasBean("notForWar")); + } + + @Test + void warDeployedServletWebApplicationShouldNotMatch() { + WebApplicationContextRunner contextRunner = new WebApplicationContextRunner(); + contextRunner.withUserConfiguration(NotWarDeploymentConfiguration.class) + .run((context) -> assertThat(context).doesNotHaveBean("notForWar")); + } + + @Configuration(proxyBeanMethods = false) + @ConditionalOnNotWarDeployment + static class NotWarDeploymentConfiguration { + + @Bean + String notForWar() { + return "notForWar"; + } + + } + +} diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/developing-auto-configuration.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/developing-auto-configuration.adoc index f361c55f21..a359708bd6 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/developing-auto-configuration.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/developing-auto-configuration.adoc @@ -129,7 +129,7 @@ The `@ConditionalOnWebApplication` and `@ConditionalOnNotWebApplication` annotat A servlet-based web application is any application that uses a Spring `WebApplicationContext`, defines a `session` scope, or has a `ConfigurableWebEnvironment`. A reactive web application is any application that uses a `ReactiveWebApplicationContext`, or has a `ConfigurableReactiveWebEnvironment`. -The `@ConditionalOnWarDeployment` annotation lets configuration be included depending on whether the application is a traditional WAR application that is deployed to a container. +The `@ConditionalOnWarDeployment` and `@ConditionalOnNotWarDeployment` annotation lets configuration be included depending on whether the application is a traditional WAR application that is deployed to a container. This condition will not match for applications that are run with an embedded server. From 6dc0f90e007a503828e35f2ef14cbca96c791dfe Mon Sep 17 00:00:00 2001 From: Scott Frederick Date: Mon, 20 Mar 2023 17:59:24 -0500 Subject: [PATCH 2/2] Polish "Disable embedded web auto-config when not using embedded web server" See gh-34332 --- .../condition/ConditionalOnNotWarDeployment.java | 2 +- .../asciidoc/features/developing-auto-configuration.adoc | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionalOnNotWarDeployment.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionalOnNotWarDeployment.java index 507b1f9eb4..0d8387274e 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionalOnNotWarDeployment.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionalOnNotWarDeployment.java @@ -25,7 +25,7 @@ import java.lang.annotation.Target; import org.springframework.context.annotation.Conditional; /** - * {@link Conditional @Conditional} that only matches when the application is a not + * {@link Conditional @Conditional} that only matches when the application is not a * traditional WAR deployment. For applications with embedded servers, this condition will * return true. * diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/developing-auto-configuration.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/developing-auto-configuration.adoc index a359708bd6..2dad062fee 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/developing-auto-configuration.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/developing-auto-configuration.adoc @@ -125,12 +125,12 @@ Resources can be specified by using the usual Spring conventions, as shown in th [[features.developing-auto-configuration.condition-annotations.web-application-conditions]] ==== Web Application Conditions -The `@ConditionalOnWebApplication` and `@ConditionalOnNotWebApplication` annotations let configuration be included depending on whether the application is a "`web application`". +The `@ConditionalOnWebApplication` and `@ConditionalOnNotWebApplication` annotations let configuration be included depending on whether the application is a web application. A servlet-based web application is any application that uses a Spring `WebApplicationContext`, defines a `session` scope, or has a `ConfigurableWebEnvironment`. A reactive web application is any application that uses a `ReactiveWebApplicationContext`, or has a `ConfigurableReactiveWebEnvironment`. -The `@ConditionalOnWarDeployment` and `@ConditionalOnNotWarDeployment` annotation lets configuration be included depending on whether the application is a traditional WAR application that is deployed to a container. -This condition will not match for applications that are run with an embedded server. +The `@ConditionalOnWarDeployment` and `@ConditionalOnNotWarDeployment` annotations let configuration be included depending on whether the application is a traditional WAR application that is deployed to a servlet container. +This condition will not match for applications that are run with an embedded web server.