venerdì 14 novembre 2014

Grails external configurations without reloading the app

Any time you want to change the configurations in Config.groovy you have to restart the application (if it is deployed). And if you need to add new configurations you have to redeploy the app even if you don't need to add additional code to manage them because you have already built a dynamic mechanism.

This is quite annoying. Fortunately Grails expose different way to solve this problem.

First of all have a look at the documentation: http://grails.org/doc/latest/guide/conf.html#configExternalized

There is only something that doesn't work for me: they say it is possible to perform change without restarting the app but that's not my case, i had always to restart the app.

So, let's have a look at the important code section:

grails.config.locations = [
   "classpath:${appName}-config.properties",
   "classpath:${appName}-config.groovy",
   "file:${userHome}/.grails/${appName}-config.properties",
   "file:${userHome}/.grails/${appName}-config.groovy" ]

Here you can specify two different ways to get an external configuration file which is via classpath or via file.

If you want to put a file directly under the app root folder, simply use this kind of syntax:
file:configfile.groovy

This way you can read properties from an external file.

But what if you want to read the file using an environment variable which specify the location of the file, so that you can have different environment configuration files without the need to know where the file is, as often happens in real world systems where developers doesn't know what is the production config file which is usually managed by an application manager?

Here is the solution:

if (System.getenv("TEST_CONF_GROOVY")) {
   grails.config.locations << "file:" + System.getenv("TEST_CONF_GROOVY")
}

Here you are simply saying to Grails to use, if defined, an environment variable which is the path to your configuration file.

At this point you are able to specify external configuration file but what if you want to update configuration at runtime?

Here it is: you can specify a code section (i placed it inside a controller) which refresh the external configuration:

import grails.util.Environment

def grailsApplication;

def refreshConfig() {

def files = grailsApplication.config.grails.config.locations
   
   files.each { fileName ->
   
      File configFile = new File(fileName.replace("file:", "")).absoluteFile
   
      try {
   
         ConfigSlurper configSlurper = new ConfigSlurper(Environment.getCurrent().getName())
         ConfigObject updatedConfig
         updatedConfig = configSlurper.parse(configFile.text)
         grailsApplication.config.merge(updatedConfig)
      } catch (Throwable e) {
         log.error("Failed parsing and merging config file ${configFile} changes", e)
      }
   }
}

It is super simple and this code is specific to groovy configurations and not properties file. It simply parse again any external file and merge the new configurations with the current one.

So you don't need anymore to restart or reload the server!
Now that you have read my article, i would like to show you another thing: i've developed an app to help increase customers registration and customers conversion.

You can find it at appromocodes.com