I?m working with a framework library separated in two JARs: fwk.jar has three packages: "peristence", "facade", "control" and fwkWeb.jar has one package called "web". The packages inside fwk.jar use utility JARs.
My EJBs implement and extend classes from "persistence" and use classes from "facade".
My JSPs use classes from "web" package (fwkWeb.jar) and these ones extend Struts classes (struts.jar and ApplicationResources.properties) and use "peristence" classes (fwk.jar).
A deployed the EAR as follows:
EAR
|- fwk.jar and utility JARs
|- AppEJB.jar
| |- EJBs
| |- META-INF/MANIFEST.MF (pointing to utility JARs and fwk.jar)
|- AppWeb.war
| |- JSPs
| |- WEB-INF/classes/ApplicationResources.properties
| |- WEB-INF/lib/struts.jar
| |- WEB-INF/lib/fwkWeb.jar (package "web")
| |- WEB-INF/lib/AppWeb.jar
The problem is as follows:
- In my AppWeb.jar I have a class called UserTypeForm which extends BaseForm from
fwkWeb.jar which in turn extend AtionForm from Struts (struts.jar). So far,
so good. But, BaseForm has a instance field of type DataObject (from "persistence"
package in fwk.jar). Then, when the JSP tries to instantiate the for, the following
situation occurs: when BaseForm is being instantiated it creates its field of type
persitence.DataObject and seems to be loosing its context (or something like that)
and then throwing an exception: action: "Error creating ActionForm instance of class
'company.app.web.forms.UserTypeForm' java.lang.NoClassDefFoundError:
org/apache/struts/action/ActionForm"
Here goes the stack trace:
action: Error creating ActionForm instance of class 'company.app.web.forms.UserTypeForm'
java.lang.NoClassDefFoundError: org/apache/struts/action/ActionForm
at java.lang.ClassLoader.defineClass0(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:502)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:123)
at com.evermind[OC4J].util.OC4JSecureClassLoader.defineClassEntry(OC4JSecureClassLoader.java:46)
at com.evermind[OC4J].naming.ContextClassLoader.defineClass(ContextClassLoader.java:1106)
at com.evermind[OC4J].naming.ContextClassLoader.findClass(ContextClassLoader.java:369)
at java.lang.ClassLoader.loadClass(ClassLoader.java:299)
at com.evermind[OC4J].naming.ContextClassLoader.loadClass(ContextClassLoader.java:139)
at java.lang.ClassLoader.loadClass(ClassLoader.java:255)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:315)
at java.lang.ClassLoader.defineClass0(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:502)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:123)
at com.evermind[OC4J].util.OC4JSecureClassLoader.defineClassEntry(OC4JSecureClassLoader.java:46)
at com.evermind[OC4J].naming.ContextClassLoader.defineClass(ContextClassLoader.java:1106)
at com.evermind[OC4J].naming.ContextClassLoader.findClass(ContextClassLoader.java:369)
at java.lang.ClassLoader.loadClass(ClassLoader.java:299)
at com.evermind[OC4J].naming.ContextClassLoader.loadClass(ContextClassLoader.java:139)
at java.lang.ClassLoader.loadClass(ClassLoader.java:292)
at com.evermind[OC4J].naming.ContextClassLoader.loadClass(ContextClassLoader.java:139)
at java.lang.ClassLoader.loadClass(ClassLoader.java:255)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:315)
at java.lang.ClassLoader.defineClass0(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:502)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:123)
at com.evermind[OC4J].util.OC4JSecureClassLoader.defineClassEntry(OC4JSecureClassLoader.java:46)
at com.evermind[OC4J].naming.ContextClassLoader.defineClass(ContextClassLoader.java:1106)
at com.evermind[OC4J].naming.ContextClassLoader.findClass(ContextClassLoader.java:369)
at java.lang.ClassLoader.loadClass(ClassLoader.java:299)
at com.evermind[OC4J].naming.ContextClassLoader.loadClass(ContextClassLoader.java:139)
at java.lang.ClassLoader.loadClass(ClassLoader.java:255)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:315)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:140)
at org.apache.struts.action.ActionServlet.processActionForm(ActionServlet.java:1701)
at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1563)
at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:492)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:740)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
at com.evermind[OC4J].server.http.ResourceFilterChain.doFilter(ResourceFilterChain.java:65)
at oracle.security.jazn.oc4j.JAZNFilter.doFilter(JAZNFilter.java:293)
at com.evermind[OC4J].server.http.ServletRequestDispatcher.invoke(ServletRequestDispatcher.java:602)
at com.evermind[OC4J].server.http.ServletRequestDispatcher.forwardInternal(ServletRequestDispatcher.java:308)
at com.evermind[OC4J].server.http.HttpRequestHandler.processRequest(HttpRequestHandler.java:779)
at com.evermind[OC4J].server.http.HttpRequestHandler.run(HttpRequestHandler.java:264)
at com.evermind[OC4J].server.http.HttpRequestHandler.run(HttpRequestHandler.java:107)
at com.evermind[OC4J].util.ReleasableResourcePooledExecutor$MyWorker.run(ReleasableResourcePooledExecutor.java:192)
at java.lang.Thread.run(Thread.java:536)
have the same problem with extended struts classes , seems to be a classloader problem. one thing i found out is that in tomcat webapplications the default class loading stategy is reversed, to make it possible to have different versions of same jars in parallel in different webapps. with the default class loading stategy it would be impredictalble which version of a jar would be used first for loading a certain class.
therefor the tomcat webapp classloader does not delegate classloading to its parent first before trying to load the class by itself.
instead it locks for the class first in this order:
WEB-INF/classes
WEB-INF/libs
and after this it delegetes to its classloader parent.
that means:
if a class in a jar file located in WEB-INF/libs trys to load a class from WEB-INF/classes this will NOT work .
only the reverse is ok.
but what i dont understand is that struts seems to work around this problem obviousely. otherwist its ActionServlet in lib/struts.jar would not be able to load a Actions in the classes directory. right?
but when i use a class that extends ActionServlet, the problem is magically back.