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
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)…
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
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/
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())
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 🙂