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
This commit is contained in:
Andy Wilkinson 2016-01-21 10:21:07 +00:00
parent ea5195c8a6
commit 03669002de
2 changed files with 45 additions and 0 deletions

View File

@ -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();

View File

@ -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;