JBoss Deployment Gotchas

The other day I was attempting to deploy a web app in JBoss (5.1) that had deployed just fine in Tomcat. In JBoss I kept seeing the following error:

java.lang.ClassCastException: org.hibernate.ejb.HibernatePersistence cannot be cast to javax.persistence.spi.PersistenceProvider

It turns out that the problem was because JBoss was first loading its own Hibernate classes. When my application started to deploy there was a Hibernate jar conflict (my Hibernate version was newer than that which JBoss shipped with).

To solve this problem is is necessary to direct JBoss to load class files for the application first. To achieve this, create the following jboss-classloading.xml file in WEB-INF:

<classloading xmlns="urn:jboss:classloading:1.0"

I had been testing my application using Tomcat 6.x, and, knowing that JBoss uses Tomcat as its web container, I assumed there would be no problems when deploying to JBoss. I never saw this issue in Tomcat because it does not package its own Hibernate jars.

With that issue resolved, I was still perplexed as to why my application would not launch. In my JBoss server log files I continued to get errors the the deployment of my application would not complete. This is hardly a new issue to those with JBoss experience (I found this post from 2003) The problem, it turns out, was that my application included a newer version of xalan.jar than that which JBoss ships with. This problem is similar to the Hibernate issue above, however, it cannot be resolved in the same way, since the xalan classes are used during JBoss’s initial deployment of the web application (i.e., it relies on the xalan jar file prior to reading jboss-classloading.xml).

To resolve this issue I decided that it would be easiest to simply making a separate distribution for my JBoss deployment. I would like to be able to deploy on Glassfish, Jetty, Tomcat and JBoss, but since JBoss has this conflict, one solution is to make a build target similar to this (I am using ant):

<target name="jboss-dist" depends="compile">
 <war destfile="jboss-dist/MyProject.war">
   <fileset dir="WebContent">
     <exclude name="**/xalan*"/>
   <classes dir="build/classes"/>

Now I have a JBoss deployment which does not include xalan–and it deploys without error!