Commit 03669002 authored by Andy Wilkinson's avatar Andy Wilkinson

Check for null context when trying to find an exception mapper

If application context refresh fails, SpringApplication will have a 
null context. Previously, this would result in an NPE when looking for
an ExitCodeExceptionMapper.

This commit updates SpringApplication to gracefully handle the context
being null when looking for an ExitCodeExceptionMapper.

Closes gh-4803
parent ea5195c8
......@@ -881,6 +881,9 @@ public class SpringApplication {
private int getExitCodeFromMappedException(ConfigurableApplicationContext context,
Throwable exception) {
if (context == null) {
return 0;
}
ExitCodeGenerators generators = new ExitCodeGenerators();
Collection<ExitCodeExceptionMapper> beans = context
.getBeansOfType(ExitCodeExceptionMapper.class).values();
......
......@@ -24,6 +24,8 @@ import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import javax.annotation.PostConstruct;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
......@@ -74,6 +76,7 @@ import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.isA;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.sameInstance;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.assertArrayEquals;
......@@ -83,6 +86,7 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
......@@ -615,6 +619,31 @@ public class SpringApplicationTests {
assertThat(listener.getExitCode(), equalTo(11));
}
@Test
public void exceptionFromRefreshIsHandledGracefully() throws Exception {
final SpringBootExceptionHandler handler = mock(SpringBootExceptionHandler.class);
SpringApplication application = new SpringApplication(
RefreshFailureConfig.class) {
@Override
SpringBootExceptionHandler getSpringBootExceptionHandler() {
return handler;
}
};
ExitCodeListener listener = new ExitCodeListener();
application.addListeners(listener);
application.setWebEnvironment(false);
try {
application.run();
fail("Did not throw");
}
catch (RuntimeException ex) {
}
verify(handler).registerLoggedException(any(RefreshFailureException.class));
assertThat(this.output.toString(), not(containsString("NullPointerException")));
}
@Test
public void defaultCommandLineArgs() throws Exception {
SpringApplication application = new SpringApplication(ExampleConfig.class);
......@@ -966,6 +995,15 @@ public class SpringApplicationTests {
}
@Configuration
static class RefreshFailureConfig {
@PostConstruct
public void fail() {
throw new RefreshFailureException();
}
}
static class ExitStatusException extends RuntimeException
implements ExitCodeGenerator {
......@@ -976,6 +1014,10 @@ public class SpringApplicationTests {
}
static class RefreshFailureException extends RuntimeException {
}
static class AbstractTestRunner implements ApplicationContextAware, Ordered {
private final String[] expectedBefore;
......
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