alexcuesta

My tech blog

Grails 1.3.6 & JNDI on Tomcat

with 3 comments

We’ve been struggling for a couple of days to configure grails to pick up JNDI resources using the embedded tomcat plugin (run-app). After some googling I found an article which solved my problem. At least for now. You will find the link to the article at the end of this post. For completeness, I’ve added a few comments in this blog post + the steps for how to get this working.

Before we start. Some notes about Tomcat and JNDI.

Tomcat support a number of different JNDI resource types (normally configured in Tomcat’s context xml file).

These are:

<Environment>
<Resource>
<ResourceLink>
<Transaction>

On a side note, also Jetty support at least the first three resource types but additional configuration is needed which is beyond the scope of this post.

The <Environment> type is mainly used to configure environmental properties within an application while <Resource> and <ResourceLink> types link to external resources such as JDBC, JMS or LDAP. I won’t elaborate on <Transaction> since I’m unfamiliar with this type.

When it comes to configuring the embedded tomcat plugin (1.2-M2) with JNDI it took a little while to get this right.

If you are only using <Resource> types you won’t have any problems \:) The problem you will encounter is with applications using the <Environment> type. As of version 1.2-M2 the tomcat plugin doesn’t support <Environment> JNDI types. On the other hand, the Jetty plugin support both of them. The very quick solution is to switch to Jetty obviously. Hopefully next version of the tomcat plugin will have better JNDI support. In the meantime we have to fall back on the following hack.

There is an easy way to get the Tomcat plugin to accept other types of JNDI resources and this is what the following article is about [http://6by9.wordpress.com/2010/12/10/grails-1-3-5-tomcat-plugin-and-jndi-environment-variables/]

I’ve also provided the steps here but please read the article before following the steps below.

Do the following:

  • Locate the following file TomcatServer.groovy. Mine was located under:C:\Documents and Settings\alejandro.cuesta\.grails\1.3.6\projects\trace\plugins\tomcat-1.3.6\src\groovy\org\grails\tomcat
  • Replace the private preStart() method with the following methods

private preStart() {
  eventListener?.event("ConfigureTomcat", [tomcat])
  def jndiEntries = grailsConfig?.grails?.naming?.entries

  if(jndiEntries instanceof Map) {
    def envs = jndiEntries.remove('environments')
    if (envs instanceof Map) {
      envs.each { name, cfg ->
        if (cfg) {
          addEnvironment(name, cfg)
        }
      }
    }
    def ress = jndiEntries.remove('resources')
    if (ress instanceof Map) {
      ress.each { name, cfg ->
        if (cfg) {
          addResource(name, cfg)
        }
      }
    }
    jndiEntries.each { name, cfg ->
      if(cfg) {
        addResource(name, cfg)
      }
    }
  }
}

private addEnvironment(name, envCfg) {
  if (!envCfg["type"]) {
    throw new IllegalArgumentException("Must supply a environment type for JNDI configuration")
  }
  def env = loadInstance('org.apache.catalina.deploy.ContextEnvironment')
  env.name = name
  env.type = envCfg.type
  env.description = envCfg.description
  env.override = envCfg.override as boolean
  env.value = envCfg.value

  context.namingResources.addEnvironment env
}

private addResource(name, resCfg) {
  if (!resCfg["type"]) {
    throw new IllegalArgumentException("Must supply a resource type for JNDI configuration")
  }
  def res = loadInstance('org.apache.catalina.deploy.ContextResource')
  res.name = name
  res.auth = resCfg.remove("auth")
  res.scope = resCfg.remove("scope")
  res.type = resCfg.remove("type")
  res.description = resCfg.remove("description")
  // now it's only the custom properties left in the Map...
  resCfg.each {key, value ->
    res.setProperty (key, value)
  }

  context.namingResources.addResource res
}
  • The tomcat plugin has now been configured to also read environment resource types
  • You should now be able to define your resources in Config.groovy. Such as
grails.naming.entries = [

  "resources" : [

    "jms/bananas": [
      type: "org.apache.activemq.command.ActiveMQTopic",
      description: "Fruit salad",
      factory: "org.apache.activemq.jndi.JNDIReferenceFactory",
      physicalName: "bananas"
    ]
  ],

  "environments" : [
    "/app/config/db.mysql.username": [
      type: "java.lang.String",
      value: "MYUSERNAME",
      override: "true"
    ],

    "/app/config/db.mysql.password": [
      type: "java.lang.String",
      value: "MYPASSWORD",
      override: "true"
    ]
  ]

]

Written by alexcuesta

February 12, 2011 at 6:54 pm

Posted in Groovy/Grails

3 Responses

Subscribe to comments with RSS.

  1. Hi Alex!
    Thank you so much.
    This is exactly what we need!
    This is such basic requirement, it weird that the plugin doesn’t support Environments.
    Let’s hope they add support soon.

    Emilio Trussardi

    April 13, 2011 at 11:27 am

    • You are welcome Emilio!

      alexcuesta

      April 13, 2011 at 12:30 pm

  2. So now that we have Environment entries being added to the context, how do we retrieve them in grails code? I’m setting LDAP server info in the tomcat context using Environment, and need to be able to use those settings inside Grails.

    Bud Byrd (@BudByrd)

    May 10, 2012 at 9:20 pm


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: