Thanks,
will do soon.

On 02/04/14 16:17, Daniel Kulp wrote:

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



--
Alessio Soldano
Web Service Lead, JBoss

Reply via email to