5.10. Properties Management¶
Caution
This version is already obsolete. Please check the latest guideline.
Table of Contents
5.10.1. Overview¶
This section explains how to manage properties.
Value that needs to be managed as properties can be classified into following two categories.
| Sr. No. | Classification | Description | Example |
|---|---|---|---|
| Environment dependent setting | The setting needs to be changed according to the environment on which the application is running. It depends on non-functional requirements such as system configuration. |
|
|
| Application settings | The settings that can be customize the application behavior. It depends on functional requirements. |
|
Note
In this guideline, it is recommended to manage these settings as properties (properties file).
If an application is mechanized such a way that acquires setting from the properties, there is no need to re-build the application even if there is any changes in these values. Therefore it is possible to release the tested application on production environment.
About how to release the tested application, refer to “Removing Environment Dependency”.
Tip
Values that are managed as properties can be acquired from JVM system properties (-D option) or OS environment variables. About access order, refer to “How to use”.
Values that are managed as properties can be used at the following two locations.
- Bean definition file
- Java classes managed by DI container
5.10.2. How to use¶
5.10.2.1. About properties file definition¶
<context:property-placeholder/> tag in bean definition file.<context:property-placeholder/> tag reads the group of specified properties filesxxx specified in ${xxx} format in @Value annotation or bean definition files.Note
When specified in
${xxx:defaultValue}format and when keyxxxis not set in properties file,defaultValueis used.
See the method below for defining a properties file
bean definition file
- applicationContext.xml
- spring-mvc.xml
<context:property-placeholder location="classpath*:META-INF/spring/*.properties"/> <!-- (1) -->
Sr. No. Description (1) In location, set the resource location path.Multiple paths separated by comma can be specified in location attribute.By performing above settings, read properties file under META-INF/spring directory of class path.Once these settings are done, just add the properties file under META-INF/spring.For details on location value, see Reference.Note
<context:property-placeholder>needs to be defined in bothapplicationContext.xmlandspring-mvc.xml.
Properties are accessed in the following order by default.
- System properties of active JVM
- Environment variables
- Application definition properties
<context:property-placeholder/> tag to true.bean definition file
<context:property-placeholder location="classpath*:META-INF/spring/*.properties" local-override="true" /> <!-- (1) -->
Sr. No. Description (1) Access properties in the following order when local-override attribute is set to true.1. Application definition properties2. System properties of active JVM3. Environment variables
Note
Normally the above settings are sufficient. When multiple
<context:property-placeholder/>tags are specified, read order can be defined by setting order attribute value.bean definition file
<context:property-placeholder location="classpath:/META-INF/property/extendPropertySources.properties" order="1" ignore-unresolvable="true" /> <!-- (1) --> <context:property-placeholder location="classpath*:/META-INF/spring/*.properties" order="2" ignore-unresolvable="true" /> <!-- (2) -->
Sr. No. Description (1) By setting the order attribute to a value which is less than (2), properties file corresponding to location attribute is read before (2).When a key overlapping with the key in properties file read in (2) exists, value fetched in (1) is given preference.By setting ignore-unresolvable attribute to true, error which occurs when key exists only in properties file of (2) can be prevented. (2) By setting the order attribute to value greater than (1), properties file corresponding to location attribute is read after (1).When a key overlapping with the key in properties file read in (1) exists, value fetched in (1) is set.By setting ignore-unresolvable attribute to true, error which occurs when key exists only in properties file of (1) can be prevented.
5.10.2.2. Using properties in bean definition file¶
<context:property-placeholder/> ) is specified.${} placeholder.Properties file
database.url=jdbc:postgresql://localhost:5432/shopping database.password=postgres database.username=postgres database.driverClassName=org.postgresql.Driver
bean definition file
<bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp2.BasicDataSource"> <property name="driverClassName" value="${database.driverClassName}"/> <!-- (1) --> <property name="url" value="${database.url}"/> <!-- (2) --> <property name="username" value="${database.username}"/> <!-- (3) --> <property name="password" value="${database.password}"/> <!-- (4) --> <!-- omitted --> </bean>
Sr. No. Description (1) By setting${database.driverClassName}, the value for read properties file keydatabase.driverClassNamegets substituted. (2) By setting${database.url}, the value for read properties file keydatabase.urlgets substituted. (3) By setting${database.username}, the value for read properties file keydatabase.usernamegets substituted. (4) By setting${database.password}, the value for read properties file keydatabase.passwordgets substituted.
As a result of reading the properties file key, the values are replaced as follows:
<bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp2.BasicDataSource"> <property name="driverClassName" value="org.postgresql.Driver"/> <property name="url" value="jdbc:postgresql://localhost:5432/shopping"/> <property name="username" value="postgres"/> <property name="password" value="postgres"/> <!-- omitted --> </bean>
5.10.2.3. Using properties in Java class¶
@Value annotation in the field wherein properties values are to be stored.@Value annotation, the corresponding object needs to be stored in DI container of Spring.<context:property-placeholder/> ) is specified.@Value annotation to variables and setting properties file key in value using ${} placeholder.Properties file
item.upload.title=list of update file item.upload.dir=file:/tmp/upload item.upload.maxUpdateFileNum=10
Java class
@Value("${item.upload.title}") // (1) private String uploadTitle; @Value("${item.upload.dir}") // (2) private Resource uploadDir; @Value("${item.upload.maxUpdateFileNum}") // (3) private int maxUpdateFileNum; // Getters and setters omitted
Sr. No. Description (1) By setting${item.upload.title}to@Valueannotation value, the value for read properties file keyitem.upload.titlegets substituted.uploadTitleis substituted by “list of update file” in String class. (2) By setting${item.upload.dir}to@Valueannotation value, the value for read properties file keyitem.upload.dirgets substituted.org.springframework.core.io.Resourceobject created with initial value “/tmp/upload” is stored inuploadDir. (3) By setting${item.upload.maxUpdateFileNum}to@Valueannotation value, the value for read properties file keyitem.upload.maxUpdateFileNumgets substituted.maxUpdateFileNumis substituted by 10.Warning
There could be cases wherein properties values are to be used in static methods of Utility classes etc.; however properties value cannot be fetched using
@Valueannotation in classes for which bean definition is not done. In this case, it is recommended to create Helper class with@Componentannotation and to fetch properties values using@Valueannotation. (This class needs to be included in the component-scan scope.) Classes in which values from properties file is to be used, should not be made Utility classes.
5.10.3. How to extend¶
Extension of method for fetching properties values is explained below. This can be achieved by
extending org.springframework.context.support.PropertySourcesPlaceholderConfigurer class.
The example below illustrates a case wherein encrypted properties file is used.
5.10.3.1. Decrypting encrypted values and using them¶
bean definition file
- applicationContext.xml
- spring-mvc.xml
<!-- (1) --> <bean class="com.example.common.property.EncryptedPropertySourcesPlaceholderConfigurer"> <!-- (2) --> <property name="locations" value="classpath*:/META-INF/spring/*.properties" /> </bean>
Sr. No. Description (1) Define the extended PropertySourcesPlaceholderConfigurer instead of<context:property-placeholder/>.<context:property-placeholder/>tag should be deleted. (2) Set “locations” in name attribute of property tag and specify the path of the properties file to be read, in value attribute.The method of specifying path of the properties file to be read is same as About properties file definition.
Java class
- Extended PropertySourcesPlaceholderConfigurer
public class EncryptedPropertySourcesPlaceholderConfigurer extends PropertySourcesPlaceholderConfigurer { // (1) @Override protected void doProcessProperties( ConfigurableListableBeanFactory beanFactoryToProcess, StringValueResolver valueResolver) { // (2) super.doProcessProperties(beanFactoryToProcess, new EncryptedValueResolver(valueResolver)); // (3) } }
Sr. No. Description (1) Inherited PropertySourcesPlaceholderConfigurer, should extendorg.springframework.context.support.PropertySourcesPlaceholderConfigurerclass. (2) OverridedoProcessPropertiesmethod oforg.springframework.context.support.PropertySourcesPlaceholderConfigurerclass. (3) CalldoProcessPropertiesof parent class; however, use valueResolver(EncryptedValueResolver)valueResolverwhereinvalueResolveris implemented independently.InEncryptedValueResolverclass, decrypt when encrypted values of properties file are fetched.
- EncryptedValueResolver.java
public class EncryptedValueResolver implements StringValueResolver { // (1) private final StringValueResolver valueResolver; EncryptedValueResolver(StringValueResolver stringValueResolver) { // (2) this.valueResolver = stringValueResolver; } @Override public String resolveStringValue(String strVal) { // (3) // Values obtained from the property file to the naming // as seen with the encryption target String value = valueResolver.resolveStringValue(strVal); // (4) // Target messages only, implement coding if (value.startsWith("Encrypted:")) { // (5) value = value.substring(10); // (6) // omitted decryption } return value; } }
Sr. No. Description (1) InheritedEncryptedValueResolvershould implementorg.springframework.util.StringValueResolver. (2) WhenEncryptedValueResolverclass is created in constructor, setStringValueResolverinherited fromEncryptedPropertySourcesPlaceholderConfigurer. (3) OverrideresolveStringValuemethod oforg.springframework.util.StringValueResolver.If the values fetched from properties file are encrypted, these must be decrypted inresolveStringValuemethod.The process mentioned in steps (5) and (6) is just an example, the process differs depending on type of implementation. (4) The value is being fetched by specifying key as an argument ofresolveStringValuemethod ofStringValueResolverset in constructor. This value is defined in properties file. (5) Check whether values of properties file are encrypted. The method to determine whether the values are encrypted differs depending on type of implementation.Here, the value can be considered encrypted if it starts with “Encrypted:”.If the values are encrypted, decrypt them in step (6) and if they are not encrypted, return them as is. (6) Encrypted values of properties file are being decrypted. (No specific decryption process is mentioned.)Decryption method differs depending on type of implementation.
- Helper to fetch properties
@Value("${encrypted.property.string}") // (1) private String testString; @Value("${encrypted.property.int}") // (2) private int testInt; @Value("${encrypted.property.integer}") // (3) private Integer testInteger; @Value("${encrypted.property.file}") // (4) private File testFile; // Getters and setters omitted
Sr. No. Description (1) By setting${encrypted.property.string}to@Valueannotation value, the value for read properties file keyencrypted.property.stringis decrypted and then substituted.Value decrypted in String class is substituted intestString. (2) By setting${encrypted.property.int}to@Valueannotation value, the value for read properties file keyencrypted.property.intis decrypted and then substituted.Value decrypted in integer type is substituted intestInt. (3) By setting${encrypted.property.integer}to@Valueannotation value, the value for read properties file keyencrypted.property.integeris decrypted and then substituted.Value decrypted in Integer class is substituted intestInteger. (4) By setting${encrypted.property.file}to@Valueannotation value, the value for read properties file keyencrypted.property.fileis decrypted and then substituted.IntestFile, File object is stored as initial value which is created using the decrypted value (auto conversion).
Properties file
The values encrypted as properties values are prefixed with “Encrypted:” to indicate that they are encrypted. Although one can view the contents of properties file, but cannot understand them as the values are encrypted.
encrypted.property.string=Encrypted:ZlpbQRJRWlNAU1FGV0ASRVteXhJQVxJXXFFAS0JGV1Yc encrypted.property.int=Encrypted:AwI= encrypted.property.integer=Encrypted:AwICAgI= encrypted.property.file=Encrypted:YkBdQldARkt/U1xTVVdfV1xGHFpGX14=