2015-09-15 11 views
28

W mojej aplikacji Spring Boot mam plik konfiguracyjny application.yaml z następującą treścią. Chcę mieć to wstrzykiwany jako obiekt konfiguracji z listy konfiguracji kanałów:Lista mapowania w Yaml do listy obiektów w Spring Boot

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

I @Configuration obiekt Chcę być wypełnione listy obiektów 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 
     } 

    } 

ja to jak wstrzykiwanie normalna fasola z @Autowiowanym konstruktorem. Wartość xyz jest wypełniona prawidłowo, ale kiedy wiosna próbuje zanalizować yaml do listy obiektów Dostaję

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] 

żadnych wskazówek co tu jest nie tak?

+0

Mam dokładnie ten sam problem: próbowałem wielu rzeczy, ale dostałem pusty obiekt, albo ten sam błąd 'Nie można przekonwertować wartości typu ... String .... do MyObject ... brak pasujących edytorów lub znaleziona strategia konwersji ". Dziwne jest to, że nie zmieniłem niczego w Spring Boot, które mogłoby wpłynąć na parametry lub zachowanie SnakeYAML ... Właściwie, co do cholery? – Alex

+0

Prawie zapomniałem, używam Spring Boot 1.2.6 – Alex

Odpowiedz

9

Powód musi być gdzieś indziej. Używając tylko Spring Boot 1.2.2 z pudełka bez konfiguracji, to Just Works. Rzuć okiem na to repozytorium - czy możesz go złamać?

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

Czy jesteś pewien, że plik YAML wygląda dokładnie tak, jak wklejone? Bez dodatkowych białych znaków, znaków, znaków specjalnych, błędnego wcięcia czy czegoś w tym rodzaju? Czy jest możliwe, że masz inny plik w innej ścieżce wyszukiwania niż ten, którego się spodziewasz?

+0

Zrobiłem to samo i dla czystego projektu SpringBoot to działa. Okazało się, że nasze dostosowywanie ładowań właściwości dla różnych środowisk nie zachowywało się właściwie. –

11
  • Nie trzeba konstruktorów
  • nie trzeba do opisywania wewnętrzne klas
  • RefreshScope mieć pewne problemy podczas korzystania z @Configuration. Proszę zobaczyć this github issue

Zmień swoją klasę tak:

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

} 
+0

Same rzeczy, generalnie twój kod jest tylko uproszczeniem mojego kopalni zagnieżdżony wyjątek to java.lang.IllegalStateException: Nie można przekonwertować wartości typu [java.lang.String] do wymaganego typu [io.example.available_channels.AvailableChannelsConfiguration $ ChannelConfiguration] dla właściwości "channelConfigurations [0]": nie znaleziono zgodnych edytorów ani strategii konwersji] –

+0

Uruchomiłem kod i wyświetlono wszystkie przypisane wartości. Czy usunąłeś adnotację RefreshScope –

+0

Jaka jest twoja wersja wiosennego buta? –

4

Miałem wiele problemów z tym też. W końcu dowiedziałem się, jaka jest ostateczna umowa.

Odnosząc się do odpowiedzi @Gokhan Oner, gdy już masz klasę serwisową i POJO reprezentujące twój obiekt, plik konfiguracyjny YAML jest miły i szczupły, jeśli używasz adnotacji @ConfigurationProperties, musisz jawnie uzyskać obiekt dla być w stanie z niego korzystać. Na przykład:

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

} 

A teraz proszę. To proste jak diabli, ale musimy wiedzieć, że musimy nazwać obiektowym geterem. Czekałem na inicjalizację, żałuję, że obiekt nie został zbudowany z wartością, ale nie. Mam nadzieję, że to pomaga :)

3

Odwołałem się do tego artykułu i wielu innych i nie znalazłem jednoznacznej, zwięzłej odpowiedzi na pomoc. Podaję moje odkrycie, przybył z niektórych referencje od tego wątku, w następujący:

Wiosna-Boot wersji: Wersja 1.3.5.RELEASE

Wiosna-Core: 4.2.6.RELEASE

Zarządzanie zależnościami: Brixton.SR1

Poniżej opisano istotne yaml fragment:

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

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

utworzonego 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); 
    } 
} 

I stosowana to połączenie w innej klasie przez @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 */ 

} 

W moich dziennikach rejestrowano nazwę i pasujące adresy URL. Zostało to opracowane na innej maszynie i dlatego musiałem ponownie wpisać wszystkie powyższe, więc proszę o wybaczenie z góry, jeśli pomyliłem się przypadkowo.

Mam nadzieję, że ten komentarz do konsolidacji jest pomocny dla wielu osób i dziękuję poprzednim uczestnikom tego wątku!

+0

nie potrzebujesz adnotacji "@ Component'" dla klasy Tool – heroin