Make ConversionService customisable

- Add ShellConversionServiceSupplier interface to define
  shell spesific ConversionService so that we don't
  get trouble with other services in boot.
- Fixes #435
This commit is contained in:
Janne Valkealahti
2022-05-31 12:58:10 +01:00
parent 3891a8b375
commit 7201a25567
4 changed files with 41 additions and 34 deletions

View File

@@ -3,10 +3,8 @@ package org.springframework.shell.boot;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.ConversionService;
import org.springframework.messaging.handler.annotation.support.HeadersMethodArgumentResolver;
import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver;
import org.springframework.shell.command.ArgumentHeaderMethodArgumentResolver;
@@ -14,6 +12,7 @@ import org.springframework.shell.command.CommandContextMethodArgumentResolver;
import org.springframework.shell.command.CommandExecution.CommandExecutionHandlerMethodArgumentResolvers;
import org.springframework.shell.completion.CompletionResolver;
import org.springframework.shell.completion.DefaultCompletionResolver;
import org.springframework.shell.config.ShellConversionServiceSupplier;
import org.springframework.shell.standard.ShellOptionMethodArgumentResolver;
@Configuration(proxyBeanMethods = false)
@@ -26,12 +25,12 @@ public class ParameterResolverAutoConfiguration {
@Bean
public CommandExecutionHandlerMethodArgumentResolvers commandExecutionHandlerMethodArgumentResolvers(
@Qualifier("shellConversionService") ConversionService shellConversionService) {
ShellConversionServiceSupplier shellConversionServiceSupplier) {
List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>();
resolvers.add(new ArgumentHeaderMethodArgumentResolver(shellConversionService, null));
resolvers.add(new ArgumentHeaderMethodArgumentResolver(shellConversionServiceSupplier.get(), null));
resolvers.add(new HeadersMethodArgumentResolver());
resolvers.add(new CommandContextMethodArgumentResolver());
resolvers.add(new ShellOptionMethodArgumentResolver(shellConversionService, null));
resolvers.add(new ShellOptionMethodArgumentResolver(shellConversionServiceSupplier.get(), null));
return new CommandExecutionHandlerMethodArgumentResolvers(resolvers);
}
}

View File

@@ -20,20 +20,19 @@ import java.util.Set;
import org.jline.terminal.Terminal;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.convert.ApplicationConversionService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.format.support.FormattingConversionService;
import org.springframework.shell.ResultHandler;
import org.springframework.shell.ResultHandlerService;
import org.springframework.shell.Shell;
import org.springframework.shell.command.CommandCatalog;
import org.springframework.shell.config.ShellConversionServiceSupplier;
import org.springframework.shell.context.ShellContext;
import org.springframework.shell.exit.ExitCodeMappings;
import org.springframework.shell.result.GenericResultHandlerService;
@@ -47,13 +46,13 @@ import org.springframework.shell.result.ResultHandlerConfig;
public class SpringShellAutoConfiguration {
@Bean
@ConditionalOnMissingBean(value = ConversionService.class, name = { "shellConversionService" })
public ConversionService shellConversionService(ApplicationContext applicationContext) {
@ConditionalOnMissingBean
public ShellConversionServiceSupplier shellConversionServiceSupplier(ApplicationContext applicationContext) {
FormattingConversionService service = new FormattingConversionService();
DefaultConversionService.addDefaultConverters(service);
DefaultConversionService.addCollectionConverters(service);
ApplicationConversionService.addBeans(service, applicationContext);
return service;
return () -> service;
}
@Bean
@@ -67,10 +66,10 @@ public class SpringShellAutoConfiguration {
@Bean
public Shell shell(ResultHandlerService resultHandlerService, CommandCatalog commandRegistry, Terminal terminal,
@Qualifier("shellConversionService") ConversionService shellConversionService, ShellContext shellContext,
ShellConversionServiceSupplier shellConversionServiceSupplier, ShellContext shellContext,
ExitCodeMappings exitCodeMappings) {
Shell shell = new Shell(resultHandlerService, commandRegistry, terminal, shellContext, exitCodeMappings);
shell.setConversionService(shellConversionService);
shell.setConversionService(shellConversionServiceSupplier.get());
return shell;
}
}

View File

@@ -21,10 +21,10 @@ import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.shell.command.CommandExecution.CommandExecutionHandlerMethodArgumentResolvers;
import org.springframework.shell.completion.CompletionResolver;
import org.springframework.shell.config.ShellConversionServiceSupplier;
import static org.assertj.core.api.Assertions.assertThat;
@@ -49,31 +49,12 @@ public class ParameterResolverAutoConfigurationTests {
});
}
@Test
void multipleConversionServiceBeans() {
this.contextRunner
.withUserConfiguration(CustomShellConversionServiceConfiguration.class,
ExtraConversionServiceConfiguration.class)
.run((context) -> {
assertThat(context).hasSingleBean(CommandExecutionHandlerMethodArgumentResolvers.class);
});
}
@Configuration
static class CustomShellConversionServiceConfiguration {
@Bean
ConversionService shellConversionService() {
return new DefaultConversionService();
}
}
@Configuration
static class ExtraConversionServiceConfiguration {
@Bean
ConversionService conversionService() {
return new DefaultConversionService();
ShellConversionServiceSupplier shellConversionServiceSupplier() {
return () -> new DefaultConversionService();
}
}
}

View File

@@ -0,0 +1,28 @@
/*
* Copyright 2022 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.config;
import java.util.function.Supplier;
import org.springframework.core.convert.ConversionService;
/**
* Interface to provide shell spesific {@link ConversionService}.
*
* @author Janne Valkealahti
*/
public interface ShellConversionServiceSupplier extends Supplier<ConversionService> {
}