Отображение списка в Yaml для списка объектов в Spring Загрузка

В моем загрузочном приложении Spring у меня есть файл конфигурации application.yaml со следующим контентом. Я хочу, чтобы он был введен как объект конфигурации со списком конфигураций каналов:

available-payment-channels-list:
  xyz: "123"
  channelConfigurations:
    -
      name: "Company X"
      companyBankAccount: "1000200030004000"
    -
      name: "Company Y"
      companyBankAccount: "1000200030004000"

И объект @Configuration Я хочу быть заполнен списком объектов PaymentConfiguration:

    @ConfigurationProperties(prefix = "available-payment-channels-list")
    @Configuration
    @RefreshScope
    public class AvailableChannelsConfiguration {

        private String xyz;

        private List<ChannelConfiguration> channelConfigurations;

        public AvailableChannelsConfiguration(String xyz, List<ChannelConfiguration> channelConfigurations) {
            this.xyz = xyz;
            this.channelConfigurations = channelConfigurations;
        }

        public AvailableChannelsConfiguration() {

        }

        // getters, setters


        @ConfigurationProperties(prefix = "available-payment-channels-list.channelConfigurations")
        @Configuration
        public static class ChannelConfiguration {
            private String name;
            private String companyBankAccount;

            public ChannelConfiguration(String name, String companyBankAccount) {
                this.name = name;
                this.companyBankAccount = companyBankAccount;
            }

            public ChannelConfiguration() {
            }

            // getters, setters
        }

    }

Я вставляю это как обычный bean с @Autowired конструктором. Значение xyz заполнено правильно, но когда Spring пытается проанализировать yaml в списке объектов, я получаю

   nested exception is java.lang.IllegalStateException: 
    Cannot convert value of type [java.lang.String] to required type    
    [io.example.AvailableChannelsConfiguration$ChannelConfiguration] 
    for property 'channelConfigurations[0]': no matching editors or 
    conversion strategy found]

Любые подсказки, что здесь не так?

Ответ 1

Причина должна быть где-то в другом месте. Используя только Spring Boot 1.2.2 из коробки без конфигурации, он просто работает. Посмотрите на это репо - вы можете заставить его сломаться?

https://github.com/konrad-garus/so-yaml

Вы уверены, что файл YAML выглядит так, как вы вставляете? Нет лишних пробелов, символов, специальных символов, неправильного ввода или что-то в этом роде? Возможно, у вас есть другой файл в другом месте пути поиска, который используется вместо того, который вы ожидаете?

Ответ 2

  • Вам не нужны конструкторы
  • Вам не нужно комментировать внутренние классы
  • RefreshScope имеют некоторые проблемы при использовании с @Configuration. См. эту проблему github

Измените свой класс следующим образом:

@ConfigurationProperties(prefix = "available-payment-channels-list")
@Configuration
public class AvailableChannelsConfiguration {

private String xyz;
private List<ChannelConfiguration> channelConfigurations;

// getters, setters

public static class ChannelConfiguration {
    private String name;
    private String companyBankAccount;

    // getters, setters
}

}

Ответ 3

У меня было много проблем с этим. Наконец я узнал, что это за заключительная сделка.

Обратившись к ответу @Gokhan Oner, если у вас есть свой класс обслуживания и POJO, представляющий ваш объект, ваш конфигурационный файл YAML приятный и скудный, если вы используете аннотацию @ConfigurationProperties, вам нужно явно получить объект для способный использовать его. Например:

@ConfigurationProperties(prefix = "available-payment-channels-list")
//@Configuration  <-  you don't specificly need this, instead you're doing something else
public class AvailableChannelsConfiguration {

    private String xyz;
    //initialize arraylist
    private List<ChannelConfiguration> channelConfigurations = new ArrayList<>();

    public AvailableChannelsConfiguration() {
        for(ChannelConfiguration current : this.getChannelConfigurations()) {
            System.out.println(current.getName()); //TADAAA
        }
    }

    public List<ChannelConfiguration> getChannelConfigurations() {
        return this.channelConfigurations;
    }

    public static class ChannelConfiguration {
        private String name;
        private String companyBankAccount;
    }

}

И вот вы здесь. Это просто, как черт, но мы должны знать, что мы должны назвать объект getter. Я ждал при инициализации, желая, чтобы объект строился со значением, но нет. Надеюсь, это поможет:)

Ответ 4

Я ссылался на эту статью и многие другие, и не нашел четкого краткого ответа на помощь. Я предлагаю свое открытие, получив некоторые ссылки из этого потока, в следующем:

Spring -Boot version: 1.3.5.RELEASE

Spring -Core version: 4.2.6.RELEASE

Управление зависимостями: Brixton.SR1

Ниже приведена соответствующая выдержка yaml:

tools:
  toolList:
    - 
      name: jira
      matchUrl: http://someJiraUrl
    - 
      name: bamboo
      matchUrl: http://someBambooUrl

Я создал инструмент Tools.class:

@Component
@ConfigurationProperties(prefix = "tools")
public class Tools{
    private List<Tool> toolList = new ArrayList<>();
    public Tools(){
      //empty ctor
    }

    public List<Tool> getToolList(){
        return toolList;
    }

    public void setToolList(List<Tool> tools){
       this.toolList = tools;
    }
}

Я создал Tool.class:

@Component
public class Tool{
    private String name;
    private String matchUrl;

    public Tool(){
      //empty ctor
    }

    public String getName(){
        return name;
    }

    public void setName(String name){
       this.name= name;
    }
    public String getMatchUrl(){
        return matchUrl;
    }

    public void setMatchUrl(String matchUrl){
       this.matchUrl= matchUrl;
    }

    @Override
    public String toString(){
        StringBuffer sb = new StringBuffer();
        String ls = System.lineSeparator();
        sb.append(ls);
        sb.append("name:  " + name);
        sb.append(ls);
        sb.append("matchUrl:  " + matchUrl);
        sb.append(ls);
    }
}

Я использовал эту комбинацию в другом классе через @Autowired

@Component
public class SomeOtherClass{

   private Logger logger = LoggerFactory.getLogger(SomeOtherClass.class);

   @Autowired
   private Tools tools;

   /* excluded non-related code */

   @PostConstruct
   private void init(){
       List<Tool>  toolList = tools.getToolList();
       if(toolList.size() > 0){
           for(Tool t: toolList){
               logger.info(t.toString());
           }
       }else{
           logger.info("*****-----     tool size is zero     -----*****");
       }  
   }

   /* excluded non-related code */

}

И в моих журналах было зарегистрировано имя и соответствующий URL-адрес. Это было разработано на другой машине, и поэтому мне пришлось перепечатать все вышеизложенное, поэтому, пожалуйста, простите меня заранее, если я нечаянно ошибся.

Я надеюсь, что этот комментарий консолидации полезен для многих, и я благодарю предыдущих участников этой темы!