Environment independent WAR in Grails
Sometimes I like to break out of Grails convention of building separate WAR archives for each environment. I guess that typical Grails application is developed with development profile and when code is ready it is pushed straight to the production. Unfortunately, that is not the case in corporate environment
Common choice of environments I see everyday is development, integration, certification (or staging) and production. Possibilities are almost endless, and depend on creativity of your enterprise architects
Suppose we want adapt light web framework to heavyweight corporate standards:
Adding custom environment is simple. Open Config.groovy and add new section id Grails' DSL:
environments { production { grails.serverURL = "http://localhost:8080/${appName}" } staging { grails.serverURL = "http://localhost:8080/${appName}" } development { grails.serverURL = "http://localhost:8080/${appName}" } test { grails.serverURL = "http://localhost:8080/${appName}" } }
You can do exactly the same thing in DataSource.groovy and add database url for new enviroment:
environments { // ... integration { dataSource { dbCreate = "update" url = "jdbc:hsqldb:file:intDb;shutdown=true" } } }
Finallly, run grails application with usual command line option:
grails -Dgrails.env=integration run-app
or, even better, add this command line switch to your favorite servlet container environment options.
I want more
Adding custom environment with just another database setting is trivial use case. You may want to have additional per-environment configuration settings, different for each environment. For example, while developing eBay auction sniper, you would like to publish production like instance, but connecting to "sandbox" API. Thanks to Grails' flexibility it is plain simple. Go back to Config.groovy and add anything you with to environment blocks:
environments { production { grails.serverURL = "http://localhost:8080/${appName}" ebay.url = "http://open.api.ebay.com/" } staging { grails.serverURL = "http://localhost:8080/${appName}" ebay.url = "https://api.sandbox.ebay.com/" } development { grails.serverURL = "http://localhost:8080/${appName}" ebay.url = "https://api.sandbox.ebay.com/" } test { grails.serverURL = "http://localhost:8080/${appName}" ebay.url = "https://api.sandbox.ebay.com/" } }
You can access variables defined inside braces via ConfigurationHolder singleton:
ConfigurationHolder.config.ebay.url
Telling current configuration from code
You may want to show running environment name somewhere on page, to make sure application your testers are playing with is not connected to production ebay environment
Grails offers a way to obtain current running configuration:
Environment.getCurrent()
Environment is actually enum type and getCurrent() returns value for current configuration. There is one catch: this is enum, so it lists only factory-defined configurations: PRODUCTION, DEVELOPMENT, TEST, and for everything else: CUSTOM. Casting this enum to string will effectively return "CUSTOM" for all custom configuration. However, if you make call like this one:
Environment.getCurrent().getName()
You will find that getCurrent() method is smart enough to alter CUSTOM enum's name property and set it to right value.
This is why people love Grails: it is simple, yet flexible. Have fun!

Polski
English




