diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/context/ReactiveWebServerApplicationContext.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/context/ReactiveWebServerApplicationContext.java index eca86f28a784..9ff12bd8238d 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/context/ReactiveWebServerApplicationContext.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/context/ReactiveWebServerApplicationContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 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. @@ -66,9 +66,10 @@ public final void refresh() throws BeansException, IllegalStateException { super.refresh(); } catch (RuntimeException ex) { - WebServerManager serverManager = this.serverManager; - if (serverManager != null) { - serverManager.getWebServer().stop(); + WebServer webServer = getWebServer(); + if (webServer != null) { + webServer.stop(); + webServer.destroy(); } throw ex; } @@ -147,6 +148,10 @@ protected void doClose() { AvailabilityChangeEvent.publish(this, ReadinessState.REFUSING_TRAFFIC); } super.doClose(); + WebServer webServer = getWebServer(); + if (webServer != null) { + webServer.destroy(); + } } /** diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/reactive/context/ReactiveWebServerApplicationContextTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/reactive/context/ReactiveWebServerApplicationContextTests.java index 3db25d347352..e87deafa73ca 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/reactive/context/ReactiveWebServerApplicationContextTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/reactive/context/ReactiveWebServerApplicationContextTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 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. @@ -30,6 +30,7 @@ import org.springframework.boot.availability.ReadinessState; import org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer; import org.springframework.boot.web.reactive.server.MockReactiveWebServerFactory; +import org.springframework.boot.web.server.WebServer; import org.springframework.context.ApplicationContextException; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; @@ -42,6 +43,7 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatIllegalStateException; import static org.mockito.BDDMockito.then; +import static org.mockito.Mockito.times; /** * Tests for {@link ReactiveWebServerApplicationContext}. @@ -121,13 +123,25 @@ void whenContextIsRefreshedThenLocalServerPortIsAvailableFromTheEnvironment() { } @Test - void whenContextIsClosedThenWebServerIsStopped() { + void whenContextRefreshFailedThenWebServerIsStoppedAndDestroyed() { + addWebServerFactoryBean(); + addHttpHandlerBean(); + this.context.registerBeanDefinition("refreshFailure", new RootBeanDefinition(RefreshFailure.class)); + assertThatExceptionOfType(BeanCreationException.class).isThrownBy(this.context::refresh); + WebServer webServer = this.context.getWebServer(); + then(webServer).should(times(2)).stop(); + then(webServer).should().destroy(); + } + + @Test + void whenContextIsClosedThenWebServerIsStoppedAndDestroyed() { addWebServerFactoryBean(); addHttpHandlerBean(); this.context.refresh(); MockReactiveWebServerFactory factory = this.context.getBean(MockReactiveWebServerFactory.class); this.context.close(); - then(factory.getWebServer()).should().stop(); + then(factory.getWebServer()).should(times(2)).stop(); + then(factory.getWebServer()).should().destroy(); } @Test