3 Replies Latest reply on Nov 14, 2006 1:42 PM by Michael Bauer

    WAR files lib seems not to get loaded by classloader

    Michael Bauer Newbie

      My team is in the process of porting our app from JBoss 3.2.5 to JBoss 4.0.5. One of the things that has been biting us is the difference in the class loader.

      As part of this move, we are trying to stay away from the old "Unified" class loader. As such, we are trying to deploy out application as a set of EAR files, encapsulating the main function(s) and exposing them via a combination of Spring, Web Services, etc.

      This leads me to my current problem. I have a simple EAR, consisting of only one WAR in the EAR's lib dir and an application.xml specifying that war and giving it a context. So far so good.

      The WAR is a Struts-based application. In its lib dir are a bunch of JARs, basically all the libs needed. Included in this list are struts-core.jar, struts-tiles.jar, and struts-extras.jar.

      When I deploy this EAR file, everything deploys fine, but as soon as I access the main page:

      java.lang.NoClassDefFoundError: org/apache/struts/actions/DispatchAction
       at java.lang.ClassLoader.defineClass1(Native Method)
       at java.lang.ClassLoader.defineClass(ClassLoader.java:620)
       at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)
       at java.net.URLClassLoader.defineClass(URLClassLoader.java:260)
       at java.net.URLClassLoader.access$100(URLClassLoader.java:56)
       at java.net.URLClassLoader$1.run(URLClassLoader.java:195)

      I don't understand it! I thought that when JBoss deployed the WAR, it was supposed to add the WAR's lib dir to the hierarchical classpath. Why is it then that DispatchAction is not found, when it is sitting inside the WAR's lib folder?

      I am confused. Can someone please set me on the right path here? I really want to try and get a good grasp on this class loader stuff.

        • 2. Re: WAR files lib seems not to get loaded by classloader
          Michael Bauer Newbie


          "genman" wrote:
          There was a change...

          Not quite sure what has changed. I know the default for JBoss 3.2.x and prior is the Unified ClassLoader, whereas after its a hierarchical class loaded. But, either way, shouldn't a library within the WAR be loaded and available?

          The only thing I can thing of that may explain is that they changed the class loader for Tomcat itself.

          • 3. Re: WAR files lib seems not to get loaded by classloader
            Michael Bauer Newbie

            I have done a lot of reading and a bunch of testing, and here is what I have found so far...

            The problem is not with the EAR, per say, as much as its a problem with the WAR. When deployed outside of the EAR, I still get the "NoClassDefFoundError" for DispatchAction. Switching the Tomcat classloader to use the JBoss Unified Classloader fixes the problem, in as much as one can say circumventing the problem is indeed a fix. Please keep in mind that the JSPs, web.xml, libs, and custom tags are all part of this WAR being deployed.

            This brings me to the next set of questions, if someone could be so kind as to help me answer them...
            - Why is it that, under the normal Tomcat classloader setup, the libraries inside the WAR are not "visible"? Isn't there some concept of a "context" that encompasses a particular request within the container?
            - Shouldn't the hierarchical classloaded allow classes within the leaves, in this case the WAR, to see classes loaded above it? If this is the case, then why is there a problem finding the DispatchAction, which is in the WEB-INF/lib folder of the WAR?
            - If visibility of the classes from within the WAR are a problem, how can one get the classes loaded without compromising the idea of WAR isolation or by just throwing the required JARs into the lib folder in JBoss.
            - What is actually trying to load the DispatchAction class? I believe this class extends Servlet, in which case I would think this would be Tomcat doing it as part of the Servlet container. Shouldn't the servlet container have visibility to the classloader of the web application its servicing? Doesn't this get setup as part of the context mentioned above?

            We are trying to fix some past mistakes here, and want to stay within the boundaries. WAR isolation is an important concept we want to try to maintain. In the past, we simply threw all the libs in the JBoss lib folder, and everything, all components and pieces of the application, was deployed separately as a hodge-podge of JARs, WARs, and SARs. We banked on the fact that the Unified Classloader would just make everything visible to everything. Whereas this worked, it made the code a huge pile of spaghetti references, libraries were all over...it was a mess.

            Now, in this refactor, we are trying to play more by the *rules*. We have refactored all the spaghetti out into core "components", to be used as libraries to the application pieces. We have employed Maven2 as the new build system (over ant) to help enforce dependencies. We are isolating the various pieces of the application into separate deployments to be deployed as bundled EARs. This makes classloader isolation VERY important to us, as one application may use a different version of STRUTS than another. How can we make this work without falling back to the same-ol' habit of making everything visible to everything? What are we doing wrong?