Properties Management
===================================================================================
.. only:: html
 .. contents:: Table of Contents
    :depth: 3
    :local:
Overview
--------------------------------------------------------------------------------
This section explains how to manage properties.
Value that needs to be managed as properties can be classified into following two categories.
.. tabularcolumns:: |p{0.10\linewidth}|p{0.20\linewidth}|p{0.35\linewidth}|p{0.35\linewidth}|
.. list-table::
    :header-rows: 1
    :widths: 10 20 35 35
    * - Sr. No.
      - Classification
      - Description
      - Example
    * - 1.
      - 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.
      - * Database connection information (connection URL, connection user, password, etc)
        * Destination of the file storage (directory path etc)
        * more ...
    * - 2.
      - Application settings
      - The settings that can be customize the application behavior.
        It depends on functional requirements.
      - * Password valid days
        * Reservation period days
        * more ...
.. 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.
.. 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 ":ref:`PropertiesManagementHowToUse`".
|
Values that are managed as properties can be used at the following two locations.
* Bean definition file
* Java classes managed by DI container
|
.. _PropertiesManagementHowToUse:
How to use
--------------------------------------------------------------------------------
.. _technical-details_label:
About properties file definition
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| Properties file values in Java class and bean definition file  can be accessed by defining ```` tag in bean definition file.
| ```` tag reads the group of specified properties files
| and can fetch values for properties files key \ ``xxx``\  specified in \ ``${xxx}``\  format in ``@Value`` annotation or bean definition files.
 .. note::
    When specified in \ ``${xxx:defaultValue}``\ format and when key \ ``xxx``\  is not set in properties file, \ ``defaultValue``\   is used.
|
See the method below for defining a properties file
**bean definition file**
- applicationContext.xml
- spring-mvc.xml
 .. code-block:: xml
      
 .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}|
 .. list-table::
    :header-rows: 1
    :widths: 10 90
    * - 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::
    \ ````\  needs to be defined in both ``applicationContext.xml`` and ``spring-mvc.xml``.
|
Properties are accessed in the following order by default.
#. System properties of active JVM 
#. Environment variables
#. Application definition properties
| As per default setting, properties file defined in application is searched and read after all environment related properties (JVM system properties and environment variables) are read.
| Read sequence can be changed by setting local-override attribute of ```` tag to true.
| By performing these settings, the properties defined in application are enabled with higher priority.
**bean definition file**
 .. code-block:: xml
    
 .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}|
 .. list-table::
   :header-rows: 1
   :widths: 10 90
   * - Sr. No.
     - Description
   * - | (1)
     - | Access properties in the following order when local-override attribute is set to true.
       | 1. Application definition properties
       | 2. System properties of active JVM
       | 3. Environment variables
|
 .. note::
        Normally the above settings are sufficient.
        When multiple ```` tags are specified, read order can be defined by setting order attribute value.
            **bean definition file**
            .. code-block:: xml
                
                
            .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}|
            .. list-table::
               :header-rows: 1
               :widths: 10 90
               * - 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.
|
.. _bean-definition-file_label:
Using properties in bean definition file
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| See the example below of datasource configuration file.
| In the following example, it is assumed that properties file definition ( ```` ) is specified.
| Basically, property value can be set by setting properties file key in bean definition file using ``${}`` placeholder.
**Properties file**
 .. code-block:: properties
   database.url=jdbc:postgresql://localhost:5432/shopping
   database.password=postgres
   database.username=postgres
   database.driverClassName=org.postgresql.Driver
|
**bean definition file**
 .. code-block:: xml
   
         
         
         
         
       
   
|
 .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}|
 .. list-table::
   :header-rows: 1
   :widths: 10 90
   * - Sr. No.
     - Description
   * - | (1)
     - | By setting ``${database.driverClassName}``, the value for read properties file key \ ``database.driverClassName``\  gets substituted.
   * - | (2)
     - | By setting ``${database.url}``, the value for read properties file key \ ``database.url``\  gets substituted.
   * - | (3)
     - | By setting ``${database.username}``, the value for read properties file key \ ``database.username``\  gets substituted.
   * - | (4)
     - | By setting ``${database.password}``, the value for read properties file key \ ``database.password``\  gets substituted.
|
As a result of reading the properties file key, the values are replaced as follows:
 .. code-block:: xml
   
       
       
       
       
       
   
|
Using properties in Java class
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| It is possible to use properties in Java class by specifying ``@Value`` annotation in the field wherein properties values are to be stored.
| To use ``@Value`` annotation, the corresponding object needs to be stored in DI container of Spring.
| In the following example, it is assumed that properties file definition ( ```` ) is specified.
| External reference is possible by adding ``@Value``  annotation to variables and setting properties file key in value using ``${}`` placeholder.
**Properties file**
 .. code-block:: properties
   item.upload.title=list of update file
   item.upload.dir=file:/tmp/upload
   item.upload.maxUpdateFileNum=10
**Java class**
 .. code-block:: java
   @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
 .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}|
 .. list-table::
   :header-rows: 1
   :widths: 10 90
   * - Sr. No.
     - Description
   * - | (1)
     - | By setting ``${item.upload.title}`` to ``@Value`` annotation value, the value for read properties file key \ ``item.upload.title``\  gets substituted.
       | ``uploadTitle`` is substituted by "list of update file" in String class.
   * - | (2)
     - | By setting ``${item.upload.dir}`` to ``@Value`` annotation value, the value for read properties file key \ ``item.upload.dir``\  gets substituted.
       | \ ``org.springframework.core.io.Resource``\  object created with initial value "/tmp/upload" is stored in ``uploadDir``.
   * - | (3)
     - | By setting ``${item.upload.maxUpdateFileNum}`` to ``@Value`` annotation value, the value for read properties file key \ ``item.upload.maxUpdateFileNum``\  gets substituted.
       | ``maxUpdateFileNum`` is 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 \ ``@Value``\  annotation in classes for which bean definition is not done.
        In this case, it is recommended to create Helper class with ``@Component``  annotation and to fetch properties values using \ ``@Value``\  annotation. (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.
|
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.
|
Decrypting encrypted values and using them
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| To strengthen security, properties file needs to be encrypted in some cases.
| The example below illustrates decryption of encrypted properties values. (No specific encrypting and decrypting methods are mentioned.)
**bean definition file**
- applicationContext.xml
- spring-mvc.xml
 .. code-block:: xml
    
    
        
        
    
 .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}|
 .. list-table::
   :header-rows: 1
   :widths: 10 90
   * - Sr. No.
     - Description
   * - | (1)
     - | Define the extended PropertySourcesPlaceholderConfigurer instead of  ````\. ````\  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 :ref:`technical-details_label`.
**Java class**
- Extended PropertySourcesPlaceholderConfigurer
 .. code-block:: java
    public class EncryptedPropertySourcesPlaceholderConfigurer extends 
        PropertySourcesPlaceholderConfigurer { // (1)
        @Override
        protected void doProcessProperties(
                ConfigurableListableBeanFactory beanFactoryToProcess,
                StringValueResolver valueResolver) { // (2)
            super.doProcessProperties(beanFactoryToProcess, 
                new EncryptedValueResolver(valueResolver)); // (3)
        }
    }
 .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}|
 .. list-table::
   :header-rows: 1
   :widths: 10 90
   * - Sr. No.
     - Description
   * - | (1)
     - | Inherited PropertySourcesPlaceholderConfigurer, should extend ``org.springframework.context.support.PropertySourcesPlaceholderConfigurer`` class.
   * - | (2)
     - | Override ``doProcessProperties`` method of ``org.springframework.context.support.PropertySourcesPlaceholderConfigurer`` class.
   * - | (3)
     - | Call ``doProcessProperties`` of parent class; however, use valueResolver( ``EncryptedValueResolver`` ) ``valueResolver`` wherein ``valueResolver`` is implemented independently.
       | In ``EncryptedValueResolver`` class, decrypt when encrypted values of properties file are fetched.
|
- EncryptedValueResolver.java
 .. code-block:: 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;
        }
    }
 .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}|
 .. list-table::
   :header-rows: 1
   :widths: 10 90
   * - Sr. No.
     - Description
   * - | (1)
     - | Inherited ``EncryptedValueResolver`` should implement ``org.springframework.util.StringValueResolver``.
   * - | (2)
     - | When ``EncryptedValueResolver``  class is created in constructor, set ``StringValueResolver`` inherited from ``EncryptedPropertySourcesPlaceholderConfigurer``.
   * - | (3)
     - | Override ``resolveStringValue`` method of ``org.springframework.util.StringValueResolver``.
       | If the values fetched from properties file are encrypted, these must be decrypted in ``resolveStringValue`` method.
       | 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 of ``resolveStringValue``  method of ``StringValueResolver`` set 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
 .. code-block:: java
    @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
 .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}|
 .. list-table::
   :header-rows: 1
   :widths: 10 90
   * - Sr. No.
     - Description
   * - | (1)
     - | By setting ``${encrypted.property.string}`` to ``@Value`` annotation value, the value for read properties file key \ ``encrypted.property.string``\  is decrypted and then substituted.
       | Value decrypted in String class is substituted in  ``testString``.
   * - | (2)
     - | By setting ``${encrypted.property.int}`` to ``@Value``  annotation value, the value for read properties file key \ ``encrypted.property.int``\  is decrypted and then substituted.
       | Value decrypted in integer type is substituted in ``testInt``.
   * - | (3)
     - | By setting ``${encrypted.property.integer}`` to ``@Value``  annotation value, the value for read properties file key \ ``encrypted.property.integer``\  is decrypted and then substituted.
       | Value decrypted in Integer class is substituted in ``testInteger``.
   * - | (4)
     - | By setting ``${encrypted.property.file}`` to ``@Value`` annotation value, the value for read properties file key \ ``encrypted.property.file``\  is decrypted and then substituted.
       | In ``testFile``, 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.
 .. code-block:: properties
   encrypted.property.string=Encrypted:ZlpbQRJRWlNAU1FGV0ASRVteXhJQVxJXXFFAS0JGV1Yc
   encrypted.property.int=Encrypted:AwI=
   encrypted.property.integer=Encrypted:AwICAgI=
   encrypted.property.file=Encrypted:YkBdQldARkt/U1xTVVdfV1xGHFpGX14=
.. raw:: latex
   \newpage