Grails framework One of the cool things I love about Grails is its out-of-the box support for different environments (dev, test, prod, etc.). I can have separate configuration for them – making life easy when doing deployment – or enable/disable certain features of the application depending on which environment the application is running on.

Configuring multiple environments

Typically there are three areas in the Grails framework to keep environment specific configurations: Config.groovy, DataSource.groovy and BootStrap.groovy.

Sample Config.groovy snippet for configuring serverUrl in different environments:

environments {
    development {
        grails.logging.jul.usebridge = true
        grails.serverURL = "http://localhost:8080/mygrailsapp"
    }
    test {
        grails.logging.jul.usebridge = false
        grails.serverURL = "http://localhost:8080/mygrailsapp"
    }
    production {
        grails.logging.jul.usebridge = false
        grails.serverURL = "http://www.mygrailsapp.com"
        grails.app.context = "/"
    }
}

Note the grails.app.context param that tells Grails to use root context path in production.

Sample DataSource.groovy configuration with different DB per environment:

environments {
    development {
        dataSource {
            dbCreate = "create-drop" // one of 'create', 'create-drop', 'update', 'validate', ''
            url = "jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000"
            username = "sa"
            password = ""
        }
    }
    test {
        dataSource {
            dbCreate = "update"
            url = "jdbc:h2:mem:testDb;MVCC=TRUE;LOCK_TIMEOUT=10000"
            username = "sa"
            password = ""
        }
    }
    production {
        dataSource {
            dbCreate = "update"
            url = System.getProperty("JDBC_CONNECTION_STRING")
            driverClassName = "com.mysql.jdbc.Driver"
            dialect = org.hibernate.dialect.MySQL5InnoDBDialect
            pooled = true
            properties {
               maxActive = -1
               minEvictableIdleTimeMillis=1800000
               timeBetweenEvictionRunsMillis=1800000
               numTestsPerEvictionRun=3
               testOnBorrow=true
               testWhileIdle=true
               testOnReturn=true
               validationQuery="SELECT 1"
            }
        }
    }
}

In this example Grails gets the JDBC url (including username and password) for production from the system properties. This way I don’t have to worry that the DB credentials are exposed in the source code and I can also make changes to the JDBC connection string without requiring redeployment of the application.

Sample BootStrap.groovy with environment specific logic:

import grails.util.Environment
...

switch (Environment.current) {
    case Environment.DEVELOPMENT:
        new Site(url: 'http://kaviddiss.com').save(flush: true)
        break
}

Creating war file for different environments

When Grails packages the web application into a war file, we have to tell which environment configuration to use:

grails prod war

There are three preset environments: development (dev), testing (test) and production (prod), for other custom environments we can use the following syntax:

grails -Dgrails.env=staging war

We can even tell Grails to use a custom file name:

grails -Dgrails.env=staging war target/mygrailsapp-staging.war

Using environment specific logic in GSP files

I’m using Google Analytics in one of my projects and I don’t want the Google to collect data when I run the application locally. Here’s how I solved it in GSP:

...

<g:if env="development">
</g:if>
<g:else>
<script>
  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

  ga('create', 'UA-XXXXXXXX-Y', '<my grails app>');
  ga('send', 'pageview');

</script>
</g:else>

...

I’m using here the env attribute of the <g:if> tag, though it would be nicer if I didn’t need the else block. Anyways, I hope you found this little tutorial helpful. Cheers.