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.