I’m working on a Spring webapp and I have a library I include as a jar file. That library uses Spring annotations, and it has its own context file which is referenced in my webapp’s contextConfigLocation context parameter. The library has its own properties file, loaded through <context:property-placeholder ... />, the values of which are used in the library’s code via the @Value annotation.
I was able to use the library in my webapp until I added a properties file to my webapp via the same mechanism (i.e. <context:property-placeholder... ). All of a sudden I started getting an exception stating “could not resolve placeholder”, the placeholder being the first one referenced in my library’s code.
I spent hours trying to puzzle this out, reading questions, docs, code and finally came across a bit of sample code that was doing what I was trying to do: set up a Spring-managed library that loaded properties from an external file. The snippet showing the loading of the property file held the solution to my problem, but there was no explanation as to why it worked. In the library’s application context I had to reference the property file like this:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="classpath:my/package/config/app-lib.properties" />
<property name="placeholderPrefix" value="$app-lib{" />
</bean>
I’m happy my code is working again but I’m not completely satisfied because I don’t understand what’s going on. This question is similar (I’d missed the significance of it while searching for an answer) but the answer doesn’t say why using a placeholderPrefix is necessary.
Can someone explain why my library wasn’t able to find its properties until I customized the prefix?
Normally, you can only have one PropertyPlaceholderConfigurer, and it is responsible for processing all property placeholders.
Since the library that you are using apparently already sets up a PropertyPlaceholderConfigurer, yours was clashing with the one from the library, which was set up to read the library’s property file, not your application’s.
By setting a different placeholderPrefix, you are allowing the two PropertyPlaceholderConfigurer instances to co-exist, with the library’s instance processing ‘normal’ property placeholders (ones with the default prefix of “${“, and your application’s instance processing the the custom placeholders with the prefix of “$app-lib{“.