Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Boot Property Yml/Properties with List structure

I have looked all over stackoverflow and the net for a solution for this. No solution I have seen works because maybe none of the posts exactly fit my use case which contain a lists inside the file and also an object struture.

Here is a sample as a yaml

teddy.list:
    -
      name: Red
      price: Five
    -
      name: Blue
      price: One
    -
      name: Yellow
      price: Two
    -
      name: Green
      price: Three

Here is the same sample as a property file

teddy.list[0].name=Red
teddy.list[0].price=Five
teddy.list[1].name=Blue
teddy.list[1].price=One
teddy.list[2].name=Yellow
teddy.list[2].price=Two
teddy.list[3].name=Green
teddy.list[3].price=Three

I want to be able to supply a teddy.yml or teddy.properties file to my application for configuration.

Here is my class for this:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;

@Configuration
@PropertySource(name = "props", value = "classpath:teddy.yml", ignoreResourceNotFound = false)
@ConfigurationProperties(prefix = "teddy")
public class TeddyBearConfig {

    @Autowired
    Environment env;

    @Value("${teddy.list}")
    private TeddyBear[] teddyBears;

    public TeddyBear[] getTeddyBears() {
        return teddyBears;
    }

    public void setTeddyBears(TeddyBear[] teddyBears) {
        this.teddyBears = teddyBears;
    }

    public static class TeddyBear {
        private String name;
        private String price;

        public TeddyBear() {

        }

        public TeddyBear(String name, String price) {
            this.name = name;
            this.price = price;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getPrice() {
            return price;
        }

        public void setPrice(String price) {
            this.price = price;
        }
    }
}

I've tried this setup, using the environment to try and access the properties, removing the prefix, declaring a bean of "PropertySourcesPlaceholderConfigurer".

With the current code, spring throws a IllegalStateException because it cannot convert java.lang.string to my TeddyBear class.

like image 847
GSUgambit Avatar asked Mar 13 '18 05:03

GSUgambit


People also ask

How do you represent a list in YAML?

Each element in the list is represented in YAML as a new line with the same indentation, starting with - followed by a space.

Can we use both YAML and properties in Spring boot?

As well as Java properties files, we can also use YAML-based configuration files in our Spring Boot application. YAML is a convenient format for specifying hierarchical configuration data.


1 Answers

This should work.

@Configuration
@PropertySource(name = "props", value = "classpath:teddy.properties", ignoreResourceNotFound = false)
@ConfigurationProperties(prefix = "teddy")
public class TeddyBearConfig {

  private List<TeddyBear> list;

  public List<TeddyBear> getList() {
    return list;
  }

  public void setList(List<TeddyBear> list) {
    this.list = list;
  }

  public static class TeddyBear {
    private String name;
    private String price;

    public TeddyBear() {

    }

    public TeddyBear(String name, String price) {
      this.name = name;
      this.price = price;
    }

    public String getName() {
      return name;
    }

    public void setName(String name) {
      this.name = name;
    }

    public String getPrice() {
      return price;
    }

    public void setPrice(String price) {
      this.price = price;
    }
  }
}

Update :

Above code works for the properties file you have given above.
If you wish to use yml file, you can do so. but there are a few points.
1. You yml structure isn't correct, it should be like this

teddy:
  list:
    -
      name: Red
      price: Five
    -
      name: Blue
      price: One
    -
      name: Yellow
      price: Two
    -
      name: Green
      price: Three

2. After fixing your yml structure, (and also file name in your TeddyBearConfig), you will see that springboot doesn't complaint during startup, but list variable in TeddBearConfig will be null. This is a bug in the way springboot handles yml files through @PropertySource.

3.If you move this yml content to application.yml and remove @PropertySource line in your config file, you would see that everything works perfectly fine.

like image 105
pvpkiran Avatar answered Oct 20 '22 05:10

pvpkiran