dev@ws-test-harness.java.net

Investigated ClassCastException

From: Kohsuke Kawaguchi <Kohsuke.Kawaguchi_at_Sun.COM>
Date: Wed, 12 Jul 2006 18:08:30 -0700

I investigated the following problem Ken found during invoking APT:

warning: Bad annotation processor factory: java.lang.ClassCastException:
com.sun.istack.ws.AnnotationProcessorFactoryImpl

The problem was that when APT creates a classloader (I'll call it ACL)
for loading annotation processors, it does so by making the system
classloader its parent.

This is correct when APT is running stand-alone, as the system
classloader does include APT classes. But in our set up, the system
classloader is almost empty, and ACL includes tools.jar in itself
(because we pass World.toolClasspath that includes tools.jar.)

So when annotation processor is loaded, it loads one more copy of APT,
which is different from the running APT instance, and hence when they
try to cast, it fails.

This is essentially an APT bug, in the sense that it's making a wrong
assumption about itself being present in the system class loader, but
unfortunately we need to work around the problem by ourselves, since any
fix to APT is unlikely to happen in any time soon, in a way that we can
use it.

One approach is to create the instance of
"com.sun.istack.ws.AnnotationProcessorFactoryImpl" by ourselevs
and then use the following version of APT entry point to pass in this
instance:

     int process(AnnotationProcessorFactory factory, String... args)

This prevents APT from loading another copy of annotation processor, and
has a nice side effect of making things faster. The downside is that
this requires the harness to hard-code the annotation processor name.

This downside can be mitigated by having the harness scan
META-INF/services/com.sun.mirror.apt.AnnotationProcessorFactory. This
class name is somewhat unlikely to change, so perhaps it's acceptable
for now to hard-code this name in the benefit of making progress.


Alternative approach is to invoke wsgen (either internally via
WsGen.doMain or externally --- just like how we invoke wsimport.) WsGen
internally uses the above-mentioned process method, so this should fix
the problem, too. Perhaps this is more desirable, as it's simpler (plus
it's in line with how we use wsimport.)

If we are to do this, we need to drive wsgen by command line arguments,
and perhaps there's some implications in doing this that I don't know of.

Overall, for now I'm inclined to invoke wsgen.

-- 
Kohsuke Kawaguchi
Sun Microsystems                   kohsuke.kawaguchi_at_sun.com