6 Replies Latest reply on Nov 8, 2009 11:14 AM by jaikiran

    JBoss AS 5.1.0.GA Classloading Help

    garethwebbley

      I have an ear file containing 2 war files. I have structured the files so that common jars appear in the ear file root directory and jars that are specific to the individual war files are included in the appropriate war file. Each war file contains a MANIFEST.MF referencing the jars contained in the ear file that they need to use.

      I am using spring to configure a shared application context which is the parent of application contexts in the war files.

      I have run into a problem when trying to inject a bean from the shared context into a bean defined in war 2 if the same bean is injected into a bean defined in war 1. It appears that the class file is loaded by war 1's class loader rather than the ear classloader even though the file is from a jar in the ear file. I was expecting this class to be loaded by the class loader of the ear but instead it was loaded by the class loader of war 1. I can tell this by using the jmx-console classloader MBean and running the findClassLoaderForClass operation.

      I have spent some time googling for details of class loading in JBoss 5 but unfortunately the available resources are quite limited so I resorted to looking through the source code. I found references to the jboss-classloading.xml files so I have tried creating some of these files for my ear and war files but I am still having no luck. Here are my attempts :-

      In the EAR file -
      <classloading xmlns="urn:jboss:classloading:1.0"
      name="ptd-ear-1.0-SNAPSHOT.ear"
      domain="ptd-ear-1.0-SNAPSHOT.ear"
      export-all="NON_EMPTY"
      import-all="true"
      parent-first="false">


      In war file 1 -
      <classloading xmlns="urn:jboss:classloading:1.0"
      name="ptd-jsf-1.0-SNAPSHOT.war"
      domain="ptd-jsf-1.0-SNAPSHOT.war"
      parent-domain="ptd-ear-1.0-SNAPSHOT.ear"
      export-all="NON_EMPTY"
      import-all="true"
      parent-first="true">


      In war file 2 -
      <classloading xmlns="urn:jboss:classloading:1.0"
      name="ptd-ws-1.0-SNAPSHOT.war"
      domain="ptd-ws-1.0-SNAPSHOT.war"
      parent-domain="ptd-ear-1.0-SNAPSHOT.ear"
      export-all="NON_EMPTY"
      import-all="true"
      parent-first="true">


      I was expecting the fact that I have parent-first set to true in the war files to mean that the classes in jars in the ear file would be loaded by the ear class loader not the war class loader but this is not the case.

      I have done similar things in the websphere with no problems so I don't think my understanding is completely wrong.

      Can anyone help me achieve what I want in JBoss 5.1.0.GA?

      Thanks

        • 1. Re: JBoss AS 5.1.0.GA Classloading Help
          alesj

          I have mocked your test here -- see testEar2War:
          * http://anonsvn.jboss.org/repos/jbossas/projects/jboss-deployers/trunk/deployers-vfs/src/test/java/org/jboss/test/deployers/vfs/reflect/test/TypeInfoTest.java
          And it works as expected.

          If the common class is the only such class, then parent-first shouldn't actually be needed.

          • 2. Re: JBoss AS 5.1.0.GA Classloading Help
            alesj

             

            "garethwebbley" wrote:
            Each war file contains a MANIFEST.MF referencing the jars contained in the ear file that they need to use.

            What about if you remove this?
            Or what's the exact content of this manifest.mf files?

            • 3. Re: JBoss AS 5.1.0.GA Classloading Help
              garethwebbley

              Thanks for your responses.

              The manifest.mf files are automatically generated by maven and include a Class-Path: entry which references all the jar files which are in the ear file that are needed to satisfy dependencies from the the war file. If I don't include the Class-Path: entry then I get ClassNotFoundException/NoClassDefFoundErrors.

              I have had a look at your test case and a couple of things have sprung to mind. I am including my jar files in the root of the EAR file (not in a lib directory) would this make any difference? Also I am referencing the jar files in the application.xml as java modules - do I still need to do this?

              Thanks again

              • 4. Re: JBoss AS 5.1.0.GA Classloading Help
                garethwebbley

                I have created a small set of test projects to illustrate the problem. I get slightly different results to my main projects but still not the results that I expect.

                In my example projects the war files contain only one class each and no jar files. All the supporting jar files are in the ear file. I would expect the war classloaders to only load the class defined in each of the war files but this is not the case - the war class loaders load some classes from jars in the ear file.

                Is there some way I can send you my ear file and source to my example projects?

                Thanks again

                • 5. Re: JBoss AS 5.1.0.GA Classloading Help
                  garethwebbley

                  I think I've figured it out now.

                  Basically if you have a jar in the ear file (rather than the webapp WEB-INF/lib) directory then it *MUST* be referenced in the application.xml as a java module as well as the war file MANIFEST.MF that uses it. If you omit the declaration in application.xml but include it in the MANIFEST.MF then the classes are loaded by war class loader not the ear class loader.

                  • 6. Re: JBoss AS 5.1.0.GA Classloading Help
                    jaikiran

                     

                    "garethwebbley" wrote:


                    Basically if you have a jar in the ear file (rather than the webapp WEB-INF/lib) directory then it *MUST* be referenced in the application.xml as a java module as well as the war file MANIFEST.MF that uses it. If you omit the declaration in application.xml but include it in the MANIFEST.MF then the classes are loaded by war class loader not the ear class loader.



                    If that jar which you are adding as a "java" module in the application.xml is a plain library and if it is common to all modules in the .ear, then it should be packaged in .ear/lib folder. This will then be available to all the components in the .ear. You don't even have to add a reference to this library in the MANIFEST.MF of the war files.