Islation of application - Classloading in JBoss5

Reference: 

http://phytodata.wordpress.com/2010/10/21/demystifying-the-jboss5-jboss-classloading-xml-file/

https://developer.jboss.org/wiki/useJBossWebClassLoaderinJBoss5

http://java.dzone.com/articles/jboss-microcontainer-classloading

Posted on October 21, 2010 by phytodata

I have recently been given the task of getting the Pentaho BIServer to deploy within JBoss5 AS.  Classloading has aparently been completely reworked in v5 vs v4 and prior.  The new way to customize classloading behavior is to write up a jboss-classloading.xml file and drop it in various spots within your application to be deployed.  After many hours of being frustrated reading blog and forum posts and not finding a single source of information on exactly what the jboss-classloading.xml is and does and where to put it, I figured I’d try to save someone else (and myself later after I forget this) the same pain I’ve experienced.  Below I answer some of the questions I had on my journey.

Where do I place a jboss-classloading.xml file?

To control classloading behavior of an..

What are all the attributes and what do they mean?

How do I deploy a WAR within an EAR in which the WAR can see all jars in the EAR, but the EAR’s classes trump JBoss’s?

The original problem I had was the Pentaho BIServer application uses a more recent version of commons-collections.jar, more recent than the one in JBoss’s own library.  When deploying the Pentaho WAR outside of an EAR, I did not have a problem since as of JBoss5, WARs are deployed with a classloading scheme that looks up classes within the WAR first, before delegating to the parent domain.  However, when I deployed the Pentaho EAR I saw the opposite, as if JBoss’s copy of commons-collections.jar was found first, not the EAR’s classes first.  I needed to override this behavior such that EAR classes are preferred over JBoss’s.   The situation I started with was a pentaho.war within a pentaho.ear and no jboss-classloading.xml files present.  As I mentioned earlier, once I deployed this, JBoss libs were preferred over mine.  So I had to go to work authoring some custom classloading.  Here’s what I wound up with:

Contents of jboss-classloading.xml in pentaho.ear/META_INF:

1

2

3

4

5

6

<classloading xmlns="urn:jboss:classloading:1.0" domain="pentaho.ear" export-all="NON_EMPTY" import-all="true" parent-first="false">

</classloading>

The important parts here: (1) we are specifing that the pentaho.ear application participate in it’s own domain “pentaho.ear”.  This is so in the embedded war, we can declare this domain as it’s parent. (2) by setting parent-first to false, we are essentially declaring that EARs classes be preferred over JBoss’s (in the DefaultDomain presumably).

One funny side-effect to mention here is that I was actually able to deploy an EAR in which javax.servlet.HttpServlet was not found during deployment.  Amazing that this is even possible, but it happened.   The jboss-classloading.xml file that made this happen included only a parent-first=”false” attribute, nothing else.  I haven’t eliminated the attrs one-by-one to find out which is responsible for this; I suspect perhaps import-all.

Contents of jboss-classloading.xml in pentaho.ear/pentaho.war/WEB-INF:

1

2

3

4

5

6

<classloading xmlns="urn:jboss:classloading:1.0" domain="pentaho.war" parent-domain="pentaho.ear" export-all="NON_EMPTY" import-all="true">

</classloading>

The most important bit here is the pentaho.war is in it’s own domain “pentaho.war”, but delegates to the EAR’s CL domain, “pentaho.ear”.  This enables the WAR to see classes within jars deployed at the EAR level.  The pentaho.war in the case of an EAR deployment has no libs in WEB-INF/lib, so it must rely on the EAR for jars.

Result? Once I dropped these files in, the app “just worked”.  My app found my commons-collections.jar and not JBoss’s.

FYI, the most helpful article on the subject I found during this effort was http://java.dzone.com/articles/jboss-microcontainer-classloading