Saturday, June 4, 2016

Customizing Play application configuration

By default a Play application configuration is defined with a file conf/application.conf. The default configuration file may be replaced or additional configuration files may be provided.

Using alternative configuration file


The default application configuration file may be replaced via system properties:
  • config.resource specifies an alternative configuration as a resource - file name including extension
  • config.file specifies an alternative configuration as a filesystem path: absolute or relative path, file name and extension

For example, a custom configuration file is my-application.conf and it is located in conf directory. It should be specified in run-time with:
activator -Dconfig.resource=my-application.conf
or
activator -Dconfig.file=conf/my-application.conf

Using several configuration files


A configuration file may include another configuration file with "include" statement. In such a case all properties from the included configuration will be inherited.
Any property from the included configuration may be reassigned with the different value in the including configuration.
For example, the my-application.conf may include the default application.conf:
include "application.conf"

# Redefined properties (put here properties, defined in the application.conf)
# ~~~~~
....
# Additional properties
# ~~~~~
....

Using different configuration for tests


Availability to use a different configuration has a great value for testing. For example, you can replace the real DB with the in-memory DB while running the tests or make another reasonable substitutions for the application properties.
The sbt provides a shortcut for a using a different configuration file for tests and so it should not be mentioned explicitly with -Dconfig options while running the tests.

To add a different configuration for tests:
1. Create a tests configuration file conf/my-app-test.conf (select whatever file name).
2. Suppose, the application configuration is defined with conf/application.conf and defined mySql as a dbDriver:

# Database configuration
# ~~~~~
# MySql
db.default.driver=com.mysql.jdbc.Driver
db.default.url=".. real DB connection string "
db.default.jndiName=AppDS
jpa.default=appDbPersistanceUnit
Redefine application configuration properties in the test configuration:
include "application.conf"

# Database configuration
# ~~~~~
# H2
db.default.driver=org.h2.Driver
db.default.url="jdbc:h2:mem:play"
db.default.jndiName=DefaultDS
jpa.default=testPersistenceUnit
3. Instruct the sbt to use a different configuration file when running the tests. Add to build.sbt:
javaOptions in Test ++= Seq("-Dconfig.file=conf/test.conf")
or
javaOptions in Test += "-Dconfig.file=conf/test.conf"
4. Run tests:
activator test
or
sbt test
Note: If you are using Eclipse as IDE, you still should provide a VM argument -Dconfig.file=conf/test.conf to a test run configuration.

Using Java configuration files


As soon as particular services/classes are used by a Play application as a dependency jar, they could have their own configuration. Such jar's configuration is a regular Java configuration file, which should be handled explicitly somewhere in the code including loading and access to the properties.

Play is not aware on additional configuration files but its configuration yet may be used for setting of additional configurations.
Let's consider an example.

1. The configuration class AppPropertiesConfiguration is implemented with apache.commomns.configuration framework. It loads a properties configuration from a directory, which is defined by the system property config.dir:
package com.alasch1.configuration.api;  
 import java.io.File;  
 import org.apache.commons.configuration.ConfigurationException;  
 import org.apache.commons.configuration.PropertiesConfiguration;  
 import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;  
 /**  
  * Implements application configuration, based on properties file  
  *   
  * @author aschneider  
  *  
  */  
 public abstract class AppPropertiesConfiguration implements AppConfiguration {
  
      private static final String CONFIG_DIR_SYSTEM_PROPERTY = "config.dir";  
      private PropertiesConfiguration configuration;
  
      public AppPropertiesConfiguration() {  
      }
  
      abstract public String getConfigFileName();

      public void init() {  
           try {  
                configuration = new PropertiesConfiguration(buildConfigPath());  
                configuration.setReloadingStrategy(new FileChangedReloadingStrategy());  
                configuration.setAutoSave(true);  
           }   
           catch (ConfigurationException e) {  
                System.err.println("Failed to initilize configuration file "+ getConfigFileName());  
                throw new ConfigurationError(e);  
           }            
      }
  
      public String getConfigDirSystemProperty() {  
           return CONFIG_DIR_SYSTEM_PROPERTY;  
      } 
 
      public PropertiesConfiguration getConfiguration() {  
           return configuration;  
      }
  
      public String buildConfigPath() {  
           String configPath = System.getProperty(getConfigDirSystemProperty());  
           if (configPath != null) {  
                // System property config.dir is defined  
                configPath += File.separator + getConfigFileName();  
           }  
           else {  
                // Use embedded configuration file  
                configPath = Thread.currentThread().getContextClassLoader().getResource(getConfigFileName()).getPath();  
           }  
           return configPath;  
      }  
 }  
2. Play configuration file application.conf contains the property config.dir, assigned with value conf - the standard location of the Play configuration:
config.dir=conf
3. Additional configuration files must be located in the conf directory.
4. On startup the Play application reads a value of the property config.dir from its application.conf and assigns it to the system property config.dir. It calls to AppConfigurationManager, which takes care to init all additional configurations:
 @Singleton  
 public class StartUpHandler {  
      private static final String CONFIG_DIR_PROPERTY = "config.dir";  
      @Inject  
      public StartUpHandler(final Configuration configuration) {  
           System.setProperty(CONFIG_DIR_PROPERTY, configuration.getString(CONFIG_DIR_PROPERTY));  
           AppConfigurationManager.start();  
      }  
     ...  
 }  

No comments :

About the author

My Photo
I trust only simple code and believe that code should be handsome. This is not a matter of technology, but professional approach, consolidated after years of software development. I enjoy to cause things working and feel very happy, when I manage to solve a problem.
Back to Top