diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java index 11f0287e0e5..755d98c4d7f 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java @@ -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 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); diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java index 02f71004d2c..6bed2b01cbd 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java @@ -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 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 { - 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; }