aspose file tools*
The moose likes Servlets and the fly likes Tricky class loading error Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Servlets
Bookmark "Tricky class loading error " Watch "Tricky class loading error " New topic
Author

Tricky class loading error

Kasper Pedersen
Greenhorn

Joined: Apr 03, 2011
Posts: 4
Hi guys
Hope someone can help me out on this one. I spent 2 days experimenting and Googling with absolutely no positive results.


Background:
I have an webapplication that i use for a lot of different customers, containing a framework to handle customized plugins/codeunits. In order to make upgrades easy i wish to deploy the plugins outside the webapplication, so all customers can share the common webapplication and make updates easy (basically downloading new war files and leaving the plugins on the server).

Setup:
Got a webapplication, with an abstract class "CodeunitFormevents" (in a jar inside WEB-INF/lib).
I have deployed another jar file in the webservers "common/lib". This contains a class "TestPlugin" that extends the "CodeunitFormevents".
The TestPlugin is instaciated from the "CodeunitFormeventsFactory" within the webapplication.

Problem:
When creating a new instance i get an java.lang.NoClassDefFoundError (stacktrace below)
Note that the problem is with the superclass (CodeunitFormevents) - NOT the class (TestPlugin) itself !

Non-issues:
As long as the plugin jar is deployed inside "WEB-INF/lib" everything is fine.
Explicitly setting serialVersionUID had no effect.

Stacktrace:
java.lang.NoClassDefFoundError: dk/p2e/blanket/codeunit/CodeunitFormevents
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access$000(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1350)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1209)
at java.lang.ClassLoader.loadClassInternal(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at dk.p2e.blanket.codeunit.CodeunitFormeventsFactory.getCodeunitFormevents(CodeunitFormeventsFactory.java:21)
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18991
    
    8

Classes in "common/lib" don't have access to classes in any of the web applications. And when you load a class, that causes its superclass to be loaded first. In this case the superclass is in one of the web applications, so it can't be loaded.

It doesn't make sense (to me, anyway) for a plugin which is to be common to all web applications to have a superclass which isn't also common to all web applications.
Kasper Pedersen
Greenhorn

Joined: Apr 03, 2011
Posts: 4
Paul Clapham wrote:Classes in "common/lib" don't have access to classes in any of the web applications. And when you load a class, that causes its superclass to be loaded first. In this case the superclass is in one of the web applications, so it can't be loaded.

It doesn't make sense (to me, anyway) for a plugin which is to be common to all web applications to have a superclass which isn't also common to all web applications.


I see your point - thank you for clarifying.

Would it be possible to somehow deploy the codeunit classes outside the webapplication folder. I have looked into dynamic jar loading, but i am reluctant to use this approach (gets very installation specific). Finally i had considered storing the .jar in DB blobs, and writing the files til WEB-INF/lib at application boot time - i just fear that i have to degrade performance / cause classloader leaks by activating WatchedRessource.
David O'Meara
Rancher

Joined: Mar 06, 2001
Posts: 13459

You could look at using a URLClassLoader so that they get the code from you and you can control which version each client gets.
You would still need to manage it from each client so that they periodically (or explicitly) check for updates and get a new URLClassLoader if the remote package changes.
Can't say I'm a fan of this though.
Kasper Pedersen
Greenhorn

Joined: Apr 03, 2011
Posts: 4
The URL loader is actually fine - only annoyance is that i need to keep track of both the .jar name and the class name ... some naming convention comes to mind.

Thanks for help both of you
 
 
subject: Tricky class loading error