Optionally close context after command logic

- spring.shell.context.close=true adds ApplicationListerner
  which attempts to close context with ApplicationReadyEvent.
- Relates #863
This commit is contained in:
Janne Valkealahti
2023-09-12 08:08:23 +03:00
parent 51c250608b
commit 2e5264a379
4 changed files with 88 additions and 1 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2021 the original author or authors.
* Copyright 2021-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,7 +19,10 @@ import java.util.List;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.shell.DefaultShellApplicationRunner;
import org.springframework.shell.ShellApplicationRunner;
@@ -34,4 +37,20 @@ public class ApplicationRunnerAutoConfiguration {
public DefaultShellApplicationRunner defaultShellApplicationRunner(List<ShellRunner> shellRunners) {
return new DefaultShellApplicationRunner(shellRunners);
}
@Bean
@ConditionalOnProperty(prefix = "spring.shell.context", name = "close", havingValue = "true")
public ApplicationReadyEventListener applicationReadyEventListener() {
return new ApplicationReadyEventListener();
}
static class ApplicationReadyEventListener implements ApplicationListener<ApplicationReadyEvent>{
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
// request context close after application runners so that
// shell exits in case that context is kept alive
event.getApplicationContext().close();
}
}
}

View File

@@ -34,6 +34,7 @@ public class SpringShellProperties {
private Command command = new Command();
private Help help = new Help();
private Option option = new Option();
private Context context = new Context();
public void setConfig(Config config) {
this.config = config;
@@ -107,6 +108,14 @@ public class SpringShellProperties {
this.option = option;
}
public Context getContext() {
return context;
}
public void setContext(Context context) {
this.context = context;
}
public static class Config {
private String env;
@@ -603,6 +612,19 @@ public class SpringShellProperties {
}
}
public static class Context {
private boolean close = false;
public boolean isClose() {
return close;
}
public void setClose(boolean close) {
this.close = close;
}
}
public static enum OptionNamingCase {
NOOP,
CAMEL,

View File

@@ -0,0 +1,43 @@
/*
* Copyright 2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.shell.boot;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import static org.assertj.core.api.Assertions.assertThat;
public class ApplicationRunnerAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(ApplicationRunnerAutoConfiguration.class));
@Test
void contextCloseDisabledByDefault() {
contextRunner.run(context -> assertThat(context)
.doesNotHaveBean(ApplicationRunnerAutoConfiguration.ApplicationReadyEventListener.class));
}
@Test
void contextCloseEnabled() {
contextRunner.withPropertyValues("spring.shell.context.close:true")
.run(context -> assertThat(context)
.hasSingleBean(ApplicationRunnerAutoConfiguration.ApplicationReadyEventListener.class));
}
}

View File

@@ -70,6 +70,7 @@ public class SpringShellPropertiesTests {
assertThat(properties.getHelp().getLongNames()).containsExactly("help");
assertThat(properties.getHelp().getShortNames()).containsExactly('h');
assertThat(properties.getOption().getNaming().getCaseType()).isEqualTo(OptionNamingCase.NOOP);
assertThat(properties.getContext().isClose()).isFalse();
});
}
@@ -112,6 +113,7 @@ public class SpringShellPropertiesTests {
.withPropertyValues("spring.shell.help.long-names=fake")
.withPropertyValues("spring.shell.help.short-names=f")
.withPropertyValues("spring.shell.option.naming.case-type=camel")
.withPropertyValues("spring.shell.context.close=true")
.withUserConfiguration(Config1.class)
.run((context) -> {
SpringShellProperties properties = context.getBean(SpringShellProperties.class);
@@ -151,6 +153,7 @@ public class SpringShellPropertiesTests {
assertThat(properties.getHelp().getLongNames()).containsExactly("fake");
assertThat(properties.getHelp().getShortNames()).containsExactly('f');
assertThat(properties.getOption().getNaming().getCaseType()).isEqualTo(OptionNamingCase.CAMEL);
assertThat(properties.getContext().isClose()).isTrue();
});
}