Friday, December 13, 2013

Retrieving external config properties from JNDI, environment shell, and/or system properties.

I need to deploy multiple instances of the same WAR in a single Tomcat instance. I've been reading external config properties from System properties (e.g. System.getProperty('ext.xyz')). That won't work when deploying multiple WAR instances. So I whipped this up to read from JNDI as well as System properties (and I threw in reading from environment vars as well).

import javax.naming.Context
import javax.naming.InitialContext
import javax.naming.NamingException
class ExtConfig {
public ExtConfig() {
}
public String find(String key) {
String path = findJndiEnvVar(key)
if(!path) {
path = System.getenv(key)
if(!path) {
path = System.getProperty(key)
}
}
return path
}
private String findJndiEnvVar(String key) {
try {
def ctx = (Context) new InitialContext().lookup('java:comp/env')
return ctx.lookup(key)
}
catch(NamingException e) {
// not found, carry on
return null
}
}
}
Then in Config.groovy, I use it thus...

def extConfigPath = new ExtConfig().find('pathToExtFile')
if(extConfigPath) {
external.file = new File(extConfigPath)
if(external.file.exists()) {
println "Loading external config at ${external.file.path}"
grails.config.locations = [ "file:${external.file.path}" ]
}
else {
println "External config defined at ${extConfigPath} doesn't exist (huh?)"
}
}
else {
println "No external config found"
}
view raw gistfile1.txt hosted with ❤ by GitHub
This way my config file doesn't care where the external property comes from. In dev, I can define it as a system property. In prod, I can define it as a JNDI env var.
For completeness, here's how I'm defining the context xml in Tomcat.

<Context>
<Environment name="pathToExtFile" value="/path/to/external/file" type="java.lang.String" />
</Context>
view raw myWebApp.xml hosted with ❤ by GitHub