Working on a legacy Spring based application (Spring 4.3), I have a strange behavior: environment variables are not resolved by Spring.
For example I have this environment variable: HOST_SERVICE_BASE_URL
, when I refer to it in the application with ${host.service.base.url}
the property is not resolved and the application fails during start up.
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'host.service.base.url' in value "${host.service.base.url}
I defined these beans for property resolution:
@Bean
public PropertiesFactoryBean applicationProperties( ResourceLoader resourceLoader ) {
PropertiesFactoryBean propertiesFactory = new PropertiesFactoryBean();
propertiesFactory.setLocations( resourceLoader.getResource( "/WEB-INF/config/application.properties" ),
resourceLoader.getResource( "/WEB-INF/config/application-dev.properties" ) );
return propertiesFactory;
}
And
<bean id="dataConfigPropertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreResourceNotFound" value="true"/>
<property name="searchSystemEnvironment" value="true"/>
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
<property name="properties" ref="applicationProperties"/>
</bean>
You are using the (now deprecated) PropertyPlaceholderConfigurer
while that can consult the system environment it lacks the feature of mapping those properties to values. I.e HOST_SERVICE_BASE_URL
isn't mapped as host.service.base.url
.
That support is only available in the SystemEnvironmentPropertySource
which is automatically registered and consulted when using the PropertySourcesPlaceholderConfigurer
(recommended as of Spring 5.2, but available since 3.1).
<bean id="dataConfigPropertyConfigurer"
class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="ignoreResourceNotFound" value="true"/>
<property name="properties" ref="applicationProperties"/>
</bean>
Or in Java to replace the applicationProperties
bean and XML portion.
@Bean
public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
configurer.setLocations({"/WEB-INF/config/application.properties", /WEB-INF/config/application-dev.properties"});
configurer.setIgnoreResourceNotFound(true);
return configurer;
}
Or if you really stick with XML use the <context:property-placeholder />
tag, which automatically does this.
<context:property-placeholder properties="applicationProperties" ignore-resource-not-found="true" />
or
<context:property-placeholder locations="/WEB-INF/config/application.properties,/WEB-INF/config/application-dev.properties" ignore-resource-not-found="true" />