Commit 75af7a44 authored by Phillip Webb's avatar Phillip Webb

Add SpringApplication.setRegisterShutdownHook

Add a setRegisterShutdownHook option to SpringApplication allowing the
shutdown hook to not be registered.

Also update SpringApplicationBuilder to automatically disable shutdown
hooks for child contexts.

Fixes gh-314
parent 0b7eda89
......@@ -177,6 +177,8 @@ public class SpringApplication {
private boolean headless = true;
private boolean registerShutdownHook = true;
private List<ApplicationContextInitializer<?>> initializers;
private List<ApplicationListener<?>> listeners;
......@@ -284,7 +286,9 @@ public class SpringApplication {
// Create, load, refresh and run the ApplicationContext
context = createApplicationContext();
context.registerShutdownHook();
if (this.registerShutdownHook) {
context.registerShutdownHook();
}
context.setEnvironment(environment);
postProcessApplicationContext(context);
applyInitializers(context);
......@@ -669,6 +673,15 @@ public class SpringApplication {
this.headless = headless;
}
/**
* Sets if the created {@link ApplicationContext} should have a shutdown hook
* registered. Defaults to {@code true} to ensure that JVM shutdowns are handled
* gracefully.
*/
public void setRegisterShutdownHook(boolean registerShutdownHook) {
this.registerShutdownHook = registerShutdownHook;
}
/**
* Sets if the Spring banner should be displayed when the application runs. Defaults
* to {@code true}.
......
......@@ -79,6 +79,8 @@ public class SpringApplicationBuilder {
private Set<String> additionalProfiles = new LinkedHashSet<String>();
private boolean registerShutdownHookApplied;
public SpringApplicationBuilder(Object... sources) {
this.application = new SpringApplication(sources);
}
......@@ -109,8 +111,11 @@ public class SpringApplicationBuilder {
public ConfigurableApplicationContext run(String... args) {
if (this.parent != null) {
// If there is a parent initialize it and make sure it is added to the current
// context
// If there is a parent don't register a shutdown hook
if (!this.registerShutdownHookApplied) {
this.application.setRegisterShutdownHook(false);
}
// initialize it and make sure it is added to the current context
initializers(new ParentContextApplicationContextInitializer(
this.parent.run(args)));
}
......@@ -201,6 +206,7 @@ public class SpringApplicationBuilder {
this.parent.context = parent;
this.parent.running.set(true);
initializers(new ParentContextApplicationContextInitializer(parent));
return this;
}
......@@ -300,6 +306,16 @@ public class SpringApplicationBuilder {
return this;
}
/**
* Sets if the created {@link ApplicationContext} should have a shutdown hook
* registered.
*/
public SpringApplicationBuilder registerShutdownHook(boolean registerShutdownHook) {
this.registerShutdownHookApplied = true;
this.application.setRegisterShutdownHook(registerShutdownHook);
return this;
}
/**
* Fixes the main application class that is used to anchor the startup messages.
* @param mainApplicationClass the class to use.
......
......@@ -393,6 +393,17 @@ public class SpringApplicationTests {
verify(applicationContext.getApplicationContext()).registerShutdownHook();
}
@Test
public void registerShutdownHookOff() throws Exception {
SpringApplication application = new SpringApplication(ExampleConfig.class);
application.setApplicationContextClass(SpyApplicationContext.class);
application.setRegisterShutdownHook(false);
this.context = application.run();
SpyApplicationContext applicationContext = (SpyApplicationContext) this.context;
verify(applicationContext.getApplicationContext(), never())
.registerShutdownHook();
}
@Test
public void headless() throws Exception {
TestSpringApplication application = new TestSpringApplication(ExampleConfig.class);
......
......@@ -108,6 +108,21 @@ public class SpringApplicationBuilderTests {
this.context = application.run();
verify(((SpyApplicationContext) this.context).getApplicationContext()).setParent(
any(ApplicationContext.class));
assertThat(((SpyApplicationContext) this.context).getRegisteredShutdownHook(),
equalTo(false));
}
@Test
public void parentContextCreationWithChildShutdown() throws Exception {
SpringApplicationBuilder application = new SpringApplicationBuilder(
ChildConfig.class).contextClass(SpyApplicationContext.class)
.registerShutdownHook(true);
application.parent(ExampleConfig.class);
this.context = application.run();
verify(((SpyApplicationContext) this.context).getApplicationContext()).setParent(
any(ApplicationContext.class));
assertThat(((SpyApplicationContext) this.context).getRegisteredShutdownHook(),
equalTo(true));
}
@Test
......@@ -143,6 +158,8 @@ public class SpringApplicationBuilderTests {
this.context = application.run();
verify(((SpyApplicationContext) this.context).getApplicationContext()).setParent(
any(ApplicationContext.class));
assertThat(((SpyApplicationContext) this.context).getRegisteredShutdownHook(),
equalTo(false));
}
@Test
......@@ -216,8 +233,11 @@ public class SpringApplicationBuilderTests {
public static class SpyApplicationContext extends AnnotationConfigApplicationContext {
private final ConfigurableApplicationContext applicationContext = spy(new AnnotationConfigApplicationContext());
private ResourceLoader resourceLoader;
private boolean registeredShutdownHook;
@Override
public void setParent(ApplicationContext parent) {
this.applicationContext.setParent(parent);
......@@ -237,5 +257,14 @@ public class SpringApplicationBuilderTests {
return this.resourceLoader;
}
@Override
public void registerShutdownHook() {
super.registerShutdownHook();
this.registeredShutdownHook = true;
}
public boolean getRegisteredShutdownHook() {
return this.registeredShutdownHook;
}
}
}
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