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