Merge pull request #44310 from nosan
* pr/44310: Polish contribution Catch WebServer stop or destroy exception when context refresh fails Closes gh-44310
This commit is contained in:
commit
84998f91a9
|
|
@ -68,8 +68,13 @@ public class ReactiveWebServerApplicationContext extends GenericReactiveWebAppli
|
|||
catch (RuntimeException ex) {
|
||||
WebServer webServer = getWebServer();
|
||||
if (webServer != null) {
|
||||
webServer.stop();
|
||||
webServer.destroy();
|
||||
try {
|
||||
webServer.stop();
|
||||
webServer.destroy();
|
||||
}
|
||||
catch (RuntimeException stopOrDestroyEx) {
|
||||
ex.addSuppressed(stopOrDestroyEx);
|
||||
}
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -146,10 +146,15 @@ public class ServletWebServerApplicationContext extends GenericWebApplicationCon
|
|||
super.refresh();
|
||||
}
|
||||
catch (RuntimeException ex) {
|
||||
WebServer webServer = this.webServer;
|
||||
if (webServer != null) {
|
||||
webServer.stop();
|
||||
webServer.destroy();
|
||||
try {
|
||||
WebServer webServer = this.webServer;
|
||||
if (webServer != null) {
|
||||
webServer.stop();
|
||||
webServer.destroy();
|
||||
}
|
||||
}
|
||||
catch (RuntimeException stopOrDestroyEx) {
|
||||
ex.addSuppressed(stopOrDestroyEx);
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
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.BDDMockito.willThrow;
|
||||
import static org.mockito.Mockito.times;
|
||||
|
||||
/**
|
||||
|
|
@ -133,6 +134,40 @@ class ReactiveWebServerApplicationContextTests {
|
|||
then(webServer).should().destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenContextRefreshFailedThenWebServerStopFailedCatchStopException() {
|
||||
addWebServerFactoryBean();
|
||||
addHttpHandlerBean();
|
||||
this.context.registerBeanDefinition("refreshFailure", new RootBeanDefinition(RefreshFailure.class, () -> {
|
||||
willThrow(new RuntimeException("WebServer has failed to stop")).willCallRealMethod()
|
||||
.given(this.context.getWebServer())
|
||||
.stop();
|
||||
return new RefreshFailure();
|
||||
}));
|
||||
assertThatExceptionOfType(BeanCreationException.class).isThrownBy(this.context::refresh)
|
||||
.withStackTraceContaining("WebServer has failed to stop");
|
||||
WebServer webServer = this.context.getWebServer();
|
||||
then(webServer).should().stop();
|
||||
then(webServer).should(times(0)).destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenContextRefreshFailedThenWebServerIsStoppedAndDestroyFailedCatchDestroyException() {
|
||||
addWebServerFactoryBean();
|
||||
addHttpHandlerBean();
|
||||
this.context.registerBeanDefinition("refreshFailure", new RootBeanDefinition(RefreshFailure.class, () -> {
|
||||
willThrow(new RuntimeException("WebServer has failed to destroy")).willCallRealMethod()
|
||||
.given(this.context.getWebServer())
|
||||
.destroy();
|
||||
return new RefreshFailure();
|
||||
}));
|
||||
assertThatExceptionOfType(BeanCreationException.class).isThrownBy(this.context::refresh)
|
||||
.withStackTraceContaining("WebServer has failed to destroy");
|
||||
WebServer webServer = this.context.getWebServer();
|
||||
then(webServer).should().stop();
|
||||
then(webServer).should().destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenContextIsClosedThenWebServerIsStoppedAndDestroyed() {
|
||||
addWebServerFactoryBean();
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -51,6 +51,7 @@ import org.springframework.boot.availability.AvailabilityChangeEvent;
|
|||
import org.springframework.boot.testsupport.system.CapturedOutput;
|
||||
import org.springframework.boot.testsupport.system.OutputCaptureExtension;
|
||||
import org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer;
|
||||
import org.springframework.boot.web.server.WebServer;
|
||||
import org.springframework.boot.web.servlet.DelegatingFilterProxyRegistrationBean;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.boot.web.servlet.ServletContextInitializer;
|
||||
|
|
@ -81,6 +82,7 @@ import static org.mockito.ArgumentMatchers.any;
|
|||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.BDDMockito.then;
|
||||
import static org.mockito.BDDMockito.willThrow;
|
||||
import static org.mockito.Mockito.atMost;
|
||||
import static org.mockito.Mockito.inOrder;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
|
@ -211,6 +213,48 @@ class ServletWebServerApplicationContextTests {
|
|||
assertThat(listener.receivedEvents()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenContextRefreshFailedThenWebServerIsStoppedAndDestroyed() {
|
||||
addWebServerFactoryBean();
|
||||
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 whenContextRefreshFailedThenWebServerStopFailedCatchStopException() {
|
||||
addWebServerFactoryBean();
|
||||
this.context.registerBeanDefinition("refreshFailure", new RootBeanDefinition(RefreshFailure.class, () -> {
|
||||
willThrow(new RuntimeException("WebServer has failed to stop")).willCallRealMethod()
|
||||
.given(this.context.getWebServer())
|
||||
.stop();
|
||||
return new RefreshFailure();
|
||||
}));
|
||||
assertThatExceptionOfType(BeanCreationException.class).isThrownBy(this.context::refresh)
|
||||
.withStackTraceContaining("WebServer has failed to stop");
|
||||
WebServer webServer = this.context.getWebServer();
|
||||
then(webServer).should().stop();
|
||||
then(webServer).should(times(0)).destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenContextRefreshFailedThenWebServerIsStoppedAndDestroyFailedCatchDestroyException() {
|
||||
addWebServerFactoryBean();
|
||||
this.context.registerBeanDefinition("refreshFailure", new RootBeanDefinition(RefreshFailure.class, () -> {
|
||||
willThrow(new RuntimeException("WebServer has failed to destroy")).willCallRealMethod()
|
||||
.given(this.context.getWebServer())
|
||||
.destroy();
|
||||
return new RefreshFailure();
|
||||
}));
|
||||
assertThatExceptionOfType(BeanCreationException.class).isThrownBy(this.context::refresh)
|
||||
.withStackTraceContaining("WebServer has failed to destroy");
|
||||
WebServer webServer = this.context.getWebServer();
|
||||
then(webServer).should().stop();
|
||||
then(webServer).should().destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
void cannotSecondRefresh() {
|
||||
addWebServerFactoryBean();
|
||||
|
|
|
|||
Loading…
Reference in New Issue