URLClassLoader and Tomcat

R

Romain

Hi everybody,

I'm trying to write a plugin-like system for Tomcat. The plugin is a
class with some default method. All plugins must extend this base
class.

Here is my architecure :
/WEB-INF/classes/GenericRule.class
....
/somewhere-not-related-to-tomcat/classes/MyRule.class

I don't want to put the MyRule.class inside the WEB-INF repository
because MyRule doesn't belong to me. It's written by somebody else.
WEB-INF should contain only my proper code and all specific code should
go elsewhere.

Problem womes with the Tomcat ClassLoader. Everything works correctly
in a standalone application but not inside Tomcat because Tomcat
ClassLoader is not really a standard one.

Here is a snippet of my code (factory of rule) :

String myRuleClassname;
Object obj = null;
URL[] urls = new URL[1];
urls[0] = (new
String("/somewhere-not-related-to-tomcat/classes")).toURL();

ClassLoader cl = GenericRule.class.getClass().getClassLoader();
if (cl != null) {
System.out.println("Default ClassLoader : " + cl);

URLClassLoader urlc = new URLClassLoader(urls, cl);
obj = urlc.loadClass(myRuleClassname);
} else {
ClassLoader cl2 = ClassLoader.getSystemClassLoader();
if (cl2 != null) {
System.out.println("System ClassLoader : " + cl2);

URLClassLoader urlc = new URLClassLoader(urls, cl2);
obj = urlc.loadClass(myRuleClassname);
} else {
System.out.println("No ClassLoader found !");

URLClassLoader urlc = new URLClassLoader(urls);
obj = urlc.loadClass(myRuleClassname);
}
}

if( obj instanceof GenericRule ){
// Good
} else {
// Bad : I didn't instanciate correctly my Object.
}


Result of this is : default classLoader is void. System class loader is
"sun.misc.Launcher$AppClassLoader@1813fac".

If I try to load myRule with the SystemClassLoader, there is an
exception because GenericRule cannot be found. Which mean that System
class loader is not the one with the webapp specific classpath.
If I try to load myRule without any parent ClassLoader, the same
exception occurs which is normal.
If I modify the array of URL in the URlClassLoader to add the
WEB-INF/lib and WEB-INF/classes path, the instanciation goes correctly,
but myRule extends the GenericRule from the URLClassLoader, not the one
from Tomcat (in this cas, there is 2 types GenericRule, one for each
classloader). So, obj is not of type GenericRule. If I cast to
genericRule, I have a ClassCastException.

The last two behaviors are normal. The only way to load properly the
plugin is to be sure that the taken GenericRule is the one defined in
the first ClassLoader. My problem is that I can't find a way to get the
Tomcat ClassLoader with the GenericRule class defined.

I hope I've been clear enough...
If anyone has any idea, let me know, you will save my week :)
 
R

Romain

I finally find the problem.
The ClassLoader I must load is not :
GenericRule.class.getClass().getClassLoader(); but
GenericRule.class.getClassLoader();

It now works as it should.
The new ClassLoader is defined with the WebappClassLoader as a parent.
 
P

pkriens

Isnt it easier to have a plugin management system that runs Tomcat? It
looks like you have reversed the control her?

Take a look at Eclipse, Oscar/Felix (Apache) or Knopflerfish that allow
you to return Tomcat in a very well specified plugin environment
(OSGi). It will probably shield you completely from having to muck
around with class loaders. And you really get hot pluggability.

Kind regards,

Peter Kriens
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top