configurationproperties java spring spring-boot yaml

java - @configurationproperties



Lista de mapeo en Yaml a la lista de objetos en Spring Boot (5)

Hice referencia a este artículo y a muchos otros y no encontré una respuesta clara y concisa para ayudar. Estoy ofreciendo mi descubrimiento, llegado con algunas referencias de este hilo, en lo siguiente:

Versión Spring-Boot: 1.3.5.

Versión Spring-Core: 4.2.6.

Gestión de dependencias: Brixton.SR1

El siguiente es el extracto pertinente de yaml:

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

Creé un 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; } }

Creé un 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); } }

Usé esta combinación en otra clase a través de @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 */ }

Y en mis registros se registraron el nombre y las URL correspondientes. Esto se desarrolló en otra máquina y, por lo tanto, tuve que volver a escribir todo lo anterior, así que, por favor, perdóname de antemano si accidentalmente escribí mal.

¡Espero que este comentario de consolidación sea útil para muchos y agradezco a los contribuyentes anteriores de este hilo!

En mi aplicación Spring Boot tengo el archivo de configuración application.yaml con el siguiente contenido. Quiero que se inyecte como un objeto de configuración con una lista de configuraciones de canales:

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

Y el objeto @Configuration quiero que se complete con la lista de objetos de 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 } }

Estoy inyectando esto como un bean normal con el constructor @Autowired. El valor de xyz se rellena correctamente, pero cuando Spring intenta analizar yaml en la lista de objetos, obtengo

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]

¿Alguna pista de lo que está mal aquí?


La razón debe estar en otro lugar. Usando solo Spring Boot 1.2.2 fuera de la caja sin configuración, simplemente funciona . Echa un vistazo a este repositorio: ¿puedes hacer que se rompa?

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

¿Estás seguro de que el archivo YAML se ve exactamente como lo pegaste? ¿Sin espacios en blanco adicionales, caracteres, caracteres especiales, indentación o algo por el estilo? ¿Es posible que tenga otro archivo en otra parte de la ruta de búsqueda que se utiliza en lugar del que está esperando?


Tuve muchos problemas con este también. Finalmente descubrí cuál es el trato final.

Refiriéndose a la respuesta de @Gokhan Oner, una vez que tiene su clase de Servicio y el POJO que representa su objeto, su archivo de configuración YAML es agradable y delgado, si usa la anotación @ConfigurationProperties, debe obtener explícitamente el objeto para poder usar eso. Me gusta :

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

Y luego aquí tienes. Es simple como el infierno, pero tenemos que saber que debemos llamar al objeto getter. Estaba esperando la inicialización, deseando que el objeto se construyera con el valor pero no. Espero eso ayude :)


para mí, la solución fue agregar la clase inyectada como clase interna en la anotada con @ConfigurationProperites, porque creo que necesita @Component para inyectar propiedades.


  • No necesitas constructores
  • No necesitas anotar clases internas
  • RefreshScope tiene algunos problemas al usar con @Configuration . Por favor vea este problema de github

Cambia tu clase así:

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