Spring Boot yaml configuration for a list of strings

Spring Boot

Spring Boot Problem Overview


I am trying to load an array of strings from application.yml file. This is the config:

ignore:
    filenames:
        - .DS_Store
        - .hg

This is the class:

@Value("${ignore.filenames}")
private List<String> igonoredFileNames = new ArrayList<>();

There are other configurations in the same class that loads just fine. There are no tabs in my YAML file. Still, I get the following exception:

Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'ignore.filenames' in string value "${ignore.filenames}"

Spring Boot Solutions


Solution 1 - Spring Boot

use comma separated values in application.yml

ignoreFilenames: .DS_Store, .hg

java code for access

@Value("${ignoreFilenames}")    
String[] ignoreFilenames

It is working ;)

Solution 2 - Spring Boot

My guess is, that the @Value can not cope with "complex" types. You can go with a prop class like this:

@Component
@ConfigurationProperties('ignore')
class IgnoreSettings {
    List<String> filenames
}

Please note: This code is Groovy - not Java - to keep the example short! See the comments for tips how to adopt.

See the complete example https://github.com/christoph-frick/so-springboot-yaml-string-list

Solution 3 - Spring Boot

From the spring boot docs https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html

YAML lists are represented as property keys with [index] dereferencers, for example this YAML:

my:
   servers:
       - dev.bar.com
       - foo.bar.com

Would be transformed into these properties:

my.servers[0]=dev.bar.com
my.servers[1]=foo.bar.com

To bind to properties like that using the Spring DataBinder utilities (which is what @ConfigurationProperties does) you need to have a property in the target bean of type java.util.List and you either need to provide a setter, or initialize it with a mutable value, e.g. this will bind to the properties above. Here is what the question's code would look like.

@ConfigurationProperties(prefix="ignore")
public class Filenames {

    private List<String> ignoredFilenames = new ArrayList<String>();

    public List<String> getFilenames() {
        return this.ignoredFilenames;
    }
}

Solution 4 - Spring Boot

In addition to Ahmet's answer you can add line breaks to the coma separated string using > symbol.

application.yml:

ignoreFilenames: >
  .DS_Store, 
  .hg

Java code:

@Value("${ignoreFilenames}")    
String[] ignoreFilenames;

Solution 5 - Spring Boot

Well, the only thing I can make it work is like so:

servers: >
    dev.example.com,
    another.example.com

@Value("${servers}")
private String[] array;

And dont forget the @Configuration above your class....

Without the "," separation, no such luck...

Works too (boot 1.5.8 versie)

servers: 
       dev.example.com,
       another.example.com

Solution 6 - Spring Boot

Ahmet's answer provides on how to assign the comma separated values to String array.

To use the above configuration in different classes you might need to create getters/setters for this.. But if you would like to load this configuration once and keep using this as a bean with Autowired annotation, here is the how I accomplished:

In ConfigProvider.java

@Bean (name = "ignoreFileNames")
@ConfigurationProperties ( prefix = "ignore.filenames" )
public List<String> ignoreFileNames(){
	return new ArrayList<String>();
}

In outside classes:

@Autowired
@Qualifier("ignoreFileNames")
private List<String> ignoreFileNames;

you can use the same list everywhere else by autowiring.

Solution 7 - Spring Boot

@Value("#{'${your.elements}'.split(',')}")  
private Set<String> stringSet;

yml file:

your:
 elements: element1, element2, element3

There is lot more you can play with spring spEL.

Solution 8 - Spring Boot

In my case this was a syntax issue in the .yml file. I had:

@Value("${spring.kafka.bootstrap-servers}")
public List<String> BOOTSTRAP_SERVERS_LIST;

and the list in my .yml file:

bootstrap-servers:
  - s1.company.com:9092
  - s2.company.com:9092
  - s3.company.com:9092

was not reading into the @Value-annotated field. When I changed the syntax in the .yml file to:

bootstrap-servers >
  s1.company.com:9092
  s2.company.com:9092
  s3.company.com:9092

it worked fine.

Solution 9 - Spring Boot

@Value("${your.elements}")    
private String[] elements;

yml file:

your:
 elements: element1, element2, element3

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBahadır YağanView Question on Stackoverflow
Solution 1 - Spring BootAhmet Vehbi OlgaçView Answer on Stackoverflow
Solution 2 - Spring BootcfrickView Answer on Stackoverflow
Solution 3 - Spring BootdskowView Answer on Stackoverflow
Solution 4 - Spring BootSasha ShpotaView Answer on Stackoverflow
Solution 5 - Spring BootRoland RoosView Answer on Stackoverflow
Solution 6 - Spring BootDeepakView Answer on Stackoverflow
Solution 7 - Spring BootVivek SwansiView Answer on Stackoverflow
Solution 8 - Spring BootMatt CampbellView Answer on Stackoverflow
Solution 9 - Spring Bootsashanet burykView Answer on Stackoverflow