45

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.

Community
  • 1
  • 1
Thomas Schmidt
  • 1,248
  • 2
  • 12
  • 37
  • Run your program with --debug – Marged Jan 01 '16 at 13:56
  • 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. – Aritz Jan 01 '16 at 21:41
  • 12
    The property isn' there... There are too many spaces before `upload:`. – M. Deinum Jan 04 '16 at 09:16
  • Please check my comment about how to read YAML file in Spring and include it in JUnit and TestNG test here: http://stackoverflow.com/a/37270778/3634283 – ayurchuk May 17 '16 at 08:35

8 Answers8

20

For example: application.yml

key:
 name: description here

Your Class:

@Value("${key.name}")
private String abc;
Nick Borges
  • 477
  • 5
  • 3
  • 11
    I am trying within a @Controller and that is not working at all.... – Dimitri Kopriwa Apr 02 '20 at 09:15
  • I also had a problem where it did not read the value. However, I realized I was because I was initiating my service class by using new (was doing some quick testing) For spring to read the values, the service or object has to be initiated using @AutoWired. When I did this change, the mentioned solution worked perfectly! – Emir Husic Nov 06 '22 at 11:26
14

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

Thomas Schmidt
  • 1,248
  • 2
  • 12
  • 37
  • This is very true. For my case , I had to indent my configuration so as it is inside the Spring heading. The Spring docs did not mention this! – Kevin Kiwango Sep 08 '21 at 07:47
  • 4
    Can you please provide comparison between working solution and "wrong" solution. It's not clear, what should I do to make `@Value` work with `.yml` props. Thanks! – RomanMitasov Dec 06 '21 at 14:00
7

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.

Kjeld
  • 444
  • 4
  • 14
2

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
SatyaRajC
  • 51
  • 7
2

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();
     }
}
harun ugur
  • 1,718
  • 18
  • 18
0

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);
  }
}
Yuriy K
  • 111
  • 1
  • 5
0

For those who have problems with a @RestController, I do it as follows:

@Autowired
@Value("${google.recaptcha}") 
private String keyRecaptcha;
0

My properties file was mistakenly named applcation.properties as it was auto-generated by the Spring initializer. But I added the properties there in the .yml format and they were not retrieved with the same error.

When I renamed the file to application.yml, it started working.

havryliuk
  • 136
  • 1
  • 11