Stage aware spring contexts part II

As we have seen in the previous post with the @Environment annotation or the EnvironmentAwareSingletonFactoryBean, you can by using them choose between different implementation of Spring beans at runtime. But sometimes it is not the implementation you would like to switch between but the internal configuration of a particular class.

To support this, we have the EnvironmentAwareProperties class. It is a class in where you can register multiple property files used for looking up environment spesific values for a given property key using the environment as a prefix to separate values.

Property file layout

Each property file may have several entries for one key each prefixed by the environment it should apply. If no value found for the environment we are running in, it falls back on the key with no prefix. As shown in the following example

#
# myApp properties
#
myKey=default value
development.myKey=development value
test.myKey=test value
production.myKey=production value
custom.myKey=custom value

You are also allowed to use other property keys in the values, and it will be resolved and replaced with the value of the corresponding key as shown here :

#
# myApp properties
#
baseUrl=http://localhost
development.baseUrl=http://dev.arktekk.no
test.baseUrl=http://test.arktekk.no
production.baseUrl=http://arktekk.no

customerServiceEndpoint=${baseUrl}/services/customerService
orderServiceEndpoint=${baseUrl}/services/mockCustomerService

Configuring and using environment aware properties in Java


EnvironmentAwareProperties properties
  = new EnvironmentAwareProperties("myProperties.properties");
String myValue = properties.getProperty("myKey");

There are also constructors taking a list of property files, or you may use the registerPropertiesmethod to register more files. The EnvironmentAwareProperties class uses Spring resource loader to load the property files so you can use all the Spring supported urls, as e.g. classpath:myProperties.properties.

Use in Spring beans

In my opinion I do like spring beans that tries to configure them selves as much as possible. I think there are way to much use of Spring configuration files to configure ordinary properties like database url’s, service end points and so on. So what I would prefer is that we configure a EnvironmentAwareProperties bean in Spring, and then use the Spring autowiring support to get it injected unto other spring beans, and then use the InitializingBean inteface or the new support for the @PostConstruct annotation In this way we only need to configure our spring beans, in the case that the default values does not work in our application. This is best explained in the 2 part example below.

Configuring the EnvironmentAwareProperties bean

First we need to configure our properties in Spring by adding this xml snippet

<bean id="properties"
     class="no.arktekk.stagedspring.properties.EnvironmentAwareProperties">
  <property name="propertyFiles">
    <list>
      <value>no/arktekk/stagedspring/properties/test1.properties</value>
    </list>
  </property>
</bean>

Using in beans

Then it is time to get it injected, and utilized in a spring bean

public class SpringBean {
  @Autowired private EnvironmentAwareProperties properties;

    @PostConstruct
    public void initProperties() throws Exception {
      band = properties.getProperty("aCoolBand", "Mothers of invention");
    }

Note by using afterPropertiesSet or @PostConstruct this will override any configuration done in Spring configuration files, and the only way to change the values is by using the property files

Overriding properties

EnvironmentAwareProperties uses an ArrayList internally and, in the case of multiple files are registered, you are allowed to use a key in several files. When the EnvironmentAwareProperties class encounters several keys that match, it will always use the key registered last in the class. You may also register a file that does not yet exists, and it will be picked up if it is there at startup

Configuring Spring beans with placeholders

In addition, those of you familiar with Spring probably know the PropertyPlaceHolderConfigurer that Spring ships with. To be able to use this kind of configuration and use stages this project provide a EnvironmentAwarePropertyPlaceHolderConfigurer class that are able to use the EnvironmentAwareProperties class to resolve the values. This functionality is best shown with an example

<bean id="properties"
     class="no.arktekk.stagedspring.properties.EnvironmentAwareProperties">
  <property name="propertyFiles">
    <list>
      <value>myProperties.properties</value>
    </list>
  </property>
</bean>

<bean id="placeHolderConfigurer"
     class="no.arktekk.stagedspring.properties.EnvironmentAwarePropertyPlaceholderConfigurer">
  <property name="stagedProperties" ref="properties" />
</bean>

<bean id="testBean" class="..TestBean">
  <property name="url" value="${aCoolUrl}" />
</bean>

of course the EnvironmentAwareProperties property is marked with the @Autowired annotation so the ref shown above is optional

For more information

Reference documentation and sourcecode is availale at the at project website


About this entry