web-dev-qa-db-ja.com

YamlのリストをSpring Bootのオブジェクトのリストにマッピングする

私のSpring Bootアプリには、次のコンテンツを含む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
        }

    }

これを、@ Autowiredコンストラクターを使用して通常のBeanとして注入しています。 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]

ここで何が間違っているのか?

43
Tomasz Dziurko

理由はどこかにあるに違いありません。設定なしですぐに使えるSpring Boot 1.2.2のみを使用すると、Just Worksになります。このレポをご覧ください-それを破ることができますか?

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

YAMLファイルは、貼り付けたとおりに見えますか?余分な空白、文字、特殊文字、インデントの間違いなどはありませんか?あなたが期待しているものの代わりに使用されている検索パスの他の場所に別のファイルがある可能性はありますか?

13
Konrad Garus
  • コンストラクタは必要ありません
  • 内部クラスに注釈を付ける必要はありません
  • 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
}

}
13
Gokhan Oner

私はこの記事や他の多くの記事を参照しましたが、明確な簡潔な回答は見つかりませんでした。私は、このスレッドからの参照を次のようにして得た発見を提供しています。

スプリングブートバージョン:1.3.5.RELEASE

Spring-Coreバージョン: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が記録されました。これは別のマシンで開発されたため、上記のすべてを再入力する必要があったので、誤ってタイプミスした場合は事前にご容赦ください。

この統合コメントが多くの人に役立つことを願っています。このスレッドへの以前の貢献者に感謝します!

9
JavaJd

私もこれに関して多くの問題を抱えていました。私は最終的に何が最終的な取引であるかを見つけました。

@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;
    }

}

そして、ここに行きます。地獄のように単純ですが、オブジェクトゲッターを呼び出す必要があることを知っておく必要があります。私は初期化を待っていました。オブジェクトが値で構築されていて、そうではないことを望んでいました。それが役に立てば幸い :)

6
Alex

私にとって修正は、@ ConfigurationProperitesアノテーションが付けられたクラスの内部クラスとして、挿入されたクラスを追加することでした。プロパティを挿入するには@Componentが必要だからです。

0