diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/ChildManagementContextInitializer.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/ChildManagementContextInitializer.java index 38a6a68f36..579e7d7126 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/ChildManagementContextInitializer.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/ChildManagementContextInitializer.java @@ -33,12 +33,13 @@ import org.springframework.boot.actuate.autoconfigure.web.ManagementContextFacto import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.context.event.ApplicationFailedEvent; import org.springframework.boot.web.context.ConfigurableWebServerApplicationContext; -import org.springframework.boot.web.context.WebServerInitializedEvent; +import org.springframework.boot.web.context.WebServerGracefulShutdownLifecycle; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.SmartLifecycle; import org.springframework.context.annotation.AnnotationConfigRegistry; import org.springframework.context.aot.ApplicationContextAotGenerator; import org.springframework.context.event.ContextClosedEvent; @@ -55,8 +56,7 @@ import org.springframework.util.Assert; * @author Andy Wilkinson * @author Phillip Webb */ -class ChildManagementContextInitializer - implements ApplicationListener, BeanRegistrationAotProcessor { +class ChildManagementContextInitializer implements BeanRegistrationAotProcessor, SmartLifecycle { private final ManagementContextFactory managementContextFactory; @@ -64,6 +64,8 @@ class ChildManagementContextInitializer private final ApplicationContextInitializer applicationContextInitializer; + private volatile ConfigurableApplicationContext managementContext; + ChildManagementContextInitializer(ManagementContextFactory managementContextFactory, ApplicationContext parentContext) { this(managementContextFactory, parentContext, null); @@ -79,12 +81,33 @@ class ChildManagementContextInitializer } @Override - public void onApplicationEvent(WebServerInitializedEvent event) { - if (event.getApplicationContext().equals(this.parentContext)) { + public void start() { + if (this.managementContext == null) { ConfigurableApplicationContext managementContext = createManagementContext(); registerBeans(managementContext); managementContext.refresh(); + this.managementContext = managementContext; } + else { + this.managementContext.start(); + } + } + + @Override + public void stop() { + if (this.managementContext != null) { + this.managementContext.stop(); + } + } + + @Override + public boolean isRunning() { + return this.managementContext != null && this.managementContext.isRunning(); + } + + @Override + public int getPhase() { + return WebServerGracefulShutdownLifecycle.SMART_LIFECYCLE_PHASE + 512; } @Override diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/server/ManagementContextAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/server/ManagementContextAutoConfigurationTests.java index 1d4e7c7319..52fca8b17a 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/server/ManagementContextAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/server/ManagementContextAutoConfigurationTests.java @@ -55,6 +55,21 @@ class ManagementContextAutoConfigurationTests { .run((context) -> assertThat(output).satisfies(numberOfOccurrences("Tomcat started on port", 2))); } + @Test + void childManagementContextShouldRestartWhenParentIsStoppedThenStarted(CapturedOutput output) { + WebApplicationContextRunner contextRunner = new WebApplicationContextRunner( + AnnotationConfigServletWebServerApplicationContext::new) + .withConfiguration(AutoConfigurations.of(ManagementContextAutoConfiguration.class, + ServletWebServerFactoryAutoConfiguration.class, ServletManagementContextAutoConfiguration.class, + WebEndpointAutoConfiguration.class, EndpointAutoConfiguration.class)); + contextRunner.withPropertyValues("server.port=0", "management.server.port=0").run((context) -> { + assertThat(output).satisfies(numberOfOccurrences("Tomcat started on port", 2)); + context.getSourceApplicationContext().stop(); + context.getSourceApplicationContext().start(); + assertThat(output).satisfies(numberOfOccurrences("Tomcat started on port", 4)); + }); + } + @Test void givenSamePortManagementServerWhenManagementServerAddressIsConfiguredThenContextRefreshFails() { WebApplicationContextRunner contextRunner = new WebApplicationContextRunner(