diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle b/spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle index 3f8c3bc3fc..03124475a1 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle @@ -28,6 +28,7 @@ dependencies { testImplementation(project(":spring-boot-project:spring-boot-test")) testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support")) + testImplementation(testFixtures(project(":spring-boot-project:spring-boot-web-server"))) testImplementation("org.springframework:spring-webflux") testRuntimeOnly("ch.qos.logback:logback-classic") diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/ManagementContextFactory.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/ManagementContextFactory.java index 4b98cdfc51..8ed92f2a73 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/ManagementContextFactory.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/ManagementContextFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 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. @@ -72,7 +72,9 @@ public final class ManagementContextFactory { public void registerWebServerFactoryBeans(ApplicationContext parentContext, ConfigurableApplicationContext managementContext, AnnotationConfigRegistry registry) { - registry.register(this.autoConfigurationClasses); + if (this.autoConfigurationClasses != null && this.autoConfigurationClasses.length > 0) { + registry.register(this.autoConfigurationClasses); + } registerWebServerFactoryFromParent(parentContext, managementContext); } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure-all/src/test/java/org/springframework/boot/actuate/autoconfigure/web/server/ChildManagementContextInitializerAotTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/server/ChildManagementContextInitializerAotTests.java similarity index 67% rename from spring-boot-project/spring-boot-actuator-autoconfigure-all/src/test/java/org/springframework/boot/actuate/autoconfigure/web/server/ChildManagementContextInitializerAotTests.java rename to spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/server/ChildManagementContextInitializerAotTests.java index 1649f982c8..2e26f5009d 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure-all/src/test/java/org/springframework/boot/actuate/autoconfigure/web/server/ChildManagementContextInitializerAotTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/server/ChildManagementContextInitializerAotTests.java @@ -18,25 +18,31 @@ package org.springframework.boot.actuate.autoconfigure.web.server; import java.util.function.Consumer; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.aot.AotDetector; import org.springframework.aot.test.generate.TestGenerationContext; +import org.springframework.boot.WebApplicationType; import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration; +import org.springframework.boot.actuate.autoconfigure.web.ManagementContextFactory; import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.servlet.actuate.autoconfigure.ServletManagementContextAutoConfiguration; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; import org.springframework.boot.test.system.CapturedOutput; import org.springframework.boot.test.system.OutputCaptureExtension; import org.springframework.boot.test.util.TestPropertyValues; -import org.springframework.boot.testsupport.web.servlet.DirtiesUrlFactories; -import org.springframework.boot.tomcat.actuate.autoconfigure.web.TomcatServletManagementContextAutoConfiguration; -import org.springframework.boot.tomcat.autoconfigure.servlet.TomcatServletWebServerAutoConfiguration; +import org.springframework.boot.web.server.WebServer; +import org.springframework.boot.web.server.servlet.MockServletWebServer; +import org.springframework.boot.web.server.servlet.MockServletWebServerFactory; import org.springframework.boot.web.server.servlet.context.AnnotationConfigServletWebServerApplicationContext; import org.springframework.boot.web.server.servlet.context.ServletWebServerApplicationContext; +import org.springframework.boot.web.servlet.ServletContextInitializer; import org.springframework.context.ApplicationContextInitializer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.context.aot.ApplicationContextAotGenerator; import org.springframework.context.support.GenericApplicationContext; import org.springframework.core.test.tools.CompileWithForkedClassLoader; @@ -45,13 +51,13 @@ import org.springframework.javapoet.ClassName; import org.springframework.util.StringUtils; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.willAnswer; /** * AOT tests for {@link ChildManagementContextInitializer}. * * @author Phillip Webb */ -@DirtiesUrlFactories @ExtendWith(OutputCaptureExtension.class) class ChildManagementContextInitializerAotTests { @@ -62,10 +68,8 @@ class ChildManagementContextInitializerAotTests { WebApplicationContextRunner contextRunner = new WebApplicationContextRunner( AnnotationConfigServletWebServerApplicationContext::new) .withConfiguration(AutoConfigurations.of(ManagementContextAutoConfiguration.class, - TomcatServletWebServerAutoConfiguration.class, - TomcatServletManagementContextAutoConfiguration.class, - ServletManagementContextAutoConfiguration.class, WebEndpointAutoConfiguration.class, - EndpointAutoConfiguration.class)); + WebEndpointAutoConfiguration.class, EndpointAutoConfiguration.class)) + .withUserConfiguration(WebServerConfiguration.class, TestServletManagementContextConfiguration.class); contextRunner.withPropertyValues("server.port=0", "management.server.port=0").prepare((context) -> { TestGenerationContext generationContext = new TestGenerationContext(TestTarget.class); ClassName className = new ApplicationContextAotGenerator().processAheadOfTime( @@ -78,10 +82,10 @@ class ChildManagementContextInitializerAotTests { ApplicationContextInitializer initializer = compiled .getInstance(ApplicationContextInitializer.class, className.toString()); initializer.initialize(freshApplicationContext); - assertThat(output).satisfies(numberOfOccurrences("Tomcat started on port", 0)); + assertThat(output).satisfies(numberOfOccurrences("WebServer started", 0)); TestPropertyValues.of(AotDetector.AOT_ENABLED + "=true") .applyToSystemProperties(freshApplicationContext::refresh); - assertThat(output).satisfies(numberOfOccurrences("Tomcat started on port", 2)); + assertThat(output).satisfies(numberOfOccurrences("WebServer started", 2)); }); }); } @@ -97,4 +101,40 @@ class ChildManagementContextInitializerAotTests { } + @Configuration(proxyBeanMethods = false) + static class TestServletManagementContextConfiguration { + + @Bean + ManagementContextFactory managementContextFactory() { + return new ManagementContextFactory(WebApplicationType.SERVLET, LogOnStartServletWebServerFactory.class); + } + + } + + @Configuration(proxyBeanMethods = false) + static class WebServerConfiguration { + + @Bean + LogOnStartServletWebServerFactory servletWebServerFactory() { + return new LogOnStartServletWebServerFactory(); + } + + } + + static class LogOnStartServletWebServerFactory extends MockServletWebServerFactory { + + private static final Log log = LogFactory.getLog(LogOnStartServletWebServerFactory.class); + + @Override + public MockServletWebServer getWebServer(ServletContextInitializer... initializers) { + WebServer webServer = super.getWebServer(initializers); + willAnswer((invocation) -> { + log.info("WebServer started"); + return null; + }).given(webServer).start(); + return (MockServletWebServer) webServer; + } + + } + } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure-all/src/test/java/org/springframework/boot/actuate/autoconfigure/web/server/ManagementContextAutoConfigurationTests.java b/spring-boot-project/spring-boot-servlet/src/test/java/org/springframework/boot/servlet/actuate/autoconfigure/ServletManagementContextAutoConfigurationIntegrationTests.java similarity index 92% rename from spring-boot-project/spring-boot-actuator-autoconfigure-all/src/test/java/org/springframework/boot/actuate/autoconfigure/web/server/ManagementContextAutoConfigurationTests.java rename to spring-boot-project/spring-boot-servlet/src/test/java/org/springframework/boot/servlet/actuate/autoconfigure/ServletManagementContextAutoConfigurationIntegrationTests.java index e8a208c4fb..386c4c6a50 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure-all/src/test/java/org/springframework/boot/actuate/autoconfigure/web/server/ManagementContextAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-servlet/src/test/java/org/springframework/boot/servlet/actuate/autoconfigure/ServletManagementContextAutoConfigurationIntegrationTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.actuate.autoconfigure.web.server; +package org.springframework.boot.servlet.actuate.autoconfigure; import java.util.function.Consumer; @@ -23,27 +23,26 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration; +import org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.servlet.actuate.autoconfigure.ServletManagementContextAutoConfiguration; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; import org.springframework.boot.test.system.CapturedOutput; import org.springframework.boot.test.system.OutputCaptureExtension; import org.springframework.boot.tomcat.actuate.autoconfigure.web.TomcatServletManagementContextAutoConfiguration; import org.springframework.boot.tomcat.autoconfigure.servlet.TomcatServletWebServerAutoConfiguration; import org.springframework.boot.web.server.servlet.context.AnnotationConfigServletWebServerApplicationContext; -import org.springframework.boot.webmvc.autoconfigure.DispatcherServletAutoConfiguration; import org.springframework.util.StringUtils; import static org.assertj.core.api.Assertions.assertThat; /** - * Tests for {@link ManagementContextAutoConfiguration}. + * Integration tests for {@link ServletManagementContextAutoConfiguration}. * * @author Madhura Bhave * @author Andy Wilkinson */ @ExtendWith(OutputCaptureExtension.class) -class ManagementContextAutoConfigurationTests { +class ServletManagementContextAutoConfigurationIntegrationTests { @Test void childManagementContextShouldStartForEmbeddedServer(CapturedOutput output) { @@ -95,8 +94,7 @@ class ManagementContextAutoConfigurationTests { AnnotationConfigServletWebServerApplicationContext::new) .withConfiguration(AutoConfigurations.of(ManagementContextAutoConfiguration.class, TomcatServletWebServerAutoConfiguration.class, ServletManagementContextAutoConfiguration.class, - WebEndpointAutoConfiguration.class, EndpointAutoConfiguration.class, - DispatcherServletAutoConfiguration.class)); + WebEndpointAutoConfiguration.class, EndpointAutoConfiguration.class)); contextRunner.withPropertyValues("server.port=0", "management.server.address=127.0.0.1") .run((context) -> assertThat(context).getFailure() .hasMessageStartingWith("Management-specific server address cannot be configured"));