Browse Source

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
pull/12666/head
Stephane Nicoll 8 years ago
parent
commit
1e2eec5bcd
  1. 19
      spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java
  2. 30
      spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java

19
spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java

@ -335,10 +335,17 @@ public class SpringApplication { @@ -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 { @@ -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);

30
spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java

@ -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
public void loadSources() {
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 int exitCode;
private Integer exitCode;
@Override
public void onApplicationEvent(ExitCodeEvent event) {
this.exitCode = event.getExitCode();
}
public int getExitCode() {
public Integer getExitCode() {
return this.exitCode;
}

Loading…
Cancel
Save