That seems reasonable to me. Feel free to apply it.
Dan On Apr 2, 2014, at 8:00 AM, Alessio Soldano <[email protected]> wrote: > Hi, > I've started testing the JBossWS integration with Apache CXF 3 and I'm > currently dealing with a classloading issue on client side. > A relevant difference between 2.7.x and 3 when it comes to JAXWS client > proxies is that on 3 they implement the org.apache.cxf.endpoint.Client > interface [1], while on 2.7.x they don't. > When building up a JAXWS client, the org.apache.cxf.common.util.ProxyHelper > is used to decide which classloader will later be passed to the JDK Proxy for > building the proxy instance. If the classloader that loaded the user service > class has visibility over all the interfaces the proxy has to implement, that > classloader is used, otherwise a ProxyClassloader is built. The > ProxyClassloader is basically a combination of the classloaders that loaded > each specific interface class. > Now, with Apache CXF 2.7.x, the user application needs to have visibility > over the JAX-WS api only, while with 3.0 it also needs to "see" the Apache > CXF classes, because of the check for org.apache.cxf.endpoint.Client > interface. When running JAX-WS applications on WildFly using the JBossWS > integration, the user is not *required* to set a dependency to Apache CXF > modules, even if they're internally used to serve JAX-WS functionalities. For > this reason, the service class classloader, which is a JBoss Module > classloader, won't usually allow loading the org.apache.cxf.endpoint.Client > *directly* (that is is by doing > Class.forName("org.apache.cxf.endpoint.Client", true, loader)). For this > reason, the ProxyHelper will go the combined classloader approach. > The problem with such an approach on WildFly / JBoss AS is that later the JDK > Proxy will try to load the interfaces using the ProxyClassloader, whose > parent is the boot classloader. On recent JDK version, the boot classloader > is able to load the JAX-WS api classes (because they're included in the JDK); > however, the javax.xml.ws.BindinProvider interface class that was retrieved > from the service class is a different class, having been loaded by a specific > module part of the service class classloader. This makes a check fail in the > JDK Proxy, effectively preventing creating the jaxws client proxy. > To me, the CXF ProxyClassloader should have an explicit parent classloader > set to the same classloader instance that was provided (the application > classloader, that is the service class classloader). That in turn *might* > have the boot classloader as parent (not in the case of JBoss / WildFly, due > to the modular approach). > If you have nothing against this, I'll create a JIRA and commit the following > patch: > > diff --git > a/core/src/main/java/org/apache/cxf/common/util/ProxyClassLoader.java > b/core/src/main/java/org/apache/cxf/common/util/ProxyClassLoader.java > index f7de519..c4baa17 100644 > --- a/core/src/main/java/org/apache/cxf/common/util/ProxyClassLoader.java > +++ b/core/src/main/java/org/apache/cxf/common/util/ProxyClassLoader.java > @@ -32,10 +32,12 @@ public class ProxyClassLoader extends ClassLoader { > private final Set<ClassLoader> loaders = new HashSet<ClassLoader>(); > private boolean checkSystem; > > - public ProxyClassLoader() { > + public ProxyClassLoader(ClassLoader parent) { > + super(parent); > classes = null; > } > - public ProxyClassLoader(Class<?>[] cls) { > + public ProxyClassLoader(ClassLoader parent, Class<?>[] cls) { > + super(parent); > classes = cls; > } > > diff --git a/core/src/main/java/org/apache/cxf/common/util/ProxyHelper.java > b/core/src/main/java/org/apache/cxf/common/util/ProxyHelper.java > index c252574..27f2c56 100644 > --- a/core/src/main/java/org/apache/cxf/common/util/ProxyHelper.java > +++ b/core/src/main/java/org/apache/cxf/common/util/ProxyHelper.java > @@ -58,7 +58,7 @@ public class ProxyHelper { > if (canSeeAllInterfaces(loader, interfaces)) { > return loader; > } > - ProxyClassLoader combined = new ProxyClassLoader(interfaces); > + ProxyClassLoader combined = new ProxyClassLoader(loader, interfaces); > for (Class<?> currentInterface : interfaces) { > combined.addLoader(currentInterface.getClassLoader()); > } > > Thanks > Alessio > > > > [1] > https://fisheye6.atlassian.com/changelog/cxf?cs=3898dbb3e29202c0d2942fb903fa29a7c16418a7 > > -- > Alessio Soldano > Web Service Lead, JBoss > -- Daniel Kulp [email protected] - http://dankulp.com/blog Talend Community Coder - http://coders.talend.com
