NoClassDefFoundError in a WAR in an EAR - java

I have an EAR that has a WAR inside, which has a jar inside it's WEB-INF/lib/. However, the class in that jar cannot be located (throws NoClassDefFoundError). I've verified that the class is indeed in that jar by doing javap -classpath
Any ideas why?
I'm on glassfish.

I figured it out. For some strange reason, the classes being loaded failed to get loaded due to some missing classes. i.e. I have a ClassA and it was loading ClassB. ClassB depends on ClassC. But since ClassC was not in my classpath, ClassB's class was not properly loaded. Thus, accessing ClassB from ClassA threw NoClassDefFoundError.

Related

PyFlink "pipeline.classpaths" vs $FLINK_HOME/lib

What is the difference between class loading classes passed as part of PyFlink pipeline.classpath config and putting them into a $FLINK_HOME\lib directory?
When I want to use flink-sql-connector-kafka-*.jar it works fine just passing it using pipeline.classpath but when I want to use something that has some external dependencies like flink-avro-*.jar that needs avro-*.jar jars. It seems to load flink-avro-*.jar but it looks like it fails to load avro-*.jar and throws:
java.lang.NoClassDefFoundError: Could not initialize class org.apache.avro.SchemaBuilder
When I am dding avro-*.jar to $FLINK_HOME\lib it works just fine.
NoClassDefFoundError and ClassNotFoundException are different
java.lang.ClassNotFoundException This exception indicates that the
class was not found on the classpath. This indicates that we were
trying to load the class definition, and the class did not exist on
the classpath.
java.lang.NoClassDefFoundError This exception indicates that the JVM
looked in its internal class definition data structure for the
definition of a class and did not find it. This is different than
saying that it could not be loaded from the classpath. The point is,
a NoClassDefFoundError is not necessarily a classpath problem.
flink-sql-avro-*.jar is a shaded jar which will relocate the path of org.apache.flink:flink-avro org.apache.avro:avro
Judging from the NoClassDefFoundError, there may be a conflict between the avro version dependencies

Java Load Class Dinamically in ChildClassLoader related to SystemClassLoader

I have a java web application that comes wiht a abstract class, (lets call it ClassA) deployed on an application server. This java web application also loads classes from external jars dinamically, by using the approach on this question's accepted response.
Everything works fine, until I get to load a class (call it, ClassB) that extends from ClassA. I get a java.lang.ClassNotFoundException: ClassA error message on my SysOut, pointing to the line that loads the class: urlClassLoader.loadClass(className);.
I assumed I wouldn't have a problem, since when I call URLClassLoader.newInstance(), it gets created from the default parent class loader, which I suppose should be the SystemClassLoader, which I assume contains the WebApp classes.
Is any of my assumptions wrong?
How can I load a class from an external Jar, which happens to extend from a parent class loaded in the WebApplication classloader?
I tried changing the deployment configuration of my WebApp from parent first to parent last and got the same error. I also tried doing a Class.forName("ClassA") before executing the URLClassLoader.loadClass("ClassB") line but got the same error again.
It seems that ClassA is loaded by some container's WebAppClassLoader which is a child of SystemClassLoader. Your custom URLClassLoader is a child of SystemClassLoader too and that's the reason why ClassB doesn't "see" ClassA.
To solve the problem, ClassB should be loaded by WebAppClassLoader or its child, it can be achieved with:
ClassLoader webAppCL = ClassA.class.getClassLoader();
URLClassLoader myCL = new URLClassLoader(urls, webAppCL);

Tomcat 7 How ClassLoader loads from 2 webapps, same package/classes hierarchy, different classes?

I have this scenario:
//Tomcat7/webapps/app1/WEB-INF/classes/a/b/c/A.class
//Tomcat7/webapps/app1/WEB-INF/classes/a/b/c/B.class
//Tomcat7/webapps/app2/WEB-INF/classes/a/b/c/B.class (different class but same name as <2>)
//Tomcat7/webapps/app2/WEB-INF/classes/a/b/c/C.class
Note: class directory hierarchy is the same, just the class file is different.
The log file for app1 contains NoClassDefFoundError for A.class. Checked the directory, class file definitely is there. Now I am trying to figure out if it is possible that the ClassLoader loaded only B.class and not A.class, although there should be a ClassLoader for each webapps - meaning two ClassLoaders?
Any ideas how this works?
EDIT: Tomcat7 is started via Tanuki JWS. From wrapper.log, I can see that app2 is initialized first, then only app1.
Regards,
Allan
This issue was solved after Tomcat7 was restarted. Root cause cannot be identified.

Call a method after deploying a war in a Java EE server

I am deploying two war say A,B in Java EE Server say Jboss.
Deployment order will be
WAR A
WAR B
I need to call a method once war B is deployed. That method will create an instance of a class which will be loaded only from the class path mentioned in the manifest file of the war.
I used a ServletContextListener, but this failed.
Note : I tested ServletContextListener - by specifying a sample content in the static block of the class that has to be instantiated and tried to create an instance from the ServletContextListener. But an error is thrown stating "RunTime Exception unable to load the class", and the sample content is also not displayed. More over the class is loaded in the server which is confirmed via -verbose:class option in the JAVA_OPTS.
But it works if I load the class from war A. It even works fine. It's a big process to explain why there is a need for creating such instances. I don't want to change the way in which the instance of the class is created.
Is there any other way to call the method after the war and all its dependencies are completely loaded?

EAR lib's class throwing a ClassNotFoundException for a WAR member (different)

My EAR has the following structure :
lib/
helper.jar (Helper classes used both by war1.war and war2.war)
war1.war
WEB-INF/
lib/
entities1.jar
war2.war
WEB-INF/
lib/
entities2.jar
When war1 calls a class in helper.jar that itself calls Class.forName("a class in war1"), it throws a ClassNotFoundException.
Notice that people usually have ClassNotFoundException when a war class loads a ear/lib class. My case is the reverse situation.
My EAR is deployed in Glassfish 3.1.2.
I've seen a similar case, but in JBoss, "EAR lib's class throwing a ClassNotFoundException for a WAR member", but the answers say it's a "cyclic dependency" problem. However, I don't see any "cyclic dependency" problem here. In java, any ClassX can refer to ClassY even if ClassY refers to ClassX....
In helper.jar you can't simply load a class situated in your war1.war using Class.forName.
The limitation comes from the default classloader used by the Class.forName method, which is the enterprise app's classloader (the one which loads helper.jar), which knows only its parents, not its children (war1.war and war2.war classloaders).
The solution for your problem is to use explicitely the context classloader, which scans in order:
war -> ear -> system -> extension -> bootstrap
This can be done using:
Class.forName("war1Class.class",true,Thread.currentThread().getContextClassLoader())

Categories