javaspringenvironment-variablesproperty-placeholder

How to use Spring's `PropertySourcesPlaceholderConfigurer` to read environment variable NOT system property


The Spring 3.1 PropertySourcesPlaceholderConfigurer javadoc says:

This class is designed as a general replacement for PropertyPlaceholderConfigurer in Spring 3.1 applications.

But I don't see an obvious way to replicate the functionality of PropertyPlaceholderConfigurer's searchSystemEnvironment property, which makes the configurer look for an environment variable when no system property matching the placeholder name can be found.

Note that I've seen a lot of questions on SO asking about "environment variables" and PropertySourcesPlaceholderConfigurer but every one I've seen is actually asking about system properties, not environment variables.

How can I tell PropertySourcesPlaceholderConfigurer to fall back to supplying placeholder values using environment variables?


Solution

  • Firs thing to note is this snippet from the Javadoc

    Any local properties (e.g. those added via PropertiesLoaderSupport.setProperties(java.util.Properties), PropertiesLoaderSupport.setLocations(org.springframework.core.io.Resource...) et al.) are added as a PropertySource. Search precedence of local properties is based on the value of the localOverride property, which is by default false meaning that local properties are to be searched last, after all environment property sources.

    In other words, the PropertySourcesPlaceholderConfigurer has its own local property sources, which it searches, by default, after the property sources registered directly in the environment, ie. an instance of type ConfigurableEnvironment.

    The Javadoc of ConfigurableEnvironment, in getSystemPropeties() and getSystemEnvironment(), goes on to say that

    Return the value of System.getProperties() if allowed by the current SecurityManager, otherwise return a map implementation that will attempt to access individual keys using calls to System.getProperty(String).

    Note that most Environment implementations will include this system properties map as a default PropertySource to be searched.

    [...]

    Return the value of System.getenv() if allowed by the current SecurityManager, otherwise return a map implementation that will attempt to access individual keys using calls to System.getenv(String)

    Note that most Environment implementations will include this system environment map as a default PropertySource to be searched.

    These Environment implementations are StandardEnvironment, which is the default Spring's ApplicationContext classes use.

    This class Javadoc states

    In addition to the usual functions of a ConfigurableEnvironment such as property resolution and profile-related operations, this implementation configures two default property sources, to be searched in the following order:

    • system properties
    • system environment variables

    That is, if the key "xyz" is present both in the JVM system properties as well as in the set of environment variables for the current process, the value of key "xyz" from system properties will return from a call to environment.getProperty("xyz"). This ordering is chosen by default because system properties are per-JVM, while environment variables may be the same across many JVMs on a given system. Giving system properties precedence allows for overriding of environment variables on a per-JVM basis.

    These property sources are mutable and re-orderable. But, to answer your question, the behavior you're requesting is already provided by default.