How to Deploy a Grails Application to JBoss 5

As outlined at Grails – How to Use Native Server Logging Configuration (e.g. Tomcat GlassFish JBoss), it may be advisable to remove any conflicting logging implementation when deploying a Grails application into a production environment. I’ll give a full source example on how to achieve this and how to work-around an issue which prevents a Grails 1.2.0 and 1.2.1 applications from starting.

Unfortunately, each server provides a distinct set of logging frameworks. Still worse, servers can be reconfigured to use alternate logging frameworks (e.g. JBoss can be configured to use Java Logging instead of its default Log4J implementation and Tomcat 6 can be configured to use Log4J instead of its default Java Logging implementation).

Thus you either have to prepare a war which has been set-up for a specific target environment or completely remove any logging implementation from your Grails war and add missing jars to the lib directory of your target server instead. Which one to choose may depend on whether access to the server configuration is permitted (e.g. its lib directory), how many different servers your application is to be deployed to and how hard it is for your build process to reliably produce variants specifically tailored for a particular deployment site.

Before presenting the code for a deployment to JBoss 5.1.0GA, let’s have a look at Grails’ logging architecture. In its infancy Grails just used Apache Commons Logging (JCL) to provide an abstraction level and Log4J to implement the actual logging. Although even now, all log instances injected into Grails applications still implement org.appache.commons.logging.Log, Grails no longer uses JCL, but meanwhile has moved on to SLF4J:

Grails logging architecture

Starting with Grails 1.2, an additional bridge jul-to-slf4j which delegates Java Logging (Jul) to Slf4j is enabled by setting grails.logging.jul.usebridge = true. Be warned though, that for performance reasons this bridge should not be used when expecting heavy logging.

Now for the good news: With JBoss 5, all of the above (but excluding jul-to-slf4j) has already been integrated into the server configuration and libraries. In order to deploy a Grails application to JBoss 5, we’ll just need to get rid of the jars within your war and prevent Grails from trying to configure the logging. How to achieve this?

Within grails-app/conf/BuildConfig.groovy we’ll remove offending jars when building the war:

// TODO JBOSS - Remove own log4j and use the one supplied by JBoss instead
grails.war.resources = {stagingDir ->
    def toRemove = [
          "$stagingDir/WEB-INF/lib/log4j-1.2.14.jar", // log4j supplied by JBoss
          "$stagingDir/WEB-INF/lib/log4j-1.2.15.jar", // log4j supplied by JBoss
          "$stagingDir/WEB-INF/classes/log4j.properties", // logging conf done in JBoss only
          "$stagingDir/WEB-INF/lib/slf4j-api-1.5.6.jar", // slf4j supplied by JBoss 5+
          "$stagingDir/WEB-INF/lib/slf4j-api-1.5.8.jar", // slf4j supplied by JBoss 5+
          "$stagingDir/WEB-INF/lib/slf4j-log4j12-1.5.6.jar", // slf4j supplied by JBoss 5+
          "$stagingDir/WEB-INF/lib/slf4j-log4j12-1.5.8.jar", // slf4j supplied by JBoss 5+
          "$stagingDir/WEB-INF/lib/jcl-over-slf4j-1.5.6.jar", // jcl supplied by JBoss as well
          "$stagingDir/WEB-INF/lib/jcl-over-slf4j-1.5.8.jar", // jcl supplied by JBoss as well
        // see also Config.grails.logging.jul.usebridge - shouldn't be used
        //     http://www.slf4j.org/legacy.html#jul-to-slf4j
        //          "$stagingDir/WEB-INF/lib/jul-to-slf4j-1.5.6.jar",
        //          "$stagingDir/WEB-INF/lib/jul-to-slf4j-1.5.8.jar",
        // you might want to remove JDBC drivers when using server supplied JNDI...
        //          "$stagingDir/WEB-INF/lib/hsqldb-1.8.0.5.jar",
    ].each {
        delete(file: it)
    }
}

Within scripts/_Events.groovy we’ll disable Grails logging configuration components:

import groovy.xml.StreamingMarkupBuilder

/**
 * TODO JBOSS - Remove log4j configuration stuff (when running with JBoss or GlassFish a.s.o)
 */
eventWebXmlEnd = {String tmpfile ->

    def root = new XmlSlurper().parse(webXmlFile)

    // When running with JBoss (or GlassFish a.s.o) remove log4j configuration stuff
    def log4j = root.listener.findAll {node ->
        node.'listener-class'.text() == 'org.codehaus.groovy.grails.web.util.Log4jConfigListener'
    }
    log4j.replaceNode {}

    def log4jFile = root.'context-param'.findAll {node ->
        node.'param-name'.text() == 'log4jConfigLocation'
    }
    log4jFile.replaceNode {}

    webXmlFile.text = new StreamingMarkupBuilder().bind {
        mkp.declareNamespace("": "http://java.sun.com/xml/ns/j2ee")
        mkp.yield(root)
    }
}

You are now set to control logging within JBoss jboss-log4j.xml.

If you’re using Grails 1.2.0 or 1.2.1, JBoss still refuses to deploy your war. This is caused by version conflicts within Hibernate jars (used to be work-arounded by deleting all Hibernate jars from JBoss lib directory) and they have been fixed by GRAILS-5606 for (not yet released) Grails 1.2.2.

Graeme Rocher as well supplies a work-around for 1.2.x:

Fixed in latest hibernate plugin 1.3.0.BUILD-SNAPSHOT

It seems in order to use the latest version of Hibernate on JBoss you must include Hibernate validator otherwise you run into this classloading error. This means the hibernate plugin is forced to include hibernate-validator as a dependency even if we don’t use it which is a pretty annoying.

Anyway you can fix this yourselves in 1.2.x by adding the following dependency to BuildConfig.groovy:

runtime('org.hibernate:hibernate-validator:3.1.0.GA') {
    excludes 'sl4j-api', 'hibernate.core',
             'hibernate-commons-annotations', 'hibernate-entitymanager'
    }

Be sure to uncomment the jboss maven repository so the dependency resolvers

This work-around is included within sample sources. Just search for TODO tags.

Links:

About Reiner

Born 1954 in Ratisbon (Bavaria, Germany), in 1976 punched cards at Berlin Technical University, caught hacking one of its mainframes by Horst Zuse (son of Konrad Zuse), started studying computer science and soon was offered a job whithin their computer department doing systems programming for IBM VM/370. While studying, jobbed around Germany at various places doing all sorts of things, then returned to Berlin to work at SRZ (computer aided typesetting). Never finished my master degree, but chose to take up self-employed work (which didn't turn me rich nor famous). Now working for a mid-sized software company within a very promising department as head of server software development.
This entry was posted in English, Grails. Bookmark the permalink.

6 Responses to How to Deploy a Grails Application to JBoss 5

  1. Benjamin Armbruster says:

    Thanks a lot for your post. That greatly helped!
    I disabled grails logging configuration using the DSL and used our own log4j.properties to configure Log4j.
    This has been achieved by implementing my own org.codehaus.groovy.grails.web.util.Log4jConfigListener that behaves slightly different.

    Maybe you can add the xml-Namespace addition that has been added in

    http://stackoverflow.com/questions/11731730/how-do-disable-log4j-plugin-in-grails

    I also used
    XmlUtil.serialize(new StreamingMarkupBuilder().bind { … })
    to make the web.xml prettier. Not sure if that influences the output of the web.xml.

  2. web design company says:

    Pretty portion of content. I just stumbled
    upon your website and in accession capital to say that
    I acquire actually enjoyed account your blog posts.
    Anyway I’ll be subscribing on your augment and even I fulfillment you get
    admission to consistently fast.

  3. NBA 2K15 says:

    Pretty! This was an extremely wonderful article.

    Thanks for providing these details.

  4. seo services says:

    You should be a part of a contest for one of the highest
    quality sites on the internet. I most certainly will highly recommend
    this site!

  5. better business says:

    I don’t know if it’s just me or if perhaps everyone else experiencing issues with your site.
    It seems like some of the text on your posts are
    running off the screen. Can somebody else please provide feedback and let me know if
    this is happening to them too? This might be a issue with my web browser because I’ve had this happen previously.
    Kudos

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