Question

Sombody knows if this is a bug or an expected behaviour

If you have a component with

@Value("${foo}")
private String fooValue;

And this config:

<beans>
    <context:annotation-config />
    <context:component-scan base-package="org.mortar" />
    <aop:aspectj-autoproxy />
    <context:property-placeholder location="classpath:a.properties"/>
    <context:property-placeholder location="classpath:b.properties"/>
</bean>

You get an Exception:

java.lang.IllegalArgumentException: Could not resolve placeholder 'foo' in string value "${foo}"

If you use a singe context:property-placeholder it works just fine:

<beans>
    <context:annotation-config />
    <context:component-scan base-package="org.mortar" />
    <aop:aspectj-autoproxy />
    <context:property-placeholder location="classpath:a.properties, classpath:b.properties"/>
</bean>
Was it helpful?

Solution

Declaring

<context:property-placeholder location="classpath:a.properties"/>

registers a PropertySourcesPlaceholderConfigurer bean and a bean of an inner class of this called PlaceholderResolvingStringValueResolver. Each of these beans registers a PropertySource in the Spring Environment.

Spring, when it has to resolve a String placeholder ${} value then iterates through the registered PlaceholderResolvingStringValueResolver beans. It uses their resolveStringValue method to resolve the placeholder. If it cannot, it fails fast, even if another PlaceholderResolvingStringValueResolver could have resolved it.

The solution is to use a single <context:property-placeholder> where all the properties are registered in one PropertySourcesPlaceholderConfigurer.

Alternatively, you could declare them with the attribute ignore-unresolvable="true". In this case, if one can't resolve it, it won't throw any exceptions. Instead it will try the next one. However, you might find yourself with an unresolved property, so I don't recommend it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top