commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Johan Lindquist <>
Subject Re: [HiveMind] RE: Broken test ...
Date Thu, 11 Sep 2003 12:47:11 GMT
On Thu, 11 Sep 2003 07:35:17 -0400, Howard M. Lewis Ship wrote:

> Please keep this discussion on the Jakarta commons developer list.
>> The problem i am getting is when I try to add an interceptor to the
>> service.  The class loader used by javassist to compile the
>> class is it's
>> own one - javassist.ClassPool.SimpleClassLoader, not the
>> class loader used
>> in this case to bootstrap the system.
>> So it can't find the classes (in this case the
>> AbstractLoggingInterceptor)
>> already loaded by the URL class loader when creating the intercepted
>> classes - the call to 'return
>> _pool.writeAsClass(_ctClass.getName());' in
>> ClassFabImpl#createClass fails with an
>> NoClassDefFoundException.  I added
>> some debug and just before the call to the writeAsClass method, the
>> AbstractLoggingInterceptor can be loaded.
>> It may be that I am trying to be too clever here - maybe it
>> is best to
>> have the classpath defined on the command line - or move the
>> application
>> into an application server.
> Class loader issues are the hardest to setup and test from within JUnit 
> and Maven.
> This sounds like a bug to me. I'll double check which class loader is 
> used by the interceptor when
> fabricating classes.

I can get HiveMind to create all the classes by not using the writeAsClass 
call in the createClass method.  Instead I use the following code to 
extract the class created by javassist: baos = new; dos = new;
_pool.write(_ctClass.getName(), dos);
byte[] classFile = baos.toByteArray();

I can now load and define this class using the class loader used by the 
ClassFabImpl.  This is of course a hack (I have to use my own classloader 
allowing to load classes from a byte array) - should the ClassFabImpl use 
a class loader (inheriting from the classloader used to create the module) 
to load/create the class?

> Hm. In order to do the class manipulation, we need a class loader that 
> has visibility to the
> HiveMind classes (specifically, the abstract base class for the 
> interceptor instance) as well as
> visibility to the service interface (i.e., the service extension point 
> module's class loader). In
> your scenario, I don't know that that ispossible.  My assumptions were 
> that HiveMind would be in the
> system classpath and you might add a URL classloader on top of that to 
> suck in modules from other
> locations.
> The work around is to fiddle with your URL class loader; I would suggest 
> multiple levels: build a
> URL class loader that loads HiveMind and its dependencies (from your 
> message, I'm assuming you are
> using reflection to bridge from the system class loader to the HiveMind 
> libraries in some way).  The
> HiveMind class loader should be the parent of the class loaders for the 
> remaining modules.

Yes, agree - but isn't the problem that javassist is using it's own class 
loader, which doesn't inherit from the URLClassLoader used by hivemind but 
 from the system class loader?  So it wouldn't matter if you put the 
modules into their own class loader - as soon as you try to add an 
interceptor to the module, javassist would fail?

> I think another, simpler option for you would be to use Ant to run your 
> production app.  If
> necessary, have a short shell script or batch file that invokes Ant, use 
> Ant to set the bootstrap
> classpath (at least the HiveMind library/dependencies).  People seem to 
> overlook that Ant is useful
> for more than just building code.

Definately - I as said in the previous mail, I may be going overboard on 
this one ... :)


> --
> Howard M. Lewis Ship
> Creator, Tapestry: Java Web Components

you too?

View raw message