41
votes

I need to load a property from a .yml file, which contains the path to a folder where the application can read files from.

I'm using the following code to inject the property:

@Value("${files.upload.baseDir}")
private String pathToFileFolder;

The .yml file for development is located under src/main/resources/config/application.yml, im running the application with the following command in production, to override the development settings:

java -jar app.jar --spring.config.location=/path/to/application-production.yml

The Spring Boot documentation says:

SpringApplication will load properties from application.properties files in the following locations and add them to the Spring Environment:

  1. A /config subdirectory of the current directory.

  2. The current directory

  3. A classpath /config package

  4. The classpath root

As well as:

You can also use YAML ('.yml') files as an alternative to '.properties'.

The .yml file contains:

{...}
files:
      upload:
        baseDir: /Users/Thomas/Code/IdeaProjects/project1/files
{...}

And my Application class is annotated with:

@SpringBootApplication
@EnableCaching

When I run the application, i get an exception:

Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'files.upload.baseDir' in string value "${files.upload.baseDir}"

Do I have to use the YamlPropertySourceLoader class or add a special annotation to enable the support for .yml in Spring Boot?

Edit: The .yml file contains some other properties, which get successfully loaded by Spring Boot like dataSource.XXXor hibernate.XXX.

6
Run your program with --debugMarged
Have you tried with the same .yaml file you use in development? Just take it outside the project and try to execute it with the command. That way you'll discard any typo in the file.Xtreme Biker
The property isn' there... There are too many spaces before upload:.M. Deinum
Please check my comment about how to read YAML file in Spring and include it in JUnit and TestNG test here: stackoverflow.com/a/37270778/3634283ayurchuk

6 Answers

15
votes

For example: application.yml

key:
 name: description here

Your Class:

@Value("${key.name}")
private String abc;
10
votes

M. Deinum is right, the setup i've provided is working - the yml file was indented wrong, so the property couldn't be found.

3
votes

I found the above wasn't working for me, because I tried to access the variable in a constructor. But at construction, the value is not injected yet. Eventually I got it to work using this workaround: https://mrhaki.blogspot.com/2015/04/spring-sweets-using-value-for.html

Maybe this is helpful to others.

2
votes

For me a duplicate key in the property file caused this...

I used same key unknowingly in large yml file.

key:   
 key1: value
 key2: value

key:  
 key3: value
1
votes

In yml properties file :

xxxx:
     page:
        rowSize: 1000

Create your Yaml properties config class :

@Configuration
@EnableConfigurationProperties
@ConfigurationProperties(prefix = "xxxx")
public class YmlPropertiesConfig {

    private Page page;

    public Page getPage() {
        return page;
    }
    public void setPage(Page page) {
        this.page = page;
    }

    public class Page {
        private Integer rowSize;

        public Integer getRowSize() {
            return rowSize;
        }

        public void setRowSize(Integer rowSize) {
            this.rowSize = rowSize;
        }
    }    
}

Finally get it and use it :

public class XXXXController {

     @Autowired
     private YmlPropertiesConfig ymlProperties;

     public String getIt(){

        Integer pageRowSize = ymlProperties.getPage().getRowSize();
     }
}
0
votes

I've got that issue Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder cause I've set test spring boot profile in properties.yaml. Spring can't find properties for test profile when run app with no profile.

So remove spring boot profile from properties or yaml or run app with enabled profile.

Configuration file example is below:

@Configuration
public class AppConfig {
  @Value("${prop.foo}")
  private String foo;
  @Value("${prop.bar}")
  private String bar;

  @Bean
  BeanExample beanExample() {
    return new BeanExample(foo, bar);
  }
}