Close context if an ApplicationReadyEvent listener fails
This commit makes sure that the `ApplicationContext` is closed properly if an `ApplicationReadyListener` throws an exception. Closes gh-12549
This commit is contained in:
@@ -335,10 +335,17 @@ public class SpringApplication {
|
||||
callRunners(context, applicationArguments);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
handleRunFailure(context, listeners, exceptionReporters, ex);
|
||||
handleRunFailure(context, ex, exceptionReporters, listeners);
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
|
||||
try {
|
||||
listeners.running(context);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
handleRunFailure(context, ex, exceptionReporters, null);
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
listeners.running(context);
|
||||
return context;
|
||||
}
|
||||
|
||||
@@ -795,13 +802,15 @@ public class SpringApplication {
|
||||
}
|
||||
|
||||
private void handleRunFailure(ConfigurableApplicationContext context,
|
||||
SpringApplicationRunListeners listeners,
|
||||
Throwable exception,
|
||||
Collection<SpringBootExceptionReporter> exceptionReporters,
|
||||
Throwable exception) {
|
||||
SpringApplicationRunListeners listeners) {
|
||||
try {
|
||||
try {
|
||||
handleExitCode(context, exception);
|
||||
listeners.failed(context, exception);
|
||||
if (listeners != null) {
|
||||
listeners.failed(context, exception);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
reportFailure(exceptionReporters, exception);
|
||||
|
||||
@@ -707,6 +707,32 @@ public class SpringApplicationTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failureInReadyEventListenerCloseApplicationContext() {
|
||||
SpringApplication application = new SpringApplication(ExampleConfig.class);
|
||||
application.setWebApplicationType(WebApplicationType.NONE);
|
||||
ExitCodeListener exitCodeListener = new ExitCodeListener();
|
||||
application.addListeners(exitCodeListener);
|
||||
@SuppressWarnings("unchecked")
|
||||
ApplicationListener<SpringApplicationEvent> listener = mock(
|
||||
ApplicationListener.class);
|
||||
application.addListeners(listener);
|
||||
ExitStatusException failure = new ExitStatusException();
|
||||
willThrow(failure).given(listener)
|
||||
.onApplicationEvent(isA(ApplicationReadyEvent.class));
|
||||
try {
|
||||
application.run();
|
||||
fail("Run should have failed with a RuntimeException");
|
||||
}
|
||||
catch (RuntimeException ex) {
|
||||
verify(listener).onApplicationEvent(isA(ApplicationReadyEvent.class));
|
||||
verify(listener, never())
|
||||
.onApplicationEvent(isA(ApplicationFailedEvent.class));
|
||||
assertThat(exitCodeListener.getExitCode()).isEqualTo(11);
|
||||
assertThat(this.output.toString()).contains("Application run failed");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadSources() {
|
||||
Class<?>[] sources = { ExampleConfig.class, TestCommandLineRunner.class };
|
||||
@@ -1427,14 +1453,14 @@ public class SpringApplicationTests {
|
||||
|
||||
private static class ExitCodeListener implements ApplicationListener<ExitCodeEvent> {
|
||||
|
||||
private int exitCode;
|
||||
private Integer exitCode;
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ExitCodeEvent event) {
|
||||
this.exitCode = event.getExitCode();
|
||||
}
|
||||
|
||||
public int getExitCode() {
|
||||
public Integer getExitCode() {
|
||||
return this.exitCode;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user