Wednesday, July 29, 2009

Grails: externalize configuration with jndi

Grails provides a very handy way to set configuration with Config.groovy file.

When developing internal applications, this solution is perfect especially with per-environment configuration.

For packaged third-party applications or complex multi-environment sites, it's harder to get a maintainable solution. Grails provides the grails.config.locations setting to load configuration from files possibly out of the application war file. The problem with this solution is to get a flexible cross-appserver cross-platform way to provide the custom config file to the application.


The solution presented here is to use jndi.

Let's say you want to provide a web service URL to an application, it will be made available to the application by the application server.

We will store the web service URL at the jndi name java:comp/env/wsUrl.

To access the value in the grails application, we will use a bit of spring magic by declaring a bean in grails-app/conf/spring/resources.groovy:

beans = {
wsUrl(org.springframework.jndi.JndiObjectFactoryBean){
jndiName = 'java:comp/env/wsUrl'
}
}


This will make the bean available with the value read from jndi, to use it, simply declare a variable named wsUrl in an injected object (controller, service...):
def wsUrl


For the development environment, if you use jetty, the value can be set by creating the web-app/WEB-INF/jetty-env.xml file with the following content:
<?xml version="1.0" encoding="UTF-8"?>
<configure class="org.mortbay.jetty.webapp.WebAppContext">
<new id="wsUrl" class="org.mortbay.jetty.plus.naming.EnvEntry">
<arg>wsUrl</arg>
<arg>http://www.example.com/dev-ws/</arg>
<arg type="boolean">true</arg>
</new>
</configure>



If you deploy to a tomcat environment, you can set the value by creating a file conf/Catalina/localhost/<context-name>.xml in your tomcat installation containing:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Environment name="wsUrl" value="http://www.example.com/prod-ws/"
type="java.lang.String" override="true"/>
</Context>

If the parameter has to be set in multiple applications in the same tomcat instance, it can be declared in conf/server.xml file and referenced in each application .xml file with the ResourceLink tag.

2 comments:

  1. Hi,

    your post has helped me a lot with a configuration I need. Now I have to use a jndi variable in the Config.groovy, but it does not seem to work. Do you know if there is any problem to use the variable configured with a jndi value in this Config.groovy? My datasource works, but this environment variable is always null.

    Any idea? I will keep on searching and post the solution if I get it.

    Thanks in advance.

    Regards

    ReplyDelete
  2. Same issue for me... I am unable to access the bean value from the Config.groovy

    ReplyDelete