Hank
Hank

Reputation: 3497

Spring Multiple Property Placeholder and SPEL order independent

I have two xml config files using property-placeholder. I'm having an issue where the order of the import statements for these two config files will effect SPEL in one of the config files.

config-a.xml

<context:property-placeholder
            location="classpath:dev/food.properties"
            ignore-unresolvable="true" />

<bean id="foodNames" class="java.util.HashMap">
    <constructor-arg>
        <map key-type="com.my.project.Food"
            value-type="java.lang.String">
            <entry key="#{T(com.my.project.Food).SUSHI}"
                value="${dynamodb.sushi:#{null}}" />
        </map>
    </constructor-arg>
</bean>

config-b.xml

<context:property-placeholder
            location="classpath:dev/animals.properties"
            ignore-unresolvable="true" />

If I import config-a.xml before config-b.xml, the value is properly set in the foodNames map. But if I set config-b.xml before config-a.xml, the value is null. A more visual example can be seen below.

spring-dispatcher-servlet.xml

// Value is properly set
<import resource="classpath:spring/config-a.xml" />
<import resource="classpath:spring/config-b.xml" />

// Value is null
<import resource="classpath:spring/config-b.xml" />
<import resource="classpath:spring/config-a.xml" />

What can I do to make it order independent?

Upvotes: 0

Views: 866

Answers (1)

M. Deinum
M. Deinum

Reputation: 124506

The easiest (and I suspect recommended approach) is to use java based configuration. In this configuration define a bean for the PropertySourcesPlaceholderConfigurer and use @PropertySource annotations to load your property files.

@Configuration
@PropertySource("classpath:dev/food.properties")
public class ConfigA {}

@Configuration
@PropertySource("classpath:dev/animals.properties")
public class ConfigB {}

@Configuration
@ComponentScan("your-packages-here")
public class RootConfig {
    @Bean
    public static PropertySourcesPlaceholderConfigurer PropertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }
}

Something like this. All configuration classes are loaded as well as the property files before a replacement is going to happen.

Upvotes: 1

Related Questions