Using an External Configuration in Grails

By default, Grails configuration information is stored in grails-app/config/Config.groovy and contains various settings, including the configuration for logging. While this is convenient, it has caused me concern when deploying applications since Config.groovy will get compiled and placed in the war file. True, you can have different settings based on the environment (development, production, etc.), but often I can not predict what the production environment might be. Perhaps I need to tweak the logger level in production after it has been deployed. Maybe the database needs to be moved to a different server.

External configuration files allow you to make these changes without having to redeploy the war file.

Looking at the top of Config.groovy (this is from Grails 1.2.0), you will see that following fragment that has been commented out.

// locations to search for config files that get merged into the main config
// config files can either be Java properties files or ConfigSlurper scripts
 
// grails.config.locations = [ "classpath:${appName}-config.properties",
//                             "classpath:${appName}-config.groovy",
//                             "file:${userHome}/.grails/${appName}-config.properties",
//                             "file:${userHome}/.grails/${appName}-config.groovy"]

The example provided shows that configuration data can be supplied in the classpath or in the file system and can be a Groovy file or a Java properties file. I chose to use a Groovy file in the file system, so my declaration looks like the following:

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

Note: This was for testing. For production use, I would use a directory like: /grails/app-config or use the classpath location.

To test the idea, I commented out all the logging configuration in Config.groovy. My test application name is st3, so my st3-config.groovy file contains the following:

// log4j configuration
log4j = {
    appenders {
        rollingFile name:'rollingFile', maxFileSize:102400, maxBackupIndex: 5, file:'/temp/logs/st3.log',
                    layout:pattern(conversionPattern:'%d %-5p %c{2} %x - %m%n')
        console name:'stdout', layout:pattern(conversionPattern: '%c{2} %m%n')
    }
 
    root {
        error 'stdout', 'rollingFile'
    }
 
    error  'org.codehaus.groovy.grails.web.servlet',  //  controllers
               'org.codehaus.groovy.grails.web.pages', //  GSP
               'org.codehaus.groovy.grails.web.sitemesh', //  layouts
               'org.codehaus.groovy.grails.web.mapping.filter', // URL mapping
               'org.codehaus.groovy.grails.web.mapping', // URL mapping
               'org.codehaus.groovy.grails.commons', // core / classloading
               'org.codehaus.groovy.grails.plugins', // plugins
               'org.codehaus.groovy.grails.orm.hibernate', // hibernate integration
               'org.springframework',
               'org.hibernate',
               'net.sf.ehcache.hibernate',
	       'org.apache'
 
    warn   'org.mortbay.log'
 
    debug  'grails.app'
 
}
 
// st3 properties
st3.importDb.url='jdbc:mysql://localhost/jsfsc'

This configuration changes the default “layout” for the console logging and adds a rolling file appender as well. The last line of the file defines a new configuration property called st3.importDb.url to demonstration how you could handle application properties.

You can access the configuration in your controllers through the grailsApplication property that gets injected as follows:

println grailsApplication.config.st3.importDb.url

If you want to access configuration data in a service, you can do so as follows:

import org.codehaus.groovy.grails.commons.*
 
class DataLoaderService {
    def config = ConfigurationHolder.config
 
    boolean transactional = true
 
    def loadData() {
        log.debug 'loadData called debug'
        log.debug "st3.importDb.url = ${config.st3.importDb.url}"
    }
}

Now you have the flexibility to configure your application the way to want.

Leave a Reply