Search code examples
javaxmlspringspring-bootproperties-file

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


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"


Solution

  • 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.