Demystifying the JBoss5 jboss-classloading.xml file

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..

  • ..EAR, place it in the META-INF of the ear, e.g. myapp.ear/META-INF/jboss-classloading.xml
  • ..WAR, place it in the WEB-INF of the war, e.g. myapp.war/WEB-INF/jboss-classloading.xml
  • ..JAR, place it in the META-INF of the jar, e.g. mylib.jar/META-INF/jboss-classloading.xml  (I’ve not personally tried this but you can find info on this in JBoss forums)

What are all the attributes and what do they mean?

  • name – typically the name of war or ear, e.g. “myapp.war”
  • import-all – (“true”/”false”) – true means make all classes exported from other applications visible to this application
  • export-all – value “NON_EMPTY” – all classes are exposed to other applications
  • domain – a classloading domain, can be an arbitrary name but typically you will want to name it the name of your application, e.g. “myapp.ear” or “myapp.war”. If a domain by that name already exists, your app will join that classloading domain.
  • parent-domain – default is “DefaultDomain” which is shared with all other applications that don’t specify a domain.  If you prefer to delegate to an explicit parent domain when a class is not found in yours, then specify an existing domain here, as in delegating to an EAR’s domain, e.g. “myapp.ear”
  • top-level-classloader – used to enable embedded apps, such as a war within an EAR, to participate in a top-level domain (see JBCL-125)
  • parent-first (“true”/”false”) – if false, the app is in non-j2ee compliance mode, where the app’s domain is searched first for a class before searching the parent domain.  The default for top-level deployed WARs is “false”, however, I have found that the default behavior for WARs within EARs is “true”

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:

<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:

<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

/phyto

About phytodata

Lead software engineer with broad experience over 13 years designing and writing Java based open source and commercially licensed applications ranging from healthcare to banking to business intelligence and telecom.
This entry was posted in Uncategorized and tagged , , , , , , , , , , , . Bookmark the permalink.

30 Responses to Demystifying the JBoss5 jboss-classloading.xml file

  1. Slawo says:

    Hi phyto,

    your first blog entry is already on advanced (and mind boggling) stuff. Can’t wait for the follow up 🙂

    Cheers

    Slawo

  2. phytodata says:

    Thanks Slawo, I’ll try to not disappoint 🙂

    • Shravani says:

      Hi , I’m trying to deploy an app in which the packaging is EAR and SAR (Scheduler)
      SAR is not in the EAR. Could you please help me in how to configure the jboss-classloading.xml files? I have defined one in ear/META-INF and the other in SAR folder/META-INF (SAR folder has META-INF folder and it’s app specific jar). Sar is not deployed – complains that classes from EAR are not found.

      • Dublinario says:

        A year late on this one, but I’m wondering if you ever got to the bottom of this issue Shravani? I have a SAR, and would like that SAR to be able to access the classpath of the overall profile (e.g. the deploy folder, the conf folder etc). I also have a requirement for the solution to be generic, and not refer to the profile name, because I want the SAR to be something that can be dropped into JBOSS_HOME/server//deploy and perform a generic utility duty.

        Any help, much appreciated.

  3. alesj says:

    Hey, nice post!

    I hope you come to our forums next time,
    for such issues, so it’s not so painful. 😉
    I tend to answer mostly everything that drops into our MC forum.
    (or did I miss your post? — the notification has been broken lately :-()

    Could you somehow push this post to our wiki,
    or at least link it somehow?

    Cheers, Ales

  4. phytodata says:

    Thanks Ales! I’ll be sure to do that next time 😉 .. and I have added this post to the JBoss MicroKernel FAQ

  5. phytodata says:

    Another tip I’ve found, to debug classloading problems, turn on trace logging in server/default/conf/jboss-log4j.xml:

    <category name="org.jboss.classloader.spi.base">
          <priority value="TRACE"/>
    </category>
    
  6. Adauto says:

    Hey man! You saved my day! Thanks a lot for your help!
    Huges,
    Adauto from Brazil! 🙂

  7. phytodata says:

    No problem, I’m glad it was useful 🙂

  8. Andrew Swan says:

    Thanks for this post, it helped me a lot! Some follow-on questions if you have time please:

    1. In the WAR file’s jboss-classloading.xml file, why can’t you simply tell the WAR file to be in the same CL domain as the EAR file?

    2. How can you stop the EAR file from loading *any* classes from JBoss’ lib folders?

    FYI, for those using JBoss 6, logging is now configured by server/[xxx]/deploy/jboss-logging.xml.

  9. phytodata says:

    @Andrew – regarding your first point, I don’t recall if i tried that approach, it’s definitely worth a try. To your second point, if you see my paragraph starting “One funny side-effect…”, you’ll notice that I did in fact see behavior in which JBoss’s libraries seemed to be completely ignored. Perhaps that will do what you want (import-all=”false”). Thanks for the update on the logging configuration for JBoss6
    Cheers!

  10. Jinglebell says:

    Hi Phyto,

    I followed your suggestion setup jboss-classloading.xml in war and ear, when I deployed my app to JBoss 5, the conflicts with Hibernate jar contained in JBoss is gone, however, there was still issues with myfaces jars.

    After some researches, I added the below context-param in the web.xml file to eliminate myfaces conflicts.

    org.jboss.jbossfaces.WAR_BUNDLES_JSF_IMPL
    true

    Now I deploy my app again, I get ClassCastException for javax.servlet.* e.g. javax.servlet.Filter and javax.servlet.Servlet. So it looks like it still have conflicts with servlet-api.jar in common/lib in JBoss. Also tried to set import-all = false. but it didn’t make any difference. Can you please advise? (I used the same approach for war on its own and I reach the same issue). Thanks in advance.

    There is my class loading files for ear which contains war:
    in the ear/META-INF:

    in the war/WEB-INF:

    The below is my class loading file for war on its own: (tried with or without top-level-classloader attribute)

  11. Jinglebell says:

    There is my class loading files for ear which contains war:
    in the ear/META-INF:
    <classloading xmlns=”urn:jboss:classloading:1.0″
    domain=”my-app.ear”
    export-all=”NON_EMPTY”
    import-all=”true”
    parent-first=”false”>
    </classloading>

    in the war/WEB-INF:
    <classloading xmlns=”urn:jboss:classloading:1.0″
    domain=”my-web.war”
    parent-domain=”my-app.ear”
    export-all=”NON_EMPTY”
    import-all=”true”
    parent-first=”false”>
    </classloading>
    The below is my class loading file for war on its own: (tried with or without top-level-classloader attribute)
    <classloading xmlns=”urn:jboss:classloading:1.0″
    domain=”my-web.war”
    parent-domain=”DefaultDomain”
    export-all=”NON_EMPTY”
    import-all=”true”
    parent-first=”false”
    top-level-classloader=”true”>
    </classloading>

  12. Senthil Jayakumar says:

    Hi,
    Recently we have migrated from JBOSS 4.0.3SP1 to 5.1.0GA, after this migration we are facing tricky
    classloading issue, whereas the same was working fine in the earlier JBOSS version (4.0.3SP1).
    This application exposes SOAP services (using AXIS 1.2.1) to the third party applications.
    Below is how my application structure looks like:
    sampleapplication.ear
    |
    – myEjb.jar
    – others.jar
    – myProvisioningImpl.jar – this jar contains one class file (MyTestClass.class) which is used in myWebApp.war also.
    – META-INF
    |
    – application.xml
    – jboss-app.xml
    – myWebApp.war
    |
    – provisioning
    |
    – deploy.wsdd
    – undeploy.wsdd
    – WEB-INF
    |
    – jboss-classloading.xml
    – web.xml
    – context.xml
    – lib
    |
    – axis.jar
    – saaj.jar
    – wsdl4j.jar
    – jaxrpc.jar
    – myFiles.jar – this jar also contains MyTestClass.class.

    The issue is MyTestClass.class file is very much required in both the jar files i.e.
    one part of EAR and other part of WAR file, now when I invoke a method from WAR to EAR by passing in
    the MyTestClass as an argument to the method, I am getting
    java.lang.LinkageError: loader constraint violation: when resolving method.

    The reason for the LinkageError being classloaders having the same the class file MyTestClass.class.
    How do I get around the issue, i.e. retaining the files as it is in corresponding jars and
    tweaking the classloading if possible.

    Any help is greatly appreciated.

    Attaching logs for reference:
    In working system, JBOSS 4.0.3SP1 :-
    server.log.4:2011-04-09 21:43:12,056 TRACE [org.jboss.mx.loading.RepositoryClassLoader] getResourceLocally(org.jboss.mx.loading.UnifiedClassLoader3@1200435{ url=file:/export/home/jboss/server/insight/deploy/sampleapplication.ear/ ,addedOrder=180}), name=com/networks/ems/lawfulintercept/webservice/model/MyTestClass.class, resURL:jar:file:/export/home/jboss/server/insight/tmp/deploy/tmp231834378526396546myProvisioningImpl.jar/com/networks/ems/lawfulintercept/webservice/model/MyTestClass.class
    server.log.4:2011-04-09 21:43:12,057 TRACE [org.jboss.mx.loading.RepositoryClassLoader] getResourceLocally(org.jboss.mx.loading.UnifiedClassLoader3@17a36e1{ url=null ,addedOrder=0}), name=com/networks/ems/lawfulintercept/webservice/model/MyTestClass.class, resURL:null
    server.log.4:2011-04-09 21:43:12,085 TRACE [org.jboss.mx.loading.RepositoryClassLoader] loadClassLocally, org.jboss.mx.loading.UnifiedClassLoader3@1200435{ url=file:/export/home/jboss/server/insight/deploy/sampleapplication.ear/ ,addedOrder=180} name=com.networks.ems.lawfulintercept.webservice.model.MyTestClass class=class com.networks.ems.lawfulintercept.webservice.model.MyTestClass cl=org.jboss.mx.loading.UnifiedClassLoader3@1200435{ url=file:/export/home/jboss/server/insight/deploy/sampleapplication.ear/ ,addedOrder=180}
    server.log.4:2011-04-09 21:43:12,086 TRACE [org.jboss.mx.loading.RepositoryClassLoader] loadClass org.jboss.mx.loading.UnifiedClassLoader3@1200435{ url=file:/export/home/jboss/server/insight/deploy/sampleapplication.ear/ ,addedOrder=180} name=com.networks.ems.lawfulintercept.webservice.model.MyTestClass class=class com.networks.ems.lawfulintercept.webservice.model.MyTestClass cl=org.jboss.mx.loading.UnifiedClassLoader3@1200435{ url=file:/export/home/jboss/server/insight/deploy/sampleapplication.ear/ ,addedOrder=180}

    Logs from non working system, JBOSS 5.1.0GA:-
    server_74.24.log(640919): 13:18:49,663 TRACE (http-0.0.0.0-80-3) [org.jboss.logging.Logger] ClassLoaderDomain@3b1e8b{vfsfile:/export/home/jboss/server/insight/deploy/sampleapplication.ear/myWebApp.war/} findLoader com/networks/ems/lawfulintercept/webservice/model/MyTestClass.class classLoader=BaseClassLoader@152441a{vfsfile:/export/home/jboss/server/insight/deploy/sampleapplication.ear/myWebApp.war/} allExports=false findInParent=false
    server_74.24.log(640921): 13:18:49,666 TRACE (http-0.0.0.0-80-3) [org.jboss.logging.Logger] ClassLoaderDomain@3b1e8b{vfsfile:/export/home/jboss/server/insight/deploy/sampleapplication.ear/myWebApp.war/} trying to load com/networks/ems/lawfulintercept/webservice/model/MyTestClass.class from all exports of package com.networks.ems.lawfulintercept.webservice.model [VFSClassLoaderPolicy@1f530ab{vfsfile:/export/home/jboss/server/insight/deploy/sampleapplication.ear/myWebApp.war/}]
    server_74.24.log(640923): 13:18:49,668 TRACE (http-0.0.0.0-80-3) [org.jboss.logging.Logger] BaseClassLoader@152441a{vfsfile:/export/home/jboss/server/insight/deploy/sampleapplication.ear/myWebApp.war/} get resource locally com/networks/ems/lawfulintercept/webservice/model/MyTestClass.class
    server_74.24.log(640925): 13:18:49,671 TRACE (http-0.0.0.0-80-3) [org.jboss.logging.Logger] BaseClassLoader@152441a{vfsfile:/export/home/jboss/server/insight/deploy/sampleapplication.ear/myWebApp.war/} got resource locally com/networks/ems/lawfulintercept/webservice/model/MyTestClass.class
    server_74.24.log(839888): 13:26:51,784 TRACE (http-0.0.0.0-80-5) [org.jboss.logging.Logger] ClassLoaderDomain@12b71a3{com.networks.ems:loader=liTargetProvisioning} findLoader com/networks/ems/lawfulintercept/webservice/model/MyTestClass.class classLoader=BaseClassLoader@131b732{vfsfile:/export/home/jboss/server/insight/deploy/sampleapplication.ear/} allExports=false findInParent=true
    server_74.24.log(839890): 13:26:51,788 TRACE (http-0.0.0.0-80-5) [org.jboss.logging.Logger] ClassLoaderDomain@12b71a3{com.networks.ems:loader=liTargetProvisioning} trying to load com/networks/ems/lawfulintercept/webservice/model/MyTestClass.class from all exports of package com.networks.ems.lawfulintercept.webservice.model [VFSClassLoaderPolicy@f250f3{vfsfile:/export/home/jboss/server/insight/deploy/sampleapplication.ear/}]
    server_74.24.log(839892): 13:26:51,791 TRACE (http-0.0.0.0-80-5) [org.jboss.logging.Logger] BaseClassLoader@131b732{vfsfile:/export/home/jboss/server/insight/deploy/sampleapplication.ear/} get resource locally com/networks/ems/lawfulintercept/webservice/model/MyTestClass.class
    server_74.24.log(839893): 13:26:51,794 TRACE (http-0.0.0.0-80-5) [org.jboss.logging.Logger] BaseClassLoader@131b732{vfsfile:/export/home/jboss/server/insight/deploy/sampleapplication.ear/} got resource locally com/networks/ems/lawfulintercept/webservice/model/MyTestClass.class

    Thanks
    Senthil Jayakumar

  13. Dipti says:

    Hi JingleBell,
    Did you resolve this issue? I’m having the same trouble with Jboss 6.

  14. Jinglebell says:

    Hi Dipi,
    No I dont have it fully resolved. what I have posted here, should correct, cos I have get some of my projects working with this config. but I suspect this isolation is only working if the conflicts jars are located in common/lib folder, if the conflicts jar in the your server instance deploy or deployers folder, this config will not be able to isolate them. Researched online, it seems to have to use what JBoss provides to us. But I am still trying to find if there is alternative for this area. BTW, I am working on JBoss 5.1.0. I think JBoss 6, there is jboss-domain.xml you can use, maybe you can try look into that.

  15. YogeshN says:

    nice post.thanks!

  16. Naveen says:

    Hi phyto,

    i am having a ear where i have a jar(ejb) and war files within it. i am able to deploy the ear when some of the lib are removed from the ear/lib. when i try to use the classloader in my ear i am getting some issue with SAXParser. Below is the classloader files. Can u let me know what am i doing wrong here?

    ear/META_INF/jboss-classloading.xml

    ear/myweb/WEB-INF/jboss-classloading.xml

    Thanks in advance,

    Cheers, Naveen.

  17. caowei says:

    This is definitely a nice post, thank for your efforts.

  18. Emran says:

    Very well-written post. Had helped me a lot.

  19. Pingback: Having fun with Jboss classloader – or how I figured out how to get my application to work in Jboss 5 | Huima

  20. Lynn Owens says:

    Thanks for the help, this blog was very instrumental in me figuring something out.

  21. Pingback: JBoss Class loading revisited | Miscellaneous musings in beta

  22. Drabkey says:

    Works!
    Thank you very much.

  23. Abhinav says:

    Hi,
    I am not sure if this is too late to ask. But I am using Jboss 5.1. I am trying to deploy my war file using above configuration that is defined in blog. However, it looks like it is not working. I am still getting errors reated to XercesImpl.jar etc etc. I am keeping the above configuration file in WEB-INF/.

    Please let me know if I am doing anything wrong here.

    Regards,
    Abhinav Singhal

  24. Rahul says:

    Nice very informative.

  25. Ben says:

    This post was exactly what I needed! Thanks!

  26. Pingback: Sonar 2.3 + Jboss 5.1 | Blog de BBVA GlobalNet

  27. Nice post. I was checking continuously this weblog and I am impressed!

    Very useful information specifically the last phase :
    ) I deal with such information a lot. I used to be looking for this certain information for a long time.
    Thank you and good luck.

  28. Spot on with this write-up, I actually think
    this web site needs a great deal more attention. I’ll probably be back again to see more, thanks for the advice!

Leave a reply to Ben Cancel reply