Loading multiple YAML files (using @ConfigurationProperties?)

Alex picture Alex · Dec 3, 2015 · Viewed 16.7k times · Source

Using Spring Boot 1.3.0.RELEASE

I have a couple of yaml files that describe several instances of a program. I now want to parse all those files into a List<Program> (Map, whatever), so I can later on search for the most appropriate instance for a given criteria in all the programs.

I like the approach with @ConfigurationProperties a lot, and it works good enough for a single yaml-file, but I haven't found a way yet to read all files in a directory using that method.

Current approach working for a single file:

programs/program1.yml

name: Program 1
minDays: 4
maxDays: 6

can be read by

@Configuration
@ConfigurationProperties(locations = "classpath:programs/program1.yml", ignoreUnknownFields = false)
public class ProgramProperties {

private Program test; //Program is a POJO with all the fields in the yml.
//getters+setters

I tried changing the locations to an Array listing all of my files locations = {"classpath:programs/program1.yml", "classpath:programs/program2.yml"} as well as using locations = "classpath:programs/*.yml", but that still only loads the first file (array-approach) or nothing at all (wildcard-approach).

So, my question is, what is the best way in Spring Boot to load a bunch of yaml files in a classpath-directory and parse them into a (List of) POJO, so they can be autowired in a Controller? Do I need to use Snakeyaml directly, or is there an integrated mechanism that I just haven't found yet?

EDIT: A working approach is doing it manually:

    private static final Yaml yaml = new Yaml(new Constructor(Program.class));
private static final ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();

try {
        for (Resource resource : resolver.getResources("/programs/*.yml")) {

            Object data = yaml.load(resource.getInputStream());

            programList.add((Program) data);
        }
    }
    catch (IOException ioe) {
        logger.error("failed to load resource", ioe);
    }

Answer

Mohit picture Mohit · Dec 3, 2015

In Spring, it is possible to load multiple configuration properties files using PropertySource annotation, but not YAML files. See section 26.6.4 in link below:

https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-typesafe-configuration-properties

However, from your problem, it seems that you can configure all your programs in single YAML and then get all list of programs in a single list.

Sample YAML (all.yaml)

programs:
  - name: A
    min: 1
    max: 2
  - name: B
    min: 3
    max: 4

Config.java

@Configuration
@ConfigurationProperties(locations={"classpath:all.yaml"})
public class Config{

    private List<Program> programs;

    public void setPrograms(List<Program> programs) {
        this.programs = programs;
    }

    public List<Program> getPrograms() {
        return programs;
    }
}