Commit 1e2eec5b authored by Stephane Nicoll's avatar Stephane Nicoll

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
parent 8b298238
...@@ -335,10 +335,17 @@ public class SpringApplication { ...@@ -335,10 +335,17 @@ public class SpringApplication {
callRunners(context, applicationArguments); callRunners(context, applicationArguments);
} }
catch (Throwable ex) { 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); throw new IllegalStateException(ex);
} }
listeners.running(context);
return context; return context;
} }
...@@ -795,13 +802,15 @@ public class SpringApplication { ...@@ -795,13 +802,15 @@ public class SpringApplication {
} }
private void handleRunFailure(ConfigurableApplicationContext context, private void handleRunFailure(ConfigurableApplicationContext context,
SpringApplicationRunListeners listeners, Throwable exception,
Collection<SpringBootExceptionReporter> exceptionReporters, Collection<SpringBootExceptionReporter> exceptionReporters,
Throwable exception) { SpringApplicationRunListeners listeners) {
try { try {
try { try {
handleExitCode(context, exception); handleExitCode(context, exception);
listeners.failed(context, exception); if (listeners != null) {
listeners.failed(context, exception);
}
} }
finally { finally {
reportFailure(exceptionReporters, exception); reportFailure(exceptionReporters, exception);
......
...@@ -707,6 +707,32 @@ public class SpringApplicationTests { ...@@ -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 @Test
public void loadSources() { public void loadSources() {
Class<?>[] sources = { ExampleConfig.class, TestCommandLineRunner.class }; Class<?>[] sources = { ExampleConfig.class, TestCommandLineRunner.class };
...@@ -1427,14 +1453,14 @@ public class SpringApplicationTests { ...@@ -1427,14 +1453,14 @@ public class SpringApplicationTests {
private static class ExitCodeListener implements ApplicationListener<ExitCodeEvent> { private static class ExitCodeListener implements ApplicationListener<ExitCodeEvent> {
private int exitCode; private Integer exitCode;
@Override @Override
public void onApplicationEvent(ExitCodeEvent event) { public void onApplicationEvent(ExitCodeEvent event) {
this.exitCode = event.getExitCode(); this.exitCode = event.getExitCode();
} }
public int getExitCode() { public Integer getExitCode() {
return this.exitCode; return this.exitCode;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment