Yurii Vasilchuk
Yurii Vasilchuk

Reputation: 93

Configure Spring 4 PropertySourcesPlaceholderConfigurer with custom ClassPathResource

How to configure PropertySourcesPlaceholderConfigurer with custom .properties files for different environments (production, dev, staging)? on deploy spring throws "Could not resolve placeholder 'property.placeholder' in string value "classpath:${property.placeholder}" "

here is my pom.xml

<profiles>
    <profile>
        <id>dev</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
          <property.placeholder>_developer.properties</property.placeholder>
        </properties>
    </profile>
    <profile>
        <id>staging</id>
        <activation>
            <activeByDefault>false</activeByDefault>
        </activation>
        <properties>
            <property.placeholder>_staging.properties</property.placeholder>
        </properties>
    </profile>
    <profile>
        <id>production</id>
        <activation>
            <activeByDefault>false</activeByDefault>
        </activation>
        <properties>
            <property.placeholder>_production.properties</property.placeholder>
        </properties>
    </profile>
</profiles>

here is PropertySourcesPlaceholderConfigurer configuration

static @Bean
public PropertySourcesPlaceholderConfigurer myPropertySourcesPlaceholderConfigurer() {
    PropertySourcesPlaceholderConfigurer p = new PropertySourcesPlaceholderConfigurer();
    org.springframework.core.io.Resource[] resourceLocations = new org.springframework.core.io.Resource[] {
            new ClassPathResource("${property.placeholder}")
    };
    p.setLocations(resourceLocations);
    return p;
}

it works in xml spring configuration but didn't work if I use java config. Have any idea how make it works?

Upvotes: 3

Views: 2052

Answers (2)

Yurii Vasilchuk
Yurii Vasilchuk

Reputation: 93

I found another way to do what i want:

At first I add this plugin to builds section in my pom.xml:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>properties-maven-plugin</artifactId>
    <version>1.0-alpha-2</version>
    <executions>
        <execution>
            <id>1</id>
            <phase>initialize</phase>
            <goals>
                <goal>read-project-properties</goal>
            </goals>
            <configuration>
                <files>
                    <file>src/main/resources/${property.placeholder}</file>
                </files>
            </configuration>
        </execution>
        <execution>
            <id>2</id>
            <phase>generate-resources</phase>
            <goals>
                <goal>write-project-properties</goal>
            </goals>
            <configuration>
                <outputFile>
                    ${project.build.outputDirectory}/application.properties
                </outputFile>
            </configuration>
        </execution>
    </executions>
</plugin>

At second I modify PropertySourcesPlaceholder configuration in my spring config file:

static @Bean
public PropertySourcesPlaceholderConfigurer myPropertySourcesPlaceholderConfigurer() {
    PropertySourcesPlaceholderConfigurer p 
        = new PropertySourcesPlaceholderConfigurer();
    org.springframework.core.io.Resource[] resourceLocations 
        = new org.springframework.core.io.Resource[] {
            new ClassPathResource("application.properties")
    };
    p.setLocations(resourceLocations);
    return p;
}

And also I add this annotation to my spring config class:

@PropertySource("classpath:application.properties")

So now I write env-dependent properties to different properties files (like "_developer.properties" or "_staging.properties") and when I build project with maven it has been copied to "application.properties", which I use in PropertySourcesPlaceholder configuration

Upvotes: 1

Braj
Braj

Reputation: 46851

Use System.getProperty() to get the environment variable.

Sample code:

Environment env = new Environment(new ClassResourceLocator(ClassUtils.getDefaultClassLoader()), System.getProperty("env"));

Create PropertySourcesPlaceholderConfigurer Bean:

@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer()
{
    PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
    propertySourcesPlaceholderConfigurer.setPropertySources(new MyPropertySources());
    return propertySourcesPlaceholderConfigurer;
}

MyPropertySources.java

public class MyPropertySources implements PropertySources{
    private List<PropertySource<?>> sources = new ArrayList<>();

    public EnvironmentPropertySources()
    {
        Environment env = new Environment(new ClassResourceLocator(ClassUtils.getDefaultClassLoader()), System.getProperty("env"));
        PropertySource<?> source = ...; 
        // create class that extends PropertySource<String> and get property values from Environment
        sources.add(source);
    }

    @Override
    public Iterator<PropertySource<?>> iterator() {
        return sources.iterator();
    }

    @Override
    public boolean contains(String name) {
        return true;
    }

    @Override
    public PropertySource<?> get(String name) {
        return sources.get(0);
    }
}

Upvotes: 0

Related Questions