0

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>
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
akuma8
  • 4,160
  • 5
  • 46
  • 82
  • Environment variables will never the converted to system properties. Do you really have an environment variable OR do you have a System Property (passed with `-D`). Also why the mix of XML and Java Config and do you by anychange have multiple `PropertyPlaceholderConfigurer` instances AND are you loading multiple configs? – M. Deinum Aug 13 '20 at 13:51
  • @M.Deinum I have environnement variables not system properties. The mix with xml is because it's a legacy application and I don't want to migrate all configurations – akuma8 Aug 13 '20 at 13:56
  • Ah already see your issue. You should be using a `PropertySourcesPlaceholderConfigurer` not a `PropertyPlaceholderConfigurer` and loading the properties, unless you need them, should be done using the same class. – M. Deinum Aug 13 '20 at 13:59
  • And yes there are multiple configs loaded – akuma8 Aug 13 '20 at 14:00

1 Answers1

2

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" />
M. Deinum
  • 115,695
  • 22
  • 220
  • 224