Sunday, November 28, 2010

How to Deploy a grails 1.3.5 webapp to JBoss 5.1.0.GA

There are a few problems that prevent grails deploying to the JBoss application server. I will describe specifically how to deploy a grails 1.3.5 web application to the JBoss 5.1.0.GA Applicaton Server community edition.

A bug has been filed on the grails Jira server describing the problem. Please create a Jira account and vote for this issue so that it may get more attention. The issue is Grails-6953.


The first issue is that newer versions of hibernate require hibernate validator even though grails doesn't need it. This is Jira issue Grails-5606 and says that it was fixed in grails 1.2.2 but wasn't.

In the text of Grails-5606 there was a work around described by Graeme Rocher that solves the issue. The work around is:

In BuildConfig.groovy:
  1. Uncomment the JBoss maven repository
  2. Add the hibernate-validator dependency
runtime('org.hibernate:hibernate-validator:3.1.0.GA') {
excludes 'slf4j-api', 'hibernate.core', 'hibernate-comnmons-annotations', 'hibernate-entitymanager'
}


The second issue is that grails includes logging libraries that JBoss already includes. JBoss complains about this. There is a good post covering that issue here. The logging libraries can be removed from the grails war file by adding the following to the end of the BuildConfig.groovy file:

// Remove logging artifacts from war
grails.war.resources = { stagingDir ->
def toRemove = [
"$stagingDir/WEB-INF/lib/log4j-1.2.16.jar",
"$stagingDir/WEB-INF/lib/commons-logging.jar",
"$stagingDir/WEB-INF/lib/commons-logging-1.1.jar",
"$stagingDir/WEB-INF/lib/jcl-over-slf4j-1.5.8.jar",
"$stagingDir/WEB-INF/lib/slf4j-api-1.5.8.jar",
"$stagingDir/WEB-INF/lib/slf4j-log4j12-1.5.8.jar"
].each {
delete(file: it)
}
}


The third issue has to do with how grails creates the filename of the war. Grails constructs the war filename based on properties defined in application.properties. The war filename is app.name-app.version.war. When deploying the grails web application to an environment for testing, we may not want to access the application like:

http://mysite.com/myapp-0.1/

To get around this issue, we can create a jboss-web.xml file in the web-app/WEB-INF folder. The contents of the jboss-web.xml file are:

<jboss-web>
<context-root>/wis</context-root>
</jboss-web>

5 comments:

  1. I think a better solution for number two would be to update BuildConfig.groovy:

    grails.project.dependency.resolution = {
    inherits("global") {
    excludes 'log4j', 'jcl-over-slf4j', 'slf4j-api', 'slf4j-log4j12'
    }

    dependencies {
    provided 'org.slf4j:slf4j-api:1.5.8', ...
    }
    }

    Note that both this approach and the one you suggest in the article will break the 'grails run-war' command, so you may want to put the custom code inside conditions based on the environment.

    On the third issue, you can always pass the path and name of the WAR file as an argument to the 'grails war' command, or you can set it in BuildConfig.groovy:

    grails.project.war.file = "target/wis.war"

    ReplyDelete
  2. Thanks for improved solution for number two. Is there a good place to find BuildConfig documentation? GiA (great book BTW) has some info, but for example I'm looking for more details on provided as you mentioned above.

    Thanks for pointing out the gotcha in number three. I usually develop in my IDE, so I never noticed the run-war issue (though still good to be aware of). At first I didn't like the version numbers in the war filename, but we found it helpful when moving different builds through dev and testing.

    ReplyDelete
  3. The information is lurking in section 3 of the user guide, although only in that it explains what the provided option means.

    That section also describes the relatively new defaultDependenciesProvided option.

    ReplyDelete
  4. Thanks for sharing this function. I really need to understand this function and this page is very useful for me to learn this functionality.
    Web Application Development

    ReplyDelete