Spring Boot - property could not be resolved in xml from application.properties

mangusbrother picture mangusbrother · Oct 16, 2014 · Viewed 22.3k times · Source

I have a spring boot application

My @Configuration class loads the xml Configuration using @ImportResource("path/to/xml"), which contains the following line

<property name="bla" value="${log.directory}/file.ext" />

Under src/main/resources I have the application.properties file with the following content:

log.directory=C:/path/I/Need

However when I run It fails to load the property as follows:

Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'log.directory' in string value "${log.directory}/file.ext"

Answer

Pedro Lopez picture Pedro Lopez · Oct 20, 2014

You can solve it adding context:property-placeholder to you xml. That way you will tell Spring to load your specific properties file.

However another more in line with Spring Boot solution is just using application.properties as the name for your properties file, having it in one of the expected locations, and use the @EnableAutoconfiguration annotation.

Spring Boot expects the application.properties in the following location in order of preference.

  1. A /config subdir of the current directory.
  2. The current directory
  3. A classpath /config package
  4. The classpath root

I have tried this and it works.

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>sample</groupId>
    <artifactId>sample</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>Sample</name>
    <description>Spring Boot sample</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.1.8.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
    </dependencies>

    <!-- Package as an executable jar -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

Sample.java

package sample;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;

@Configuration
@EnableAutoConfiguration
@ComponentScan
@ImportResource("classpath:beans.xml")
public class Sample implements CommandLineRunner {

    @Value("${sample}")
    private String sample;

    @Autowired
    SampleService service;

    public static void main(String[] args) {
        SpringApplication.run(Sample.class, args);
    }

    public void run(String... args) {
        System.out.println(service.greetings());
    }
}

SampleService.java

package sample;


public class SampleService {

    private String field;

    public String greetings() {
        return field;
    }

    public String getField() {
        return field;
    }

    public void setField(String field) {
        this.field = field;
    }
}

beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans
  xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:p="http://www.springframework.org/schema/p"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <bean class="sample.SampleService">
        <property name="field" value="${sample}-world"></property>
    </bean>
</beans>

application.properties

sample=hello

In the output you will get hello world if you run the program.

Make sure that you have enabled the autoconfiguration. If you did not, it will not work as expected. In order to do so, add the @EnableAutoconfiguration annotation as in the example.

Please note that you are using Spring Boot, so you are encouraged to avoid XML configuration. You can get the same result with no beans.xml at all. Although, if you still need it, you can mix XML with annotations.

I have uploaded both sample projects to GitHub, please check.

https://github.com/plopcas/example-spring-boot/tree/master/spring-boot-xml

https://github.com/plopcas/example-spring-boot/tree/master/spring-boot

Hope this helps.