Spring property-placeholder attributes

0

In this article, we will look into the various attributes of property-placeholder like location and property-ref

location and property-ref attributes

Injection of properties is done by location and property-ref attributes. In the below context xml, property-placeholder element has location and properties-ref attributes.
location attribute has the relative file path to the properties file and properties-ref refers to the properties bean. Before we further play with the context file, we need to know the various sources of properties and the order in which the properties apply.

    <context:property-placeholder location="/org/springframework/context/support/my.properties" properties-ref="localProp"/>
    <util:properties id="localProp">
        <prop key="key1">value1_local</prop>
        <prop key="key4">value4_local</prop>
    </util:properties>
</beans>

Sources of properties

There are two main sources of properties, one is from the environment bean which by default contains java system properties and system environment properties. The second one is called local properties which is nothing but a collection of properties loaded from a resource and properties-ref attribute.

  • properties from environment
  • local properties
    • local properties loaded from file
    • local properties from the properties bean

By default, if the property is not found in environment it is looked for in the local properties. In the local properties, the properties loaded from the resource are given preference to the local properties loaded from the property-ref bean.

property-placeholder attributes

property-placeholder attributes

Attribute local-override

If we want to give preference first to local attributes and then the environment, one can set local-override attribute to true.

We will now understand the default behavior and the contrary.
Context file has properties-ref attribute which points to a properties bean. We have properties key0, key1, key2, key3 and key4.
key0, key1 and key2 are added to system properties. key0 and key3 are added to the properties file. key1 and key4 are added to local properties.
key0 is present in both environment and file, likewise key1 is present in both environment and local properties-ref. By default, environment is given preference so the common properties mentioned in file and properties-ref are ignored. The additional properties key3 and key4 are added to the source of properties.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
    <context:property-placeholder location="/org/springframework/context/support/my.properties"
                                  properties-ref="localProp"/>
    <util:properties id="localProp">
        <prop key="key1">value1_local</prop>
        <prop key="key4">value4_local</prop>
    </util:properties>
    <bean id="key0" class="java.lang.String">
        <constructor-arg index="0" value="${key0}"/>
    </bean>
    <bean id="key1" class="java.lang.String">
        <constructor-arg index="0" value="${key1}"/>
    </bean>
    <bean id="key2" class="java.lang.String">
        <constructor-arg index="0" value="${key2}"/>
    </bean>
    <bean id="key3" class="java.lang.String">
        <constructor-arg index="0" value="${key3}"/>
    </bean>
    <bean id="key4" class="java.lang.String">
        <constructor-arg index="0" value="${key4}"/>
    </bean>
</beans>

Unit test to confirm above behavior.

    @Test
    public void resolvePropertiesFromContextDefault() {
        System.setProperty("key0", "value0_env");
        System.setProperty("key1", "value1_env");
        System.setProperty("key2", "value2_env");
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/org/springframework/context/support/placeHolderDefaultProp.xml");
        assertEquals("value0_env", context.getBean("key0"));
        assertEquals("value1_env", context.getBean("key1"));
        assertEquals("value2_env", context.getBean("key2"));
        assertEquals("value3_file", context.getBean("key3"));
        assertEquals("value4_local", context.getBean("key4"));
    }

If we want the local properties to take precedence over environment properties, we need to set local-override=true. Again within local properties, the ones mentioned in properties-ref are given preference over the ones loaded from file.
Context file:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
    <context:property-placeholder location="/org/springframework/context/support/my.properties"
                                  properties-ref="localProp" local-override="true"/>
    <util:properties id="localProp">
        <prop key="key1">value1_local</prop>
        <prop key="key4">value4_local</prop>
        <prop key="key5">value5_local</prop>
    </util:properties>
    <bean id="key0" class="java.lang.String">
        <constructor-arg index="0" value="${key0}"/>
    </bean>
    <bean id="key1" class="java.lang.String">
        <constructor-arg index="0" value="${key1}"/>
    </bean>
    <bean id="key2" class="java.lang.String">
        <constructor-arg index="0" value="${key2}"/>
    </bean>
    <bean id="key3" class="java.lang.String">
        <constructor-arg index="0" value="${key3}"/>
    </bean>
    <bean id="key4" class="java.lang.String">
        <constructor-arg index="0" value="${key4}"/>
    </bean>
    <bean id="key5" class="java.lang.String">
        <constructor-arg index="0" value="${key5}"/>
    </bean>
</beans>

Unit test to capture the override behavior.

    @Test
    public void resolvePropertiesFromContextLocalOverride() {
        System.setProperty("key0", "value0_env");
        System.setProperty("key1", "value1_env");
        System.setProperty("key2", "value2_env");
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/org/springframework/context/support/placeHolderLocalOverride.xml");
        assertEquals("value0_file", context.getBean("key0"));
        assertEquals("value1_local", context.getBean("key1"));
        assertEquals("value2_env", context.getBean("key2"));
        assertEquals("value3_file", context.getBean("key3"));
        assertEquals("value4_local", context.getBean("key4"));
        assertEquals("value5_local", context.getBean("key5"));
    }
Share.

Leave A Reply