Grails Config Values Per Tomcat Host

An example of using JNDI to provide a Grails application config values per Tomcat Host..

Object Partners

Sometimes in a Grails application it is necessary to have configuration values available at the Tomcat Host level. An example of such a situation would be needing multiple Hosts in a single Tomcat instance all using the same version of a war. Each war is essentially a copy that contains generic application code that relies on external configuration values to configure its own database, Host-specific labels, integration configuration, etc. For example, you could have 3 Hosts - check here for details on specific configuration of Tomcat Hosts:

// Clip of server.xml file with multiple hosts that need
// environment variables for Grails to pull in.

<Host name="foo1.com" appBase="foo1" ...>
    ...
</Host>
<Host name="foo2.com" appBase="foo2" ...>
    ...
</Host>
<Host name="foo3.com" appBase="foo3" ...>
    ...
</Host>

Each Host’s application will need its own external configuration files, which is a problem since the wars are identical copies. The traditional use of external configuration in bootstrap.groovy would end in each Host using the same files and being configured for the same Host:

// This usual method of external configuration won't work since
// each Host will point to the same applicationConfig file

grails.config.locations = [ "file:/path/to/applicationConfig.groovy"]

We need a way to provide the application with variables pointing to the correct configuration files on a per Host basis. We can solve this with JNDI by configuring a Tomcat Context for each Host. Each Context will contain an Environment variable containing the location of the correct configuration file. In the {Tomcat}/conf/Catalina/{Host} directory, create an xml file for each Host (I’ll call it context.xml) containing:

// Example of a Context configuration

<Context>
  <Environment name="grailsExtConfFile" value="file:/path/to/foo1/applicationConfig.groovy" type="java.lang.String"/>
</Context>

The “grailsExtConfFile” Environment variable will be available to your application, so you just have to look it up and use it in Config.groovy:

...
try {
  exConfig = ((Context)(new InitialContext().lookup("java:comp/env"))).lookup("grailsExtConfFile")
} catch (Exception e) {
  println("External configuration lookup failed: " + e)
}

grails.config.locations = ["${exConfig}"]

Your application is now ready to deploy and run as multiple Hosts on one Tomcat instance. But how do you run locally while developing and testing? The easiest way is by detecting the environment and providing external configuration files more traditionally if Environment.DEVELOPMENT or Environment.TEST:

...
if (Environment.current in [Environment.DEVELOPMENT, Environment.TEST]) {
  exConfig = "file:/path/to/local/applicationConfig.groovy"
} else {
  try {
    exConfig = ((Context)(new InitialContext().lookup("java:comp/env"))).lookup("grailsExtConfFile")
    ...

Share this Post

Related Blog Posts

JVM

Guicing up Dropwizard

November 19th, 2013

Implement dependency injection in Dropwizard with Google Guice.

Object Partners
JVM

Parallel Grails Functional Tests with Geb and Gradle

November 14th, 2013

Speed up your Grails functional tests by running them in parallel with Gradle

Object Partners
JVM

Set up a pseudo test suite in Grails while doing a major upgrade

November 12th, 2013

Describes a technique for setting up a temporary test suite while upgrading a Grails application.

Object Partners

About the author