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:
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
java.io.DataOutputStream dos = new java.io.DataOutputStream(new java.io.BufferedOutputStream(baos));
_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 ... :)
Johan
-- Howard M. Lewis Ship Creator, Tapestry: Java Web Components http://jakarta.apache.org/tapestry http://jakarta.apache.org/commons/sandbox/hivemind/ http://javatapestry.blogspot.com
-- you too?
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
