Playing with Grails application configuration

This small tutorial will show how to create a configuration file and how to manage configuration of your Grails application. It will show how to

  • Access configuration parameters
  • Create external configuration
  • Configure Spring for different environments
  • Create a new environment

Accessing configuration parameters

The configuration of Grails is stored in grails-app/conf directory. Parameters are stored in configuration files in “plain text way”

app.default.user = "tester"

or in “structured way”

app{
	default{
		user = "tester"
	}
}

In an application, one can access the parameters easily. Just import the correct class and ask it the correct question.

import org.codehaus.groovy.grails.commons.ConfigurationHolder
 
class TestController {
	def query = {
		render ConfigurationHolder.config.app.default.user
	}
}

The example above should render the string “tester”. Moreover, in the configuration files, one can easily define distinct config values for each of three different environments – production, development and test.

environments {
	production {
		grails.serverURL = "http://www.changeme.com"
	}
	development {
		grails.serverURL = "http://www.do-not-change.cz"
	}
	test {
		grails.serverURL = "http://www.just-for-test.de"
	}
}

External configuration

The configuration mechanism of Grails is nice, but there is a small trouble. The configuration files are compiled and packed into the deployment package (WAR) during project build phase. However, one usually does not want to rebuild the whole application just to change say a database password. So, how to do it?

The first step is to create an external configuration file. Let’s name it externalConfig.groovy. Its structure will be the same as the structure of the other configuration files – “flat text” or “structured”.

Now, how do you tell Grails to find and use it? Adding the following code to the beginning of your config.groovy will do the trick. It expects that there is an OS environment variable MY_GREAT_CONFIG that points to the configuration file.

if(System.getenv("MY_GREAT_CONFIG")) {
	println( "Including configuration file: " + System.getenv("MY_GREAT_CONFIG"));
	grails.config.locations << "file:" + System.getenv("MY_GREAT_CONFIG")
} else {
	println "No external configuration file defined."
}

Spring configuration

The grails-app/conf/spring/resources.groovy file gives the developer a convenient way to define beans. Distinguishing environments is slightly more complex than in other configuration files, but still elegant.

switch(GrailsUtil.environment) {
	case "production":
		myBean(package.BeanClass, 1, "prod")
		break
	case "test":
		myBean(package.BeanClass, 1, "test")
		break
	case "development":
		myBean(package.BeanClass, 1, "dev")
		break

Configuration parameters can be used here the same way as in the controller example above.

myBean(package.BeanClass, 1, ConfigurationHolder.config.app.default.user)

Adding more environments

It might seem that the development, test and production environments are just enough. Yes, that is true for most basic scenarios. However, if you develop for a large company with sophisticated deployment procedures, there are typically several production-level application server environments (one for user acceptance testing, one for system patch analysis and performance testing, one for production etc.), all of them corresponding to the Grails “production” environment.

How to address this scenario? Easily. Just introduce another environment into your configuration

environments {
	production {
		grails.serverURL = "http://www.changeme.com"
	}
	development {
		grails.serverURL = "http://www.do-not-change.cz"
	}
	test {
		grails.serverURL = "http://www.just-for-test.cz"
	}
	uat {
		grails.serverURL = "http://www.uat-testing-environment.cz"
	}
}

and run the application or create a war file with an extra parameter

	grails -Dgrails.env=uat war
	or
	grails -Dgrails.env=uat run-app

6 Responses to “Playing with Grails application configuration”

  1. Brad Rhoads Says:

    In Grails 1.2.0 doing something like:

    grails.config.locations < < “file:” + System.getenv(“MY_GREAT_CONFIG”)

    results in:

    groovy.lang.MissingMethodException: No signature of method: groovy.util.ConfigObject.leftShift() is applicable for argument types:
    (org.codehaus.groovy.runtime.GStringImpl)…

  2. Brad Rhoads Says:

    You need to do:

    if(!grails.config.location || !(grails.config.location instanceof List) {
    grails.config.location = []
    }

    grails.config.location < < “file:” + System.getenv(“MY_GREAT_CONFIG)

    http://old.nabble.com/Setting-grails.config.locations-results-in-left-shift-error-td27232517.html

  3. Grials Externalizing properties « Contract to Code Says:

    […] see this site . “The configuration mechanism of Grails is nice, but there is a small trouble. The […]

  4. Sayeef Says:

    External configuration
    This procedure does not for datasource. see Graeme Rocher’s comment in http://jira.codehaus.org/browse/GRAILS-4673.
    Please see (sorry self promotion—but I work on it for 2 hours)
    http://redtoledo.wordpress.com/2010/03/11/externalize-datasource-configuration-in-grails/

  5. Roman Mackovcak Says:

    ConfigSlurper should do the job. Adding following line to the beginning of the DataSource should do the job

    def config = new ConfigSlurper().parse(new File(‘configFileName’).toURL())

  6. Jeremy Ryan Says:

    In response to Sayeef saying that you cannot externally configure “datasource” property, I’ve found a way to do this for at least the URL property. It may work for all of of the datasource properties, but I haven’t tried.

    DataSource.groovy contains a “dataSource” with no URL:

    dataSource {
    pooled = false
    driverClassName = “org.hsqldb.jdbcDriver”
    username = “sa”
    password = “”
    dbCreate = “update”
    }

    Config.groovy specifies that you should load both .groovy and .properties files:

    grails.config.locations = [ “classpath:${appName}-config.properties”, “classpath:${appName}-config.groovy”]

    And lastly, your application-config.properties file contains your dataSource.URL property. In my case it was:

    dataSource.url = jdbc:hsqldb:file:c://myDB;shutdown=true

    This allows you to change the URL in a human-readable properties file. But remember, just because you can, doesn’t mean you should :)