PropertyPlaceholderConfigurer and environment variables in .properties files

48,378

Solution 1

I'd probably change the solution completely: inject the system property directly, as opposed to injecting the property which refers to a system property

E.g.

@Value("#{ systemProperties['JAVA_MY_ENV'] }") 
private String myVar;

or

<property name ="myVar" value="#{systemProperties['JAVA_MY_ENV']}"/>

I use a property placeholder configurer like this

<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <property name="locations">
    <list>
        <value>classpath:someprops.properties</value>
    </list>
  </property>
  <property name="ignoreResourceNotFound" value="true" />
  <property name="searchSystemEnvironment" value="true" />
  <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />

You must also remember to pass the parameter into the program using

 -DJAVA_MY_ENV=xyz

This way when you run the production version you can pass one thing and when you are running tests another.

Also what I often what I do is something like this:

  <property name="locations">
    <list>
      <value>classpath:someprops.properties</value>
      <value>classpath:someprops-{environment}.properties</value>
    </list>
  </property>

where environment is prod/stage/test/int/ci/local (1 per environment - you may only have 2 or 3 for now). You can pass the environment variable to the program. Any properties which should be the same regardless of if its production/running on your local pc/tests would be in the someprops.properties property file. Any ones specific to the environment/way its being run as will go in the more specific file (you should put it in the someprops.properties file as well as a default unless overridden mechanism)

E.g. in classpath:someprops.properties

url=www.mysite.com

in classpath:someprops-local.properties

url=localhost

By using this basic idea you can separate tests and the program's normal running properties in a clean manner.

Solution 2

Using:

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

Change your:

property.name=${env.SYSTEM_PROPERTY}

To:

property.name=${SYSTEM_PROPERTY}

I'm using Spring 3.0.4.RELEASE, but I have no idea when this was introduced.

Share:
48,378
Dmitriy Sukharev
Author by

Dmitriy Sukharev

Updated on July 09, 2022

Comments

  • Dmitriy Sukharev
    Dmitriy Sukharev almost 2 years

    I have a Spring application-context.xml with PropertyPlaceholderConfigurer to get properties' values from .properties file. Main and test source folders have separate .properties file. The issue is that I need to use environment variables in .properties file. But when I do it in the following way:

    property.name=${env.SYSTEM_PROPERTY}
    

    I'm getting the following error:

    org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'beanName' defined in class path resource [com/example/applicationContext.xml]: Could not resolve placeholder 'env.SYSTEM_PROPERTY'
    

    while placeholder configurer defined as

    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:com/example/application.properties"/>
    </bean>
    

    Any ideas how-to make property.name be interpreted as environment variable (and not as placeholder)?

    Best regards, Dmitriy.

  • Dmitriy Sukharev
    Dmitriy Sukharev about 12 years
    Thank you very much. I've resolved problem using helper class that looks for VM property, then environment variable and then uses default value. Right now it's more flexible way for me. But still thanks, I'll try your way next time I'll do this.
  • Federico
    Federico almost 11 years
    This is quite good. However one problem is that forgetting to define a runtime variable produces tricky runtime errors, like config_xxx file not found and the likes. To improve on that situation I register a bean that implements special spring interfaces like this: class EnvironmentReporter implements PriorityOrdered, BeanFactoryPostProcessor, EnvironmentAware {...} environment.getProperty allows me to check for the expected properties and fail cleanly before any other bean gets created.
  • Michael Böckling
    Michael Böckling almost 10 years
    strange - using spring 3.0.4, this doesn't seem to work