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