You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by as...@apache.org on 2014/01/23 15:53:48 UTC

svn commit: r1560703 - in /cxf/branches/2.7.x-fixes: api/src/main/java/org/apache/cxf/service/invoker/ rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/ systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/

Author: ashakirin
Date: Thu Jan 23 14:53:47 2014
New Revision: 1560703

URL: http://svn.apache.org/r1560703
Log:
Backported [CXF-5512]: @UseAsyncMethod annotation doesn't work for classes implementing Provider<T>

Modified:
    cxf/branches/2.7.x-fixes/api/src/main/java/org/apache/cxf/service/invoker/AbstractInvoker.java
    cxf/branches/2.7.x-fixes/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/AbstractJAXWSMethodInvoker.java
    cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ClientServerTest.java
    cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/Server.java

Modified: cxf/branches/2.7.x-fixes/api/src/main/java/org/apache/cxf/service/invoker/AbstractInvoker.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/api/src/main/java/org/apache/cxf/service/invoker/AbstractInvoker.java?rev=1560703&r1=1560702&r2=1560703&view=diff
==============================================================================
--- cxf/branches/2.7.x-fixes/api/src/main/java/org/apache/cxf/service/invoker/AbstractInvoker.java (original)
+++ cxf/branches/2.7.x-fixes/api/src/main/java/org/apache/cxf/service/invoker/AbstractInvoker.java Thu Jan 23 14:53:47 2014
@@ -66,7 +66,7 @@ public abstract class AbstractInvoker im
                 params = new MessageContentsList(o);
             }
             
-            m = adjustMethodAndParams(m, exchange, params);
+            m = adjustMethodAndParams(m, exchange, params, serviceObject.getClass());
             
             //Method m = (Method)bop.getOperationInfo().getProperty(Method.class.getName());
             m = matchMethod(m, serviceObject);
@@ -80,7 +80,8 @@ public abstract class AbstractInvoker im
 
     protected Method adjustMethodAndParams(Method m,
                                            Exchange ex,
-                                           List<Object> params) {
+                                           List<Object> params,
+                                           Class<?> serviceObjectClass) {
         //nothing to do
         return m;
     }

Modified: cxf/branches/2.7.x-fixes/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/AbstractJAXWSMethodInvoker.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/AbstractJAXWSMethodInvoker.java?rev=1560703&r1=1560702&r2=1560703&view=diff
==============================================================================
--- cxf/branches/2.7.x-fixes/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/AbstractJAXWSMethodInvoker.java (original)
+++ cxf/branches/2.7.x-fixes/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/AbstractJAXWSMethodInvoker.java Thu Jan 23 14:53:47 2014
@@ -20,6 +20,8 @@
 package org.apache.cxf.jaxws;
 
 import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -30,6 +32,7 @@ import java.util.concurrent.ExecutionExc
 
 import javax.activation.DataHandler;
 import javax.xml.ws.AsyncHandler;
+import javax.xml.ws.Provider;
 import javax.xml.ws.Response;
 import javax.xml.ws.handler.MessageContext;
 import javax.xml.ws.handler.MessageContext.Scope;
@@ -52,6 +55,7 @@ import org.apache.cxf.message.FaultMode;
 import org.apache.cxf.message.Message;
 import org.apache.cxf.message.MessageContentsList;
 import org.apache.cxf.message.MessageImpl;
+import org.apache.cxf.service.factory.ServiceConstructionException;
 import org.apache.cxf.service.invoker.Factory;
 import org.apache.cxf.service.invoker.FactoryInvoker;
 import org.apache.cxf.service.invoker.SingletonFactory;
@@ -77,18 +81,24 @@ public abstract class AbstractJAXWSMetho
         }
         return null;
     }
-    protected Method adjustMethodAndParams(Method m, Exchange ex, List<Object> params) {
+
+    @Override
+    protected Method adjustMethodAndParams(Method mOriginal, Exchange ex, List<Object> params,
+                                           Class<?> serviceObjectClass) {
+        // If class implements Provider<T> interface, use overriden method from service object class
+        // to check UseAsyncMethod annotation
+        Method mso = getProviderServiceObjectMethod(mOriginal, serviceObjectClass);
         
-        UseAsyncMethod uam = m.getAnnotation(UseAsyncMethod.class);
+        UseAsyncMethod uam = mso.getAnnotation(UseAsyncMethod.class);
         if (uam != null) {
             BindingOperationInfo bop = ex.getBindingOperationInfo();
             Method ret = bop.getProperty(ASYNC_METHOD, Method.class);
             if (ret == null) {
-                Class<?> ptypes[] = new Class<?>[m.getParameterTypes().length + 1];
-                System.arraycopy(m.getParameterTypes(), 0, ptypes, 0, m.getParameterTypes().length);
-                ptypes[m.getParameterTypes().length] = AsyncHandler.class;
+                Class<?> ptypes[] = new Class<?>[mso.getParameterTypes().length + 1];
+                System.arraycopy(mso.getParameterTypes(), 0, ptypes, 0, mso.getParameterTypes().length);
+                ptypes[mso.getParameterTypes().length] = AsyncHandler.class;
                 try {
-                    ret = m.getDeclaringClass().getMethod(m.getName() + "Async", ptypes);
+                    ret = mso.getDeclaringClass().getMethod(mso.getName() + "Async", ptypes);
                     bop.setProperty(ASYNC_METHOD, ret);
                 } catch (Throwable t) {
                     //ignore
@@ -115,9 +125,52 @@ public abstract class AbstractJAXWSMetho
                 }
             }
         }
-        return m;
+        return mOriginal;
     }
     
+    private Method getProviderServiceObjectMethod(Method m, Class<?> serviceObjectClass) {
+        if (!Provider.class.isAssignableFrom(serviceObjectClass)) {
+            return m;
+        }
+        Class<?> currentSvcClass = serviceObjectClass;
+        Class<?> genericType = null;
+
+        while (currentSvcClass != null) {
+            genericType = getProviderGenericType(currentSvcClass);
+            if (genericType != null) {
+                break;
+            }
+            // Check superclass until top
+            currentSvcClass = currentSvcClass.getSuperclass();
+        }
+        // Should never happens
+        if (genericType == null) {
+            return m;
+        }
+        try {
+            return serviceObjectClass.getMethod("invoke", genericType);
+        } catch (Exception e) {
+            throw new ServiceConstructionException(e);
+        }
+    }
+
+    private Class<?> getProviderGenericType(Class<?> svcClass) {
+        Type[] interfaces = svcClass.getGenericInterfaces();
+        for (Type interfaceType : interfaces) {
+            if (interfaceType instanceof ParameterizedType) {
+                ParameterizedType paramInterface = (ParameterizedType)interfaceType;
+                if (!paramInterface.getRawType().equals(Provider.class)) {
+                    continue;
+                }
+                Type[] typeArgs = paramInterface.getActualTypeArguments();
+                if (typeArgs.length > 0) {
+                    return (Class<?>)typeArgs[0];
+                }
+            }
+        }
+        return null;
+    }
+
     class JaxwsServerHandler implements AsyncHandler<Object> {
         Response<Object> r;
         Continuation continuation;

Modified: cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ClientServerTest.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ClientServerTest.java?rev=1560703&r1=1560702&r2=1560703&view=diff
==============================================================================
--- cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ClientServerTest.java (original)
+++ cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ClientServerTest.java Thu Jan 23 14:53:47 2014
@@ -19,6 +19,7 @@
 
 package org.apache.cxf.systest.jaxws;
 
+import java.io.ByteArrayInputStream;
 import java.io.InputStream;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
@@ -41,8 +42,10 @@ import java.util.logging.Logger;
 import java.util.zip.GZIPInputStream;
 
 import javax.xml.namespace.QName;
+import javax.xml.transform.stream.StreamSource;
 import javax.xml.ws.AsyncHandler;
 import javax.xml.ws.BindingProvider;
+import javax.xml.ws.Dispatch;
 import javax.xml.ws.Endpoint;
 import javax.xml.ws.Response;
 import javax.xml.ws.Service;
@@ -63,6 +66,7 @@ import org.apache.cxf.frontend.ClientPro
 import org.apache.cxf.helpers.XMLUtils;
 import org.apache.cxf.helpers.XPathUtils;
 import org.apache.cxf.message.Message;
+import org.apache.cxf.staxutils.StaxUtils;
 import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
 import org.apache.cxf.transport.http.HTTPConduit;
 import org.apache.hello_world_soap_http.BadRecordLitFault;
@@ -76,7 +80,6 @@ import org.apache.hello_world_soap_http.
 import org.apache.hello_world_soap_http.types.BareDocumentResponse;
 import org.apache.hello_world_soap_http.types.GreetMeLaterResponse;
 import org.apache.hello_world_soap_http.types.GreetMeResponse;
-
 import org.junit.BeforeClass;
 import org.junit.Test;
 
@@ -1057,4 +1060,19 @@ public class ClientServerTest extends Ab
         assertEquals("Hello World", resp);
     }
 
+    @Test
+    public void testEchoProviderAsync() throws Exception {
+        String requestString = "<echo/>";
+        Service service = Service.create(serviceName);
+        service.addPort(fakePortName, javax.xml.ws.soap.SOAPBinding.SOAP11HTTP_BINDING,
+                        "http://localhost:" + PORT + "/SoapContext/AsyncEchoProvider");
+        Dispatch<StreamSource> dispatcher = service.createDispatch(fakePortName,
+                                                                   StreamSource.class,
+                                                                   Service.Mode.PAYLOAD);
+
+        StreamSource request = new StreamSource(new ByteArrayInputStream(requestString.getBytes()));
+        StreamSource response = dispatcher.invoke(request);
+
+        assertEquals(requestString, StaxUtils.toString(response));
+    }
 }

Modified: cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/Server.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/Server.java?rev=1560703&r1=1560702&r2=1560703&view=diff
==============================================================================
--- cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/Server.java (original)
+++ cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/Server.java Thu Jan 23 14:53:47 2014
@@ -25,8 +25,14 @@ import java.util.List;
 import java.util.concurrent.Future;
 
 import javax.jws.WebService;
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
 import javax.xml.ws.AsyncHandler;
 import javax.xml.ws.Endpoint;
+import javax.xml.ws.Provider;
+import javax.xml.ws.Service;
+import javax.xml.ws.ServiceMode;
+import javax.xml.ws.WebServiceProvider;
 
 import org.apache.cxf.annotations.UseAsyncMethod;
 import org.apache.cxf.interceptor.URIMappingInterceptor;
@@ -60,6 +66,10 @@ public class Server extends AbstractBusT
         address = "http://localhost:" + PORT + "/SoapContext/AsyncSoapPort";
         eps.add(Endpoint.publish(address, implementor));
         
+        implementor = new AsyncEchoProvider();
+        address = "http://localhost:" + PORT + "/SoapContext/AsyncEchoProvider";
+        eps.add(Endpoint.publish(address, implementor));
+
         implementor = new GreeterImplMultiPort();
         address = "http://localhost:" + PORT + "/MultiPort/GreeterPort";
         eps.add(Endpoint.publish(address, implementor));
@@ -146,6 +156,33 @@ public class Server extends AbstractBusT
         }
     }
 
+    @WebServiceProvider
+    @ServiceMode(value = Service.Mode.PAYLOAD)
+    public class AsyncEchoProvider implements Provider<StreamSource> {
+
+        @Override
+        @UseAsyncMethod
+        public StreamSource invoke(StreamSource request) {
+            throw new RuntimeException("Should be async");
+        }
+
+        public Future<?> invokeAsync(final StreamSource s, final AsyncHandler<Source> asyncHandler) {
+            final ServerAsyncResponse<Source> r = new ServerAsyncResponse<Source>();
+            new Thread() {
+                public void run() {
+                    try {
+                        Thread.sleep(500);
+                    } catch (InterruptedException e) {
+                        // ignore
+                    }
+                    r.set(s);
+                    asyncHandler.handleResponse(r);
+                }
+            } .start();
+            return r;
+        }
+    }
+
     public static void main(String[] args) {
         try {
             Server s = new Server();



RE: svn commit: r1560703 - in /cxf/branches/2.7.x-fixes: api/src/main/java/org/apache/cxf/service/invoker/ rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/ systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/

Posted by Andrei Shakirin <as...@talend.com>.
Yep, will update that.

Regards,
Andrei.

> -----Original Message-----
> From: Alessio Soldano [mailto:asoldano@redhat.com]
> Sent: Donnerstag, 23. Januar 2014 16:46
> To: dev@cxf.apache.org
> Cc: Daniel Kulp; ashakirin@apache.org
> Subject: Re: svn commit: r1560703 - in /cxf/branches/2.7.x-fixes:
> api/src/main/java/org/apache/cxf/service/invoker/
> rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/
> systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/
> 
> On 23/01/14 16:01, Daniel Kulp wrote:
> > Andrei,
> >
> > This changes a protected method on a Abstract class that I believe either
> the JBoss folks or TomEE folks are subclassing.
> Currently, the JBossWS integration directly calls the
> adjustMethodAndParams method from a custom invoker extending
> JAXWSMethodInvoker and overriding invoke(Exchange exchange, Object o).
> So I'd also prefer what Dan suggests below on 2.7.x ;-)
> 
> Thanks
> 
> Alessio
> 
> 
> >     That's a concern to me as that would be a backwards compatible break.
> >
> > On 2.7.x, can we update the new method to handle when
> serviceObjectClass  is null and re-introduce the original method calling the
> new one with null?
> >
> >
> > Dan
> >
> >
> >
> > On Jan 23, 2014, at 9:53 AM, ashakirin@apache.org wrote:
> >
> >> Author: ashakirin
> >> Date: Thu Jan 23 14:53:47 2014
> >> New Revision: 1560703
> >>
> >> URL: http://svn.apache.org/r1560703
> >> Log:
> >> Backported [CXF-5512]: @UseAsyncMethod annotation doesn't work for
> >> classes implementing Provider<T>
> >>
> >> Modified:
> >>     cxf/branches/2.7.x-
> fixes/api/src/main/java/org/apache/cxf/service/invoker/AbstractInvoker.jav
> a
> >>     cxf/branches/2.7.x-
> fixes/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/AbstractJAXW
> SMethodInvoker.java
> >>     cxf/branches/2.7.x-
> fixes/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ClientServ
> erTest.java
> >>
> >> cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/
> >> systest/jaxws/Server.java
> >>
> >> Modified:
> >> cxf/branches/2.7.x-fixes/api/src/main/java/org/apache/cxf/service/inv
> >> oker/AbstractInvoker.java
> >> URL:
> >> http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/api/src/main/ja
> >>
> va/org/apache/cxf/service/invoker/AbstractInvoker.java?rev=1560703&r1
> >> =1560702&r2=1560703&view=diff
> >>
> ==========================================================
> ===========
> >> =========
> >> ---
> >> cxf/branches/2.7.x-fixes/api/src/main/java/org/apache/cxf/service/inv
> >> oker/AbstractInvoker.java (original)
> >> +++ cxf/branches/2.7.x-fixes/api/src/main/java/org/apache/cxf/service
> >> +++ /invoker/AbstractInvoker.java Thu Jan 23 14:53:47 2014
> >> @@ -66,7 +66,7 @@ public abstract class AbstractInvoker im
> >>                  params = new MessageContentsList(o);
> >>              }
> >>
> >> -            m = adjustMethodAndParams(m, exchange, params);
> >> +            m = adjustMethodAndParams(m, exchange, params,
> >> + serviceObject.getClass());
> >>
> >>              //Method m =
> (Method)bop.getOperationInfo().getProperty(Method.class.getName());
> >>              m = matchMethod(m, serviceObject); @@ -80,7 +80,8 @@
> >> public abstract class AbstractInvoker im
> >>
> >>      protected Method adjustMethodAndParams(Method m,
> >>                                             Exchange ex,
> >> -                                           List<Object> params) {
> >> +                                           List<Object> params,
> >> +                                           Class<?>
> >> + serviceObjectClass) {
> >>          //nothing to do
> >>          return m;
> >>      }
> >>
> >> Modified:
> >> cxf/branches/2.7.x-fixes/rt/frontend/jaxws/src/main/java/org/apache/c
> >> xf/jaxws/AbstractJAXWSMethodInvoker.java
> >> URL:
> >> http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/rt/frontend/jax
> >>
> ws/src/main/java/org/apache/cxf/jaxws/AbstractJAXWSMethodInvoker.jav
> a
> >> ?rev=1560703&r1=1560702&r2=1560703&view=diff
> >>
> ==========================================================
> ===========
> >> =========
> >> ---
> >> cxf/branches/2.7.x-fixes/rt/frontend/jaxws/src/main/java/org/apache/c
> >> xf/jaxws/AbstractJAXWSMethodInvoker.java (original)
> >> +++ cxf/branches/2.7.x-fixes/rt/frontend/jaxws/src/main/java/org/apac
> >> +++ he/cxf/jaxws/AbstractJAXWSMethodInvoker.java Thu Jan 23
> 14:53:47
> >> +++ 2014
> >> @@ -20,6 +20,8 @@
> >> package org.apache.cxf.jaxws;
> >>
> >> import java.lang.reflect.Method;
> >> +import java.lang.reflect.ParameterizedType;
> >> +import java.lang.reflect.Type;
> >> import java.util.ArrayList;
> >> import java.util.Collection;
> >> import java.util.HashMap;
> >> @@ -30,6 +32,7 @@ import java.util.concurrent.ExecutionExc
> >>
> >> import javax.activation.DataHandler;
> >> import javax.xml.ws.AsyncHandler;
> >> +import javax.xml.ws.Provider;
> >> import javax.xml.ws.Response;
> >> import javax.xml.ws.handler.MessageContext;
> >> import javax.xml.ws.handler.MessageContext.Scope;
> >> @@ -52,6 +55,7 @@ import org.apache.cxf.message.FaultMode; import
> >> org.apache.cxf.message.Message; import
> >> org.apache.cxf.message.MessageContentsList;
> >> import org.apache.cxf.message.MessageImpl;
> >> +import org.apache.cxf.service.factory.ServiceConstructionException;
> >> import org.apache.cxf.service.invoker.Factory;
> >> import org.apache.cxf.service.invoker.FactoryInvoker;
> >> import org.apache.cxf.service.invoker.SingletonFactory;
> >> @@ -77,18 +81,24 @@ public abstract class AbstractJAXWSMetho
> >>          }
> >>          return null;
> >>      }
> >> -    protected Method adjustMethodAndParams(Method m, Exchange ex,
> List<Object> params) {
> >> +
> >> +    @Override
> >> +    protected Method adjustMethodAndParams(Method mOriginal,
> Exchange ex, List<Object> params,
> >> +                                           Class<?> serviceObjectClass) {
> >> +        // If class implements Provider<T> interface, use overriden method
> from service object class
> >> +        // to check UseAsyncMethod annotation
> >> +        Method mso = getProviderServiceObjectMethod(mOriginal,
> >> + serviceObjectClass);
> >>
> >> -        UseAsyncMethod uam = m.getAnnotation(UseAsyncMethod.class);
> >> +        UseAsyncMethod uam =
> >> + mso.getAnnotation(UseAsyncMethod.class);
> >>          if (uam != null) {
> >>              BindingOperationInfo bop = ex.getBindingOperationInfo();
> >>              Method ret = bop.getProperty(ASYNC_METHOD, Method.class);
> >>              if (ret == null) {
> >> -                Class<?> ptypes[] = new
> Class<?>[m.getParameterTypes().length + 1];
> >> -                System.arraycopy(m.getParameterTypes(), 0, ptypes, 0,
> m.getParameterTypes().length);
> >> -                ptypes[m.getParameterTypes().length] = AsyncHandler.class;
> >> +                Class<?> ptypes[] = new
> Class<?>[mso.getParameterTypes().length + 1];
> >> +                System.arraycopy(mso.getParameterTypes(), 0, ptypes, 0,
> mso.getParameterTypes().length);
> >> +                ptypes[mso.getParameterTypes().length] =
> >> + AsyncHandler.class;
> >>                  try {
> >> -                    ret = m.getDeclaringClass().getMethod(m.getName() +
> "Async", ptypes);
> >> +                    ret =
> >> + mso.getDeclaringClass().getMethod(mso.getName() + "Async",
> ptypes);
> >>                      bop.setProperty(ASYNC_METHOD, ret);
> >>                  } catch (Throwable t) {
> >>                      //ignore
> >> @@ -115,9 +125,52 @@ public abstract class AbstractJAXWSMetho
> >>                  }
> >>              }
> >>          }
> >> -        return m;
> >> +        return mOriginal;
> >>      }
> >>
> >> +    private Method getProviderServiceObjectMethod(Method m,
> Class<?> serviceObjectClass) {
> >> +        if (!Provider.class.isAssignableFrom(serviceObjectClass)) {
> >> +            return m;
> >> +        }
> >> +        Class<?> currentSvcClass = serviceObjectClass;
> >> +        Class<?> genericType = null;
> >> +
> >> +        while (currentSvcClass != null) {
> >> +            genericType = getProviderGenericType(currentSvcClass);
> >> +            if (genericType != null) {
> >> +                break;
> >> +            }
> >> +            // Check superclass until top
> >> +            currentSvcClass = currentSvcClass.getSuperclass();
> >> +        }
> >> +        // Should never happens
> >> +        if (genericType == null) {
> >> +            return m;
> >> +        }
> >> +        try {
> >> +            return serviceObjectClass.getMethod("invoke", genericType);
> >> +        } catch (Exception e) {
> >> +            throw new ServiceConstructionException(e);
> >> +        }
> >> +    }
> >> +
> >> +    private Class<?> getProviderGenericType(Class<?> svcClass) {
> >> +        Type[] interfaces = svcClass.getGenericInterfaces();
> >> +        for (Type interfaceType : interfaces) {
> >> +            if (interfaceType instanceof ParameterizedType) {
> >> +                ParameterizedType paramInterface =
> (ParameterizedType)interfaceType;
> >> +                if (!paramInterface.getRawType().equals(Provider.class)) {
> >> +                    continue;
> >> +                }
> >> +                Type[] typeArgs = paramInterface.getActualTypeArguments();
> >> +                if (typeArgs.length > 0) {
> >> +                    return (Class<?>)typeArgs[0];
> >> +                }
> >> +            }
> >> +        }
> >> +        return null;
> >> +    }
> >> +
> >>      class JaxwsServerHandler implements AsyncHandler<Object> {
> >>          Response<Object> r;
> >>          Continuation continuation;
> >>
> >> Modified:
> >> cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/
> >> systest/jaxws/ClientServerTest.java
> >> URL:
> >> http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/systests/jaxws/
> >> src/test/java/org/apache/cxf/systest/jaxws/ClientServerTest.java?rev=
> >> 1560703&r1=1560702&r2=1560703&view=diff
> >>
> ==========================================================
> ===========
> >> =========
> >> ---
> >> cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/
> >> systest/jaxws/ClientServerTest.java (original)
> >> +++ cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/
> >> +++ cxf/systest/jaxws/ClientServerTest.java Thu Jan 23 14:53:47 2014
> >> @@ -19,6 +19,7 @@
> >>
> >> package org.apache.cxf.systest.jaxws;
> >>
> >> +import java.io.ByteArrayInputStream;
> >> import java.io.InputStream;
> >> import java.lang.reflect.InvocationHandler;
> >> import java.lang.reflect.Method;
> >> @@ -41,8 +42,10 @@ import java.util.logging.Logger; import
> >> java.util.zip.GZIPInputStream;
> >>
> >> import javax.xml.namespace.QName;
> >> +import javax.xml.transform.stream.StreamSource;
> >> import javax.xml.ws.AsyncHandler;
> >> import javax.xml.ws.BindingProvider;
> >> +import javax.xml.ws.Dispatch;
> >> import javax.xml.ws.Endpoint;
> >> import javax.xml.ws.Response;
> >> import javax.xml.ws.Service;
> >> @@ -63,6 +66,7 @@ import org.apache.cxf.frontend.ClientPro import
> >> org.apache.cxf.helpers.XMLUtils; import
> >> org.apache.cxf.helpers.XPathUtils;
> >> import org.apache.cxf.message.Message;
> >> +import org.apache.cxf.staxutils.StaxUtils;
> >> import
> >> org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
> >> import org.apache.cxf.transport.http.HTTPConduit;
> >> import org.apache.hello_world_soap_http.BadRecordLitFault;
> >> @@ -76,7 +80,6 @@ import org.apache.hello_world_soap_http.
> >> import
> org.apache.hello_world_soap_http.types.BareDocumentResponse;
> >> import
> org.apache.hello_world_soap_http.types.GreetMeLaterResponse;
> >> import org.apache.hello_world_soap_http.types.GreetMeResponse;
> >> -
> >> import org.junit.BeforeClass;
> >> import org.junit.Test;
> >>
> >> @@ -1057,4 +1060,19 @@ public class ClientServerTest extends Ab
> >>          assertEquals("Hello World", resp);
> >>      }
> >>
> >> +    @Test
> >> +    public void testEchoProviderAsync() throws Exception {
> >> +        String requestString = "<echo/>";
> >> +        Service service = Service.create(serviceName);
> >> +        service.addPort(fakePortName,
> javax.xml.ws.soap.SOAPBinding.SOAP11HTTP_BINDING,
> >> +                        "http://localhost:" + PORT +
> "/SoapContext/AsyncEchoProvider");
> >> +        Dispatch<StreamSource> dispatcher =
> service.createDispatch(fakePortName,
> >> +                                                                   StreamSource.class,
> >> +
> >> + Service.Mode.PAYLOAD);
> >> +
> >> +        StreamSource request = new StreamSource(new
> ByteArrayInputStream(requestString.getBytes()));
> >> +        StreamSource response = dispatcher.invoke(request);
> >> +
> >> +        assertEquals(requestString, StaxUtils.toString(response));
> >> +    }
> >> }
> >>
> >> Modified:
> >> cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/
> >> systest/jaxws/Server.java
> >> URL:
> >> http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/systests/jaxws/
> >> src/test/java/org/apache/cxf/systest/jaxws/Server.java?rev=1560703&r1
> >> =1560702&r2=1560703&view=diff
> >>
> ==========================================================
> ===========
> >> =========
> >> ---
> >> cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/
> >> systest/jaxws/Server.java (original)
> >> +++ cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/
> >> +++ cxf/systest/jaxws/Server.java Thu Jan 23 14:53:47 2014
> >> @@ -25,8 +25,14 @@ import java.util.List; import
> >> java.util.concurrent.Future;
> >>
> >> import javax.jws.WebService;
> >> +import javax.xml.transform.Source;
> >> +import javax.xml.transform.stream.StreamSource;
> >> import javax.xml.ws.AsyncHandler;
> >> import javax.xml.ws.Endpoint;
> >> +import javax.xml.ws.Provider;
> >> +import javax.xml.ws.Service;
> >> +import javax.xml.ws.ServiceMode;
> >> +import javax.xml.ws.WebServiceProvider;
> >>
> >> import org.apache.cxf.annotations.UseAsyncMethod;
> >> import org.apache.cxf.interceptor.URIMappingInterceptor;
> >> @@ -60,6 +66,10 @@ public class Server extends AbstractBusT
> >>          address = "http://localhost:" + PORT +
> "/SoapContext/AsyncSoapPort";
> >>          eps.add(Endpoint.publish(address, implementor));
> >>
> >> +        implementor = new AsyncEchoProvider();
> >> +        address = "http://localhost:" + PORT +
> "/SoapContext/AsyncEchoProvider";
> >> +        eps.add(Endpoint.publish(address, implementor));
> >> +
> >>          implementor = new GreeterImplMultiPort();
> >>          address = "http://localhost:" + PORT + "/MultiPort/GreeterPort";
> >>          eps.add(Endpoint.publish(address, implementor)); @@ -146,6
> >> +156,33 @@ public class Server extends AbstractBusT
> >>          }
> >>      }
> >>
> >> +    @WebServiceProvider
> >> +    @ServiceMode(value = Service.Mode.PAYLOAD)
> >> +    public class AsyncEchoProvider implements Provider<StreamSource>
> >> + {
> >> +
> >> +        @Override
> >> +        @UseAsyncMethod
> >> +        public StreamSource invoke(StreamSource request) {
> >> +            throw new RuntimeException("Should be async");
> >> +        }
> >> +
> >> +        public Future<?> invokeAsync(final StreamSource s, final
> AsyncHandler<Source> asyncHandler) {
> >> +            final ServerAsyncResponse<Source> r = new
> ServerAsyncResponse<Source>();
> >> +            new Thread() {
> >> +                public void run() {
> >> +                    try {
> >> +                        Thread.sleep(500);
> >> +                    } catch (InterruptedException e) {
> >> +                        // ignore
> >> +                    }
> >> +                    r.set(s);
> >> +                    asyncHandler.handleResponse(r);
> >> +                }
> >> +            } .start();
> >> +            return r;
> >> +        }
> >> +    }
> >> +
> >>      public static void main(String[] args) {
> >>          try {
> >>              Server s = new Server();
> >>
> >>
> 
> 
> --
> Alessio Soldano
> Web Service Lead, JBoss


RE: svn commit: r1560703 - in /cxf/branches/2.7.x-fixes: api/src/main/java/org/apache/cxf/service/invoker/ rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/ systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/

Posted by Andrei Shakirin <as...@talend.com>.
Have updated in a way suggested by Dan, however strongly said compatibility is still broken:

if users override old AbstarctInvoker.adjustMethodAndParams() and just call existing AbstarctInvoker.invoke() method, the overriding adjustMethodAndParams() will not be invoked anymore (because invoke() calls a new one with serviceObjectClass argument) - a drawback of subclassing, making dependent on internal method implementation :(

That will not be a problem in case described by Alessio, when AbstractInvoker.invoke() method is overridden and old adjustMethodAndParams() is called.

I thinking about 100% compatible solution without changing adjustMethodAndParams() signature at all:
- temporary saving serviceObjectClass into exchange; 
- passing serviceObjectClass through ThreadLocal;
- repeatedly invoking of AbstractInvoker.getServiceObject() from AbstractJAXWSMethodInvoker currently causes deadlock, because PooledFactory.createObject(Exchange) tries to get Object from empty pool. This way likely will requires some additional changes/refactoring.

Does it makes sense or is it overkill and we can leave the code as it is: https://fisheye6.atlassian.com/rdiff/cxf?csid=1560923&u&N ?


Regards,
Andrei.

> -----Original Message-----
> From: Alessio Soldano [mailto:asoldano@redhat.com]
> Sent: Donnerstag, 23. Januar 2014 16:46
> To: dev@cxf.apache.org
> Cc: Daniel Kulp; ashakirin@apache.org
> Subject: Re: svn commit: r1560703 - in /cxf/branches/2.7.x-fixes:
> api/src/main/java/org/apache/cxf/service/invoker/
> rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/
> systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/
> 
> On 23/01/14 16:01, Daniel Kulp wrote:
> > Andrei,
> >
> > This changes a protected method on a Abstract class that I believe either
> the JBoss folks or TomEE folks are subclassing.
> Currently, the JBossWS integration directly calls the
> adjustMethodAndParams method from a custom invoker extending
> JAXWSMethodInvoker and overriding invoke(Exchange exchange, Object o).
> So I'd also prefer what Dan suggests below on 2.7.x ;-)
> 
> Thanks
> 
> Alessio
> 
> 
> >     That's a concern to me as that would be a backwards compatible break.
> >
> > On 2.7.x, can we update the new method to handle when
> serviceObjectClass  is null and re-introduce the original method calling the
> new one with null?
> >
> >
> > Dan
> >
> >
> >
> > On Jan 23, 2014, at 9:53 AM, ashakirin@apache.org wrote:
> >
> >> Author: ashakirin
> >> Date: Thu Jan 23 14:53:47 2014
> >> New Revision: 1560703
> >>
> >> URL: http://svn.apache.org/r1560703
> >> Log:
> >> Backported [CXF-5512]: @UseAsyncMethod annotation doesn't work for
> >> classes implementing Provider<T>
> >>
> >> Modified:
> >>     cxf/branches/2.7.x-
> fixes/api/src/main/java/org/apache/cxf/service/invoker/AbstractInvoker.jav
> a
> >>     cxf/branches/2.7.x-
> fixes/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/AbstractJAXW
> SMethodInvoker.java
> >>     cxf/branches/2.7.x-
> fixes/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ClientServ
> erTest.java
> >>
> >> cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/
> >> systest/jaxws/Server.java
> >>
> >> Modified:
> >> cxf/branches/2.7.x-fixes/api/src/main/java/org/apache/cxf/service/inv
> >> oker/AbstractInvoker.java
> >> URL:
> >> http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/api/src/main/ja
> >>
> va/org/apache/cxf/service/invoker/AbstractInvoker.java?rev=1560703&r1
> >> =1560702&r2=1560703&view=diff
> >>
> ==========================================================
> ===========
> >> =========
> >> ---
> >> cxf/branches/2.7.x-fixes/api/src/main/java/org/apache/cxf/service/inv
> >> oker/AbstractInvoker.java (original)
> >> +++ cxf/branches/2.7.x-fixes/api/src/main/java/org/apache/cxf/service
> >> +++ /invoker/AbstractInvoker.java Thu Jan 23 14:53:47 2014
> >> @@ -66,7 +66,7 @@ public abstract class AbstractInvoker im
> >>                  params = new MessageContentsList(o);
> >>              }
> >>
> >> -            m = adjustMethodAndParams(m, exchange, params);
> >> +            m = adjustMethodAndParams(m, exchange, params,
> >> + serviceObject.getClass());
> >>
> >>              //Method m =
> (Method)bop.getOperationInfo().getProperty(Method.class.getName());
> >>              m = matchMethod(m, serviceObject); @@ -80,7 +80,8 @@
> >> public abstract class AbstractInvoker im
> >>
> >>      protected Method adjustMethodAndParams(Method m,
> >>                                             Exchange ex,
> >> -                                           List<Object> params) {
> >> +                                           List<Object> params,
> >> +                                           Class<?>
> >> + serviceObjectClass) {
> >>          //nothing to do
> >>          return m;
> >>      }
> >>
> >> Modified:
> >> cxf/branches/2.7.x-fixes/rt/frontend/jaxws/src/main/java/org/apache/c
> >> xf/jaxws/AbstractJAXWSMethodInvoker.java
> >> URL:
> >> http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/rt/frontend/jax
> >>
> ws/src/main/java/org/apache/cxf/jaxws/AbstractJAXWSMethodInvoker.jav
> a
> >> ?rev=1560703&r1=1560702&r2=1560703&view=diff
> >>
> ==========================================================
> ===========
> >> =========
> >> ---
> >> cxf/branches/2.7.x-fixes/rt/frontend/jaxws/src/main/java/org/apache/c
> >> xf/jaxws/AbstractJAXWSMethodInvoker.java (original)
> >> +++ cxf/branches/2.7.x-fixes/rt/frontend/jaxws/src/main/java/org/apac
> >> +++ he/cxf/jaxws/AbstractJAXWSMethodInvoker.java Thu Jan 23
> 14:53:47
> >> +++ 2014
> >> @@ -20,6 +20,8 @@
> >> package org.apache.cxf.jaxws;
> >>
> >> import java.lang.reflect.Method;
> >> +import java.lang.reflect.ParameterizedType;
> >> +import java.lang.reflect.Type;
> >> import java.util.ArrayList;
> >> import java.util.Collection;
> >> import java.util.HashMap;
> >> @@ -30,6 +32,7 @@ import java.util.concurrent.ExecutionExc
> >>
> >> import javax.activation.DataHandler;
> >> import javax.xml.ws.AsyncHandler;
> >> +import javax.xml.ws.Provider;
> >> import javax.xml.ws.Response;
> >> import javax.xml.ws.handler.MessageContext;
> >> import javax.xml.ws.handler.MessageContext.Scope;
> >> @@ -52,6 +55,7 @@ import org.apache.cxf.message.FaultMode; import
> >> org.apache.cxf.message.Message; import
> >> org.apache.cxf.message.MessageContentsList;
> >> import org.apache.cxf.message.MessageImpl;
> >> +import org.apache.cxf.service.factory.ServiceConstructionException;
> >> import org.apache.cxf.service.invoker.Factory;
> >> import org.apache.cxf.service.invoker.FactoryInvoker;
> >> import org.apache.cxf.service.invoker.SingletonFactory;
> >> @@ -77,18 +81,24 @@ public abstract class AbstractJAXWSMetho
> >>          }
> >>          return null;
> >>      }
> >> -    protected Method adjustMethodAndParams(Method m, Exchange ex,
> List<Object> params) {
> >> +
> >> +    @Override
> >> +    protected Method adjustMethodAndParams(Method mOriginal,
> Exchange ex, List<Object> params,
> >> +                                           Class<?> serviceObjectClass) {
> >> +        // If class implements Provider<T> interface, use overriden method
> from service object class
> >> +        // to check UseAsyncMethod annotation
> >> +        Method mso = getProviderServiceObjectMethod(mOriginal,
> >> + serviceObjectClass);
> >>
> >> -        UseAsyncMethod uam = m.getAnnotation(UseAsyncMethod.class);
> >> +        UseAsyncMethod uam =
> >> + mso.getAnnotation(UseAsyncMethod.class);
> >>          if (uam != null) {
> >>              BindingOperationInfo bop = ex.getBindingOperationInfo();
> >>              Method ret = bop.getProperty(ASYNC_METHOD, Method.class);
> >>              if (ret == null) {
> >> -                Class<?> ptypes[] = new
> Class<?>[m.getParameterTypes().length + 1];
> >> -                System.arraycopy(m.getParameterTypes(), 0, ptypes, 0,
> m.getParameterTypes().length);
> >> -                ptypes[m.getParameterTypes().length] = AsyncHandler.class;
> >> +                Class<?> ptypes[] = new
> Class<?>[mso.getParameterTypes().length + 1];
> >> +                System.arraycopy(mso.getParameterTypes(), 0, ptypes, 0,
> mso.getParameterTypes().length);
> >> +                ptypes[mso.getParameterTypes().length] =
> >> + AsyncHandler.class;
> >>                  try {
> >> -                    ret = m.getDeclaringClass().getMethod(m.getName() +
> "Async", ptypes);
> >> +                    ret =
> >> + mso.getDeclaringClass().getMethod(mso.getName() + "Async",
> ptypes);
> >>                      bop.setProperty(ASYNC_METHOD, ret);
> >>                  } catch (Throwable t) {
> >>                      //ignore
> >> @@ -115,9 +125,52 @@ public abstract class AbstractJAXWSMetho
> >>                  }
> >>              }
> >>          }
> >> -        return m;
> >> +        return mOriginal;
> >>      }
> >>
> >> +    private Method getProviderServiceObjectMethod(Method m,
> Class<?> serviceObjectClass) {
> >> +        if (!Provider.class.isAssignableFrom(serviceObjectClass)) {
> >> +            return m;
> >> +        }
> >> +        Class<?> currentSvcClass = serviceObjectClass;
> >> +        Class<?> genericType = null;
> >> +
> >> +        while (currentSvcClass != null) {
> >> +            genericType = getProviderGenericType(currentSvcClass);
> >> +            if (genericType != null) {
> >> +                break;
> >> +            }
> >> +            // Check superclass until top
> >> +            currentSvcClass = currentSvcClass.getSuperclass();
> >> +        }
> >> +        // Should never happens
> >> +        if (genericType == null) {
> >> +            return m;
> >> +        }
> >> +        try {
> >> +            return serviceObjectClass.getMethod("invoke", genericType);
> >> +        } catch (Exception e) {
> >> +            throw new ServiceConstructionException(e);
> >> +        }
> >> +    }
> >> +
> >> +    private Class<?> getProviderGenericType(Class<?> svcClass) {
> >> +        Type[] interfaces = svcClass.getGenericInterfaces();
> >> +        for (Type interfaceType : interfaces) {
> >> +            if (interfaceType instanceof ParameterizedType) {
> >> +                ParameterizedType paramInterface =
> (ParameterizedType)interfaceType;
> >> +                if (!paramInterface.getRawType().equals(Provider.class)) {
> >> +                    continue;
> >> +                }
> >> +                Type[] typeArgs = paramInterface.getActualTypeArguments();
> >> +                if (typeArgs.length > 0) {
> >> +                    return (Class<?>)typeArgs[0];
> >> +                }
> >> +            }
> >> +        }
> >> +        return null;
> >> +    }
> >> +
> >>      class JaxwsServerHandler implements AsyncHandler<Object> {
> >>          Response<Object> r;
> >>          Continuation continuation;
> >>
> >> Modified:
> >> cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/
> >> systest/jaxws/ClientServerTest.java
> >> URL:
> >> http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/systests/jaxws/
> >> src/test/java/org/apache/cxf/systest/jaxws/ClientServerTest.java?rev=
> >> 1560703&r1=1560702&r2=1560703&view=diff
> >>
> ==========================================================
> ===========
> >> =========
> >> ---
> >> cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/
> >> systest/jaxws/ClientServerTest.java (original)
> >> +++ cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/
> >> +++ cxf/systest/jaxws/ClientServerTest.java Thu Jan 23 14:53:47 2014
> >> @@ -19,6 +19,7 @@
> >>
> >> package org.apache.cxf.systest.jaxws;
> >>
> >> +import java.io.ByteArrayInputStream;
> >> import java.io.InputStream;
> >> import java.lang.reflect.InvocationHandler;
> >> import java.lang.reflect.Method;
> >> @@ -41,8 +42,10 @@ import java.util.logging.Logger; import
> >> java.util.zip.GZIPInputStream;
> >>
> >> import javax.xml.namespace.QName;
> >> +import javax.xml.transform.stream.StreamSource;
> >> import javax.xml.ws.AsyncHandler;
> >> import javax.xml.ws.BindingProvider;
> >> +import javax.xml.ws.Dispatch;
> >> import javax.xml.ws.Endpoint;
> >> import javax.xml.ws.Response;
> >> import javax.xml.ws.Service;
> >> @@ -63,6 +66,7 @@ import org.apache.cxf.frontend.ClientPro import
> >> org.apache.cxf.helpers.XMLUtils; import
> >> org.apache.cxf.helpers.XPathUtils;
> >> import org.apache.cxf.message.Message;
> >> +import org.apache.cxf.staxutils.StaxUtils;
> >> import
> >> org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
> >> import org.apache.cxf.transport.http.HTTPConduit;
> >> import org.apache.hello_world_soap_http.BadRecordLitFault;
> >> @@ -76,7 +80,6 @@ import org.apache.hello_world_soap_http.
> >> import
> org.apache.hello_world_soap_http.types.BareDocumentResponse;
> >> import
> org.apache.hello_world_soap_http.types.GreetMeLaterResponse;
> >> import org.apache.hello_world_soap_http.types.GreetMeResponse;
> >> -
> >> import org.junit.BeforeClass;
> >> import org.junit.Test;
> >>
> >> @@ -1057,4 +1060,19 @@ public class ClientServerTest extends Ab
> >>          assertEquals("Hello World", resp);
> >>      }
> >>
> >> +    @Test
> >> +    public void testEchoProviderAsync() throws Exception {
> >> +        String requestString = "<echo/>";
> >> +        Service service = Service.create(serviceName);
> >> +        service.addPort(fakePortName,
> javax.xml.ws.soap.SOAPBinding.SOAP11HTTP_BINDING,
> >> +                        "http://localhost:" + PORT +
> "/SoapContext/AsyncEchoProvider");
> >> +        Dispatch<StreamSource> dispatcher =
> service.createDispatch(fakePortName,
> >> +                                                                   StreamSource.class,
> >> +
> >> + Service.Mode.PAYLOAD);
> >> +
> >> +        StreamSource request = new StreamSource(new
> ByteArrayInputStream(requestString.getBytes()));
> >> +        StreamSource response = dispatcher.invoke(request);
> >> +
> >> +        assertEquals(requestString, StaxUtils.toString(response));
> >> +    }
> >> }
> >>
> >> Modified:
> >> cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/
> >> systest/jaxws/Server.java
> >> URL:
> >> http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/systests/jaxws/
> >> src/test/java/org/apache/cxf/systest/jaxws/Server.java?rev=1560703&r1
> >> =1560702&r2=1560703&view=diff
> >>
> ==========================================================
> ===========
> >> =========
> >> ---
> >> cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/
> >> systest/jaxws/Server.java (original)
> >> +++ cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/
> >> +++ cxf/systest/jaxws/Server.java Thu Jan 23 14:53:47 2014
> >> @@ -25,8 +25,14 @@ import java.util.List; import
> >> java.util.concurrent.Future;
> >>
> >> import javax.jws.WebService;
> >> +import javax.xml.transform.Source;
> >> +import javax.xml.transform.stream.StreamSource;
> >> import javax.xml.ws.AsyncHandler;
> >> import javax.xml.ws.Endpoint;
> >> +import javax.xml.ws.Provider;
> >> +import javax.xml.ws.Service;
> >> +import javax.xml.ws.ServiceMode;
> >> +import javax.xml.ws.WebServiceProvider;
> >>
> >> import org.apache.cxf.annotations.UseAsyncMethod;
> >> import org.apache.cxf.interceptor.URIMappingInterceptor;
> >> @@ -60,6 +66,10 @@ public class Server extends AbstractBusT
> >>          address = "http://localhost:" + PORT +
> "/SoapContext/AsyncSoapPort";
> >>          eps.add(Endpoint.publish(address, implementor));
> >>
> >> +        implementor = new AsyncEchoProvider();
> >> +        address = "http://localhost:" + PORT +
> "/SoapContext/AsyncEchoProvider";
> >> +        eps.add(Endpoint.publish(address, implementor));
> >> +
> >>          implementor = new GreeterImplMultiPort();
> >>          address = "http://localhost:" + PORT + "/MultiPort/GreeterPort";
> >>          eps.add(Endpoint.publish(address, implementor)); @@ -146,6
> >> +156,33 @@ public class Server extends AbstractBusT
> >>          }
> >>      }
> >>
> >> +    @WebServiceProvider
> >> +    @ServiceMode(value = Service.Mode.PAYLOAD)
> >> +    public class AsyncEchoProvider implements Provider<StreamSource>
> >> + {
> >> +
> >> +        @Override
> >> +        @UseAsyncMethod
> >> +        public StreamSource invoke(StreamSource request) {
> >> +            throw new RuntimeException("Should be async");
> >> +        }
> >> +
> >> +        public Future<?> invokeAsync(final StreamSource s, final
> AsyncHandler<Source> asyncHandler) {
> >> +            final ServerAsyncResponse<Source> r = new
> ServerAsyncResponse<Source>();
> >> +            new Thread() {
> >> +                public void run() {
> >> +                    try {
> >> +                        Thread.sleep(500);
> >> +                    } catch (InterruptedException e) {
> >> +                        // ignore
> >> +                    }
> >> +                    r.set(s);
> >> +                    asyncHandler.handleResponse(r);
> >> +                }
> >> +            } .start();
> >> +            return r;
> >> +        }
> >> +    }
> >> +
> >>      public static void main(String[] args) {
> >>          try {
> >>              Server s = new Server();
> >>
> >>
> 
> 
> --
> Alessio Soldano
> Web Service Lead, JBoss


Re: svn commit: r1560703 - in /cxf/branches/2.7.x-fixes: api/src/main/java/org/apache/cxf/service/invoker/ rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/ systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/

Posted by Alessio Soldano <as...@redhat.com>.
On 23/01/14 16:01, Daniel Kulp wrote:
> Andrei,
>
> This changes a protected method on a Abstract class that I believe either the JBoss folks or TomEE folks are subclassing.
Currently, the JBossWS integration directly calls the 
adjustMethodAndParams method from a custom invoker extending 
JAXWSMethodInvoker and overriding invoke(Exchange exchange, Object o).
So I'd also prefer what Dan suggests below on 2.7.x ;-)

Thanks

Alessio


>     That’s a concern to me as that would be a backwards compatible break.
>
> On 2.7.x, can we update the new method to handle when serviceObjectClass  is null and re-introduce the original method calling the new one with null?
>
>
> Dan
>
>
>
> On Jan 23, 2014, at 9:53 AM, ashakirin@apache.org wrote:
>
>> Author: ashakirin
>> Date: Thu Jan 23 14:53:47 2014
>> New Revision: 1560703
>>
>> URL: http://svn.apache.org/r1560703
>> Log:
>> Backported [CXF-5512]: @UseAsyncMethod annotation doesn't work for classes implementing Provider<T>
>>
>> Modified:
>>     cxf/branches/2.7.x-fixes/api/src/main/java/org/apache/cxf/service/invoker/AbstractInvoker.java
>>     cxf/branches/2.7.x-fixes/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/AbstractJAXWSMethodInvoker.java
>>     cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ClientServerTest.java
>>     cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/Server.java
>>
>> Modified: cxf/branches/2.7.x-fixes/api/src/main/java/org/apache/cxf/service/invoker/AbstractInvoker.java
>> URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/api/src/main/java/org/apache/cxf/service/invoker/AbstractInvoker.java?rev=1560703&r1=1560702&r2=1560703&view=diff
>> ==============================================================================
>> --- cxf/branches/2.7.x-fixes/api/src/main/java/org/apache/cxf/service/invoker/AbstractInvoker.java (original)
>> +++ cxf/branches/2.7.x-fixes/api/src/main/java/org/apache/cxf/service/invoker/AbstractInvoker.java Thu Jan 23 14:53:47 2014
>> @@ -66,7 +66,7 @@ public abstract class AbstractInvoker im
>>                  params = new MessageContentsList(o);
>>              }
>>
>> -            m = adjustMethodAndParams(m, exchange, params);
>> +            m = adjustMethodAndParams(m, exchange, params, serviceObject.getClass());
>>
>>              //Method m = (Method)bop.getOperationInfo().getProperty(Method.class.getName());
>>              m = matchMethod(m, serviceObject);
>> @@ -80,7 +80,8 @@ public abstract class AbstractInvoker im
>>
>>      protected Method adjustMethodAndParams(Method m,
>>                                             Exchange ex,
>> -                                           List<Object> params) {
>> +                                           List<Object> params,
>> +                                           Class<?> serviceObjectClass) {
>>          //nothing to do
>>          return m;
>>      }
>>
>> Modified: cxf/branches/2.7.x-fixes/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/AbstractJAXWSMethodInvoker.java
>> URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/AbstractJAXWSMethodInvoker.java?rev=1560703&r1=1560702&r2=1560703&view=diff
>> ==============================================================================
>> --- cxf/branches/2.7.x-fixes/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/AbstractJAXWSMethodInvoker.java (original)
>> +++ cxf/branches/2.7.x-fixes/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/AbstractJAXWSMethodInvoker.java Thu Jan 23 14:53:47 2014
>> @@ -20,6 +20,8 @@
>> package org.apache.cxf.jaxws;
>>
>> import java.lang.reflect.Method;
>> +import java.lang.reflect.ParameterizedType;
>> +import java.lang.reflect.Type;
>> import java.util.ArrayList;
>> import java.util.Collection;
>> import java.util.HashMap;
>> @@ -30,6 +32,7 @@ import java.util.concurrent.ExecutionExc
>>
>> import javax.activation.DataHandler;
>> import javax.xml.ws.AsyncHandler;
>> +import javax.xml.ws.Provider;
>> import javax.xml.ws.Response;
>> import javax.xml.ws.handler.MessageContext;
>> import javax.xml.ws.handler.MessageContext.Scope;
>> @@ -52,6 +55,7 @@ import org.apache.cxf.message.FaultMode;
>> import org.apache.cxf.message.Message;
>> import org.apache.cxf.message.MessageContentsList;
>> import org.apache.cxf.message.MessageImpl;
>> +import org.apache.cxf.service.factory.ServiceConstructionException;
>> import org.apache.cxf.service.invoker.Factory;
>> import org.apache.cxf.service.invoker.FactoryInvoker;
>> import org.apache.cxf.service.invoker.SingletonFactory;
>> @@ -77,18 +81,24 @@ public abstract class AbstractJAXWSMetho
>>          }
>>          return null;
>>      }
>> -    protected Method adjustMethodAndParams(Method m, Exchange ex, List<Object> params) {
>> +
>> +    @Override
>> +    protected Method adjustMethodAndParams(Method mOriginal, Exchange ex, List<Object> params,
>> +                                           Class<?> serviceObjectClass) {
>> +        // If class implements Provider<T> interface, use overriden method from service object class
>> +        // to check UseAsyncMethod annotation
>> +        Method mso = getProviderServiceObjectMethod(mOriginal, serviceObjectClass);
>>
>> -        UseAsyncMethod uam = m.getAnnotation(UseAsyncMethod.class);
>> +        UseAsyncMethod uam = mso.getAnnotation(UseAsyncMethod.class);
>>          if (uam != null) {
>>              BindingOperationInfo bop = ex.getBindingOperationInfo();
>>              Method ret = bop.getProperty(ASYNC_METHOD, Method.class);
>>              if (ret == null) {
>> -                Class<?> ptypes[] = new Class<?>[m.getParameterTypes().length + 1];
>> -                System.arraycopy(m.getParameterTypes(), 0, ptypes, 0, m.getParameterTypes().length);
>> -                ptypes[m.getParameterTypes().length] = AsyncHandler.class;
>> +                Class<?> ptypes[] = new Class<?>[mso.getParameterTypes().length + 1];
>> +                System.arraycopy(mso.getParameterTypes(), 0, ptypes, 0, mso.getParameterTypes().length);
>> +                ptypes[mso.getParameterTypes().length] = AsyncHandler.class;
>>                  try {
>> -                    ret = m.getDeclaringClass().getMethod(m.getName() + "Async", ptypes);
>> +                    ret = mso.getDeclaringClass().getMethod(mso.getName() + "Async", ptypes);
>>                      bop.setProperty(ASYNC_METHOD, ret);
>>                  } catch (Throwable t) {
>>                      //ignore
>> @@ -115,9 +125,52 @@ public abstract class AbstractJAXWSMetho
>>                  }
>>              }
>>          }
>> -        return m;
>> +        return mOriginal;
>>      }
>>
>> +    private Method getProviderServiceObjectMethod(Method m, Class<?> serviceObjectClass) {
>> +        if (!Provider.class.isAssignableFrom(serviceObjectClass)) {
>> +            return m;
>> +        }
>> +        Class<?> currentSvcClass = serviceObjectClass;
>> +        Class<?> genericType = null;
>> +
>> +        while (currentSvcClass != null) {
>> +            genericType = getProviderGenericType(currentSvcClass);
>> +            if (genericType != null) {
>> +                break;
>> +            }
>> +            // Check superclass until top
>> +            currentSvcClass = currentSvcClass.getSuperclass();
>> +        }
>> +        // Should never happens
>> +        if (genericType == null) {
>> +            return m;
>> +        }
>> +        try {
>> +            return serviceObjectClass.getMethod("invoke", genericType);
>> +        } catch (Exception e) {
>> +            throw new ServiceConstructionException(e);
>> +        }
>> +    }
>> +
>> +    private Class<?> getProviderGenericType(Class<?> svcClass) {
>> +        Type[] interfaces = svcClass.getGenericInterfaces();
>> +        for (Type interfaceType : interfaces) {
>> +            if (interfaceType instanceof ParameterizedType) {
>> +                ParameterizedType paramInterface = (ParameterizedType)interfaceType;
>> +                if (!paramInterface.getRawType().equals(Provider.class)) {
>> +                    continue;
>> +                }
>> +                Type[] typeArgs = paramInterface.getActualTypeArguments();
>> +                if (typeArgs.length > 0) {
>> +                    return (Class<?>)typeArgs[0];
>> +                }
>> +            }
>> +        }
>> +        return null;
>> +    }
>> +
>>      class JaxwsServerHandler implements AsyncHandler<Object> {
>>          Response<Object> r;
>>          Continuation continuation;
>>
>> Modified: cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ClientServerTest.java
>> URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ClientServerTest.java?rev=1560703&r1=1560702&r2=1560703&view=diff
>> ==============================================================================
>> --- cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ClientServerTest.java (original)
>> +++ cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ClientServerTest.java Thu Jan 23 14:53:47 2014
>> @@ -19,6 +19,7 @@
>>
>> package org.apache.cxf.systest.jaxws;
>>
>> +import java.io.ByteArrayInputStream;
>> import java.io.InputStream;
>> import java.lang.reflect.InvocationHandler;
>> import java.lang.reflect.Method;
>> @@ -41,8 +42,10 @@ import java.util.logging.Logger;
>> import java.util.zip.GZIPInputStream;
>>
>> import javax.xml.namespace.QName;
>> +import javax.xml.transform.stream.StreamSource;
>> import javax.xml.ws.AsyncHandler;
>> import javax.xml.ws.BindingProvider;
>> +import javax.xml.ws.Dispatch;
>> import javax.xml.ws.Endpoint;
>> import javax.xml.ws.Response;
>> import javax.xml.ws.Service;
>> @@ -63,6 +66,7 @@ import org.apache.cxf.frontend.ClientPro
>> import org.apache.cxf.helpers.XMLUtils;
>> import org.apache.cxf.helpers.XPathUtils;
>> import org.apache.cxf.message.Message;
>> +import org.apache.cxf.staxutils.StaxUtils;
>> import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
>> import org.apache.cxf.transport.http.HTTPConduit;
>> import org.apache.hello_world_soap_http.BadRecordLitFault;
>> @@ -76,7 +80,6 @@ import org.apache.hello_world_soap_http.
>> import org.apache.hello_world_soap_http.types.BareDocumentResponse;
>> import org.apache.hello_world_soap_http.types.GreetMeLaterResponse;
>> import org.apache.hello_world_soap_http.types.GreetMeResponse;
>> -
>> import org.junit.BeforeClass;
>> import org.junit.Test;
>>
>> @@ -1057,4 +1060,19 @@ public class ClientServerTest extends Ab
>>          assertEquals("Hello World", resp);
>>      }
>>
>> +    @Test
>> +    public void testEchoProviderAsync() throws Exception {
>> +        String requestString = "<echo/>";
>> +        Service service = Service.create(serviceName);
>> +        service.addPort(fakePortName, javax.xml.ws.soap.SOAPBinding.SOAP11HTTP_BINDING,
>> +                        "http://localhost:" + PORT + "/SoapContext/AsyncEchoProvider");
>> +        Dispatch<StreamSource> dispatcher = service.createDispatch(fakePortName,
>> +                                                                   StreamSource.class,
>> +                                                                   Service.Mode.PAYLOAD);
>> +
>> +        StreamSource request = new StreamSource(new ByteArrayInputStream(requestString.getBytes()));
>> +        StreamSource response = dispatcher.invoke(request);
>> +
>> +        assertEquals(requestString, StaxUtils.toString(response));
>> +    }
>> }
>>
>> Modified: cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/Server.java
>> URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/Server.java?rev=1560703&r1=1560702&r2=1560703&view=diff
>> ==============================================================================
>> --- cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/Server.java (original)
>> +++ cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/Server.java Thu Jan 23 14:53:47 2014
>> @@ -25,8 +25,14 @@ import java.util.List;
>> import java.util.concurrent.Future;
>>
>> import javax.jws.WebService;
>> +import javax.xml.transform.Source;
>> +import javax.xml.transform.stream.StreamSource;
>> import javax.xml.ws.AsyncHandler;
>> import javax.xml.ws.Endpoint;
>> +import javax.xml.ws.Provider;
>> +import javax.xml.ws.Service;
>> +import javax.xml.ws.ServiceMode;
>> +import javax.xml.ws.WebServiceProvider;
>>
>> import org.apache.cxf.annotations.UseAsyncMethod;
>> import org.apache.cxf.interceptor.URIMappingInterceptor;
>> @@ -60,6 +66,10 @@ public class Server extends AbstractBusT
>>          address = "http://localhost:" + PORT + "/SoapContext/AsyncSoapPort";
>>          eps.add(Endpoint.publish(address, implementor));
>>
>> +        implementor = new AsyncEchoProvider();
>> +        address = "http://localhost:" + PORT + "/SoapContext/AsyncEchoProvider";
>> +        eps.add(Endpoint.publish(address, implementor));
>> +
>>          implementor = new GreeterImplMultiPort();
>>          address = "http://localhost:" + PORT + "/MultiPort/GreeterPort";
>>          eps.add(Endpoint.publish(address, implementor));
>> @@ -146,6 +156,33 @@ public class Server extends AbstractBusT
>>          }
>>      }
>>
>> +    @WebServiceProvider
>> +    @ServiceMode(value = Service.Mode.PAYLOAD)
>> +    public class AsyncEchoProvider implements Provider<StreamSource> {
>> +
>> +        @Override
>> +        @UseAsyncMethod
>> +        public StreamSource invoke(StreamSource request) {
>> +            throw new RuntimeException("Should be async");
>> +        }
>> +
>> +        public Future<?> invokeAsync(final StreamSource s, final AsyncHandler<Source> asyncHandler) {
>> +            final ServerAsyncResponse<Source> r = new ServerAsyncResponse<Source>();
>> +            new Thread() {
>> +                public void run() {
>> +                    try {
>> +                        Thread.sleep(500);
>> +                    } catch (InterruptedException e) {
>> +                        // ignore
>> +                    }
>> +                    r.set(s);
>> +                    asyncHandler.handleResponse(r);
>> +                }
>> +            } .start();
>> +            return r;
>> +        }
>> +    }
>> +
>>      public static void main(String[] args) {
>>          try {
>>              Server s = new Server();
>>
>>


-- 
Alessio Soldano
Web Service Lead, JBoss


Re: svn commit: r1560703 - in /cxf/branches/2.7.x-fixes: api/src/main/java/org/apache/cxf/service/invoker/ rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/ systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/

Posted by Daniel Kulp <dk...@apache.org>.
Andrei,

This changes a protected method on a Abstract class that I believe either the JBoss folks or TomEE folks are subclassing.   That’s a concern to me as that would be a backwards compatible break.

On 2.7.x, can we update the new method to handle when serviceObjectClass  is null and re-introduce the original method calling the new one with null?


Dan



On Jan 23, 2014, at 9:53 AM, ashakirin@apache.org wrote:

> Author: ashakirin
> Date: Thu Jan 23 14:53:47 2014
> New Revision: 1560703
> 
> URL: http://svn.apache.org/r1560703
> Log:
> Backported [CXF-5512]: @UseAsyncMethod annotation doesn't work for classes implementing Provider<T>
> 
> Modified:
>    cxf/branches/2.7.x-fixes/api/src/main/java/org/apache/cxf/service/invoker/AbstractInvoker.java
>    cxf/branches/2.7.x-fixes/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/AbstractJAXWSMethodInvoker.java
>    cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ClientServerTest.java
>    cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/Server.java
> 
> Modified: cxf/branches/2.7.x-fixes/api/src/main/java/org/apache/cxf/service/invoker/AbstractInvoker.java
> URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/api/src/main/java/org/apache/cxf/service/invoker/AbstractInvoker.java?rev=1560703&r1=1560702&r2=1560703&view=diff
> ==============================================================================
> --- cxf/branches/2.7.x-fixes/api/src/main/java/org/apache/cxf/service/invoker/AbstractInvoker.java (original)
> +++ cxf/branches/2.7.x-fixes/api/src/main/java/org/apache/cxf/service/invoker/AbstractInvoker.java Thu Jan 23 14:53:47 2014
> @@ -66,7 +66,7 @@ public abstract class AbstractInvoker im
>                 params = new MessageContentsList(o);
>             }
> 
> -            m = adjustMethodAndParams(m, exchange, params);
> +            m = adjustMethodAndParams(m, exchange, params, serviceObject.getClass());
> 
>             //Method m = (Method)bop.getOperationInfo().getProperty(Method.class.getName());
>             m = matchMethod(m, serviceObject);
> @@ -80,7 +80,8 @@ public abstract class AbstractInvoker im
> 
>     protected Method adjustMethodAndParams(Method m,
>                                            Exchange ex,
> -                                           List<Object> params) {
> +                                           List<Object> params,
> +                                           Class<?> serviceObjectClass) {
>         //nothing to do
>         return m;
>     }
> 
> Modified: cxf/branches/2.7.x-fixes/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/AbstractJAXWSMethodInvoker.java
> URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/AbstractJAXWSMethodInvoker.java?rev=1560703&r1=1560702&r2=1560703&view=diff
> ==============================================================================
> --- cxf/branches/2.7.x-fixes/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/AbstractJAXWSMethodInvoker.java (original)
> +++ cxf/branches/2.7.x-fixes/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/AbstractJAXWSMethodInvoker.java Thu Jan 23 14:53:47 2014
> @@ -20,6 +20,8 @@
> package org.apache.cxf.jaxws;
> 
> import java.lang.reflect.Method;
> +import java.lang.reflect.ParameterizedType;
> +import java.lang.reflect.Type;
> import java.util.ArrayList;
> import java.util.Collection;
> import java.util.HashMap;
> @@ -30,6 +32,7 @@ import java.util.concurrent.ExecutionExc
> 
> import javax.activation.DataHandler;
> import javax.xml.ws.AsyncHandler;
> +import javax.xml.ws.Provider;
> import javax.xml.ws.Response;
> import javax.xml.ws.handler.MessageContext;
> import javax.xml.ws.handler.MessageContext.Scope;
> @@ -52,6 +55,7 @@ import org.apache.cxf.message.FaultMode;
> import org.apache.cxf.message.Message;
> import org.apache.cxf.message.MessageContentsList;
> import org.apache.cxf.message.MessageImpl;
> +import org.apache.cxf.service.factory.ServiceConstructionException;
> import org.apache.cxf.service.invoker.Factory;
> import org.apache.cxf.service.invoker.FactoryInvoker;
> import org.apache.cxf.service.invoker.SingletonFactory;
> @@ -77,18 +81,24 @@ public abstract class AbstractJAXWSMetho
>         }
>         return null;
>     }
> -    protected Method adjustMethodAndParams(Method m, Exchange ex, List<Object> params) {
> +
> +    @Override
> +    protected Method adjustMethodAndParams(Method mOriginal, Exchange ex, List<Object> params,
> +                                           Class<?> serviceObjectClass) {
> +        // If class implements Provider<T> interface, use overriden method from service object class
> +        // to check UseAsyncMethod annotation
> +        Method mso = getProviderServiceObjectMethod(mOriginal, serviceObjectClass);
> 
> -        UseAsyncMethod uam = m.getAnnotation(UseAsyncMethod.class);
> +        UseAsyncMethod uam = mso.getAnnotation(UseAsyncMethod.class);
>         if (uam != null) {
>             BindingOperationInfo bop = ex.getBindingOperationInfo();
>             Method ret = bop.getProperty(ASYNC_METHOD, Method.class);
>             if (ret == null) {
> -                Class<?> ptypes[] = new Class<?>[m.getParameterTypes().length + 1];
> -                System.arraycopy(m.getParameterTypes(), 0, ptypes, 0, m.getParameterTypes().length);
> -                ptypes[m.getParameterTypes().length] = AsyncHandler.class;
> +                Class<?> ptypes[] = new Class<?>[mso.getParameterTypes().length + 1];
> +                System.arraycopy(mso.getParameterTypes(), 0, ptypes, 0, mso.getParameterTypes().length);
> +                ptypes[mso.getParameterTypes().length] = AsyncHandler.class;
>                 try {
> -                    ret = m.getDeclaringClass().getMethod(m.getName() + "Async", ptypes);
> +                    ret = mso.getDeclaringClass().getMethod(mso.getName() + "Async", ptypes);
>                     bop.setProperty(ASYNC_METHOD, ret);
>                 } catch (Throwable t) {
>                     //ignore
> @@ -115,9 +125,52 @@ public abstract class AbstractJAXWSMetho
>                 }
>             }
>         }
> -        return m;
> +        return mOriginal;
>     }
> 
> +    private Method getProviderServiceObjectMethod(Method m, Class<?> serviceObjectClass) {
> +        if (!Provider.class.isAssignableFrom(serviceObjectClass)) {
> +            return m;
> +        }
> +        Class<?> currentSvcClass = serviceObjectClass;
> +        Class<?> genericType = null;
> +
> +        while (currentSvcClass != null) {
> +            genericType = getProviderGenericType(currentSvcClass);
> +            if (genericType != null) {
> +                break;
> +            }
> +            // Check superclass until top
> +            currentSvcClass = currentSvcClass.getSuperclass();
> +        }
> +        // Should never happens
> +        if (genericType == null) {
> +            return m;
> +        }
> +        try {
> +            return serviceObjectClass.getMethod("invoke", genericType);
> +        } catch (Exception e) {
> +            throw new ServiceConstructionException(e);
> +        }
> +    }
> +
> +    private Class<?> getProviderGenericType(Class<?> svcClass) {
> +        Type[] interfaces = svcClass.getGenericInterfaces();
> +        for (Type interfaceType : interfaces) {
> +            if (interfaceType instanceof ParameterizedType) {
> +                ParameterizedType paramInterface = (ParameterizedType)interfaceType;
> +                if (!paramInterface.getRawType().equals(Provider.class)) {
> +                    continue;
> +                }
> +                Type[] typeArgs = paramInterface.getActualTypeArguments();
> +                if (typeArgs.length > 0) {
> +                    return (Class<?>)typeArgs[0];
> +                }
> +            }
> +        }
> +        return null;
> +    }
> +
>     class JaxwsServerHandler implements AsyncHandler<Object> {
>         Response<Object> r;
>         Continuation continuation;
> 
> Modified: cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ClientServerTest.java
> URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ClientServerTest.java?rev=1560703&r1=1560702&r2=1560703&view=diff
> ==============================================================================
> --- cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ClientServerTest.java (original)
> +++ cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ClientServerTest.java Thu Jan 23 14:53:47 2014
> @@ -19,6 +19,7 @@
> 
> package org.apache.cxf.systest.jaxws;
> 
> +import java.io.ByteArrayInputStream;
> import java.io.InputStream;
> import java.lang.reflect.InvocationHandler;
> import java.lang.reflect.Method;
> @@ -41,8 +42,10 @@ import java.util.logging.Logger;
> import java.util.zip.GZIPInputStream;
> 
> import javax.xml.namespace.QName;
> +import javax.xml.transform.stream.StreamSource;
> import javax.xml.ws.AsyncHandler;
> import javax.xml.ws.BindingProvider;
> +import javax.xml.ws.Dispatch;
> import javax.xml.ws.Endpoint;
> import javax.xml.ws.Response;
> import javax.xml.ws.Service;
> @@ -63,6 +66,7 @@ import org.apache.cxf.frontend.ClientPro
> import org.apache.cxf.helpers.XMLUtils;
> import org.apache.cxf.helpers.XPathUtils;
> import org.apache.cxf.message.Message;
> +import org.apache.cxf.staxutils.StaxUtils;
> import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
> import org.apache.cxf.transport.http.HTTPConduit;
> import org.apache.hello_world_soap_http.BadRecordLitFault;
> @@ -76,7 +80,6 @@ import org.apache.hello_world_soap_http.
> import org.apache.hello_world_soap_http.types.BareDocumentResponse;
> import org.apache.hello_world_soap_http.types.GreetMeLaterResponse;
> import org.apache.hello_world_soap_http.types.GreetMeResponse;
> -
> import org.junit.BeforeClass;
> import org.junit.Test;
> 
> @@ -1057,4 +1060,19 @@ public class ClientServerTest extends Ab
>         assertEquals("Hello World", resp);
>     }
> 
> +    @Test
> +    public void testEchoProviderAsync() throws Exception {
> +        String requestString = "<echo/>";
> +        Service service = Service.create(serviceName);
> +        service.addPort(fakePortName, javax.xml.ws.soap.SOAPBinding.SOAP11HTTP_BINDING,
> +                        "http://localhost:" + PORT + "/SoapContext/AsyncEchoProvider");
> +        Dispatch<StreamSource> dispatcher = service.createDispatch(fakePortName,
> +                                                                   StreamSource.class,
> +                                                                   Service.Mode.PAYLOAD);
> +
> +        StreamSource request = new StreamSource(new ByteArrayInputStream(requestString.getBytes()));
> +        StreamSource response = dispatcher.invoke(request);
> +
> +        assertEquals(requestString, StaxUtils.toString(response));
> +    }
> }
> 
> Modified: cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/Server.java
> URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/Server.java?rev=1560703&r1=1560702&r2=1560703&view=diff
> ==============================================================================
> --- cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/Server.java (original)
> +++ cxf/branches/2.7.x-fixes/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/Server.java Thu Jan 23 14:53:47 2014
> @@ -25,8 +25,14 @@ import java.util.List;
> import java.util.concurrent.Future;
> 
> import javax.jws.WebService;
> +import javax.xml.transform.Source;
> +import javax.xml.transform.stream.StreamSource;
> import javax.xml.ws.AsyncHandler;
> import javax.xml.ws.Endpoint;
> +import javax.xml.ws.Provider;
> +import javax.xml.ws.Service;
> +import javax.xml.ws.ServiceMode;
> +import javax.xml.ws.WebServiceProvider;
> 
> import org.apache.cxf.annotations.UseAsyncMethod;
> import org.apache.cxf.interceptor.URIMappingInterceptor;
> @@ -60,6 +66,10 @@ public class Server extends AbstractBusT
>         address = "http://localhost:" + PORT + "/SoapContext/AsyncSoapPort";
>         eps.add(Endpoint.publish(address, implementor));
> 
> +        implementor = new AsyncEchoProvider();
> +        address = "http://localhost:" + PORT + "/SoapContext/AsyncEchoProvider";
> +        eps.add(Endpoint.publish(address, implementor));
> +
>         implementor = new GreeterImplMultiPort();
>         address = "http://localhost:" + PORT + "/MultiPort/GreeterPort";
>         eps.add(Endpoint.publish(address, implementor));
> @@ -146,6 +156,33 @@ public class Server extends AbstractBusT
>         }
>     }
> 
> +    @WebServiceProvider
> +    @ServiceMode(value = Service.Mode.PAYLOAD)
> +    public class AsyncEchoProvider implements Provider<StreamSource> {
> +
> +        @Override
> +        @UseAsyncMethod
> +        public StreamSource invoke(StreamSource request) {
> +            throw new RuntimeException("Should be async");
> +        }
> +
> +        public Future<?> invokeAsync(final StreamSource s, final AsyncHandler<Source> asyncHandler) {
> +            final ServerAsyncResponse<Source> r = new ServerAsyncResponse<Source>();
> +            new Thread() {
> +                public void run() {
> +                    try {
> +                        Thread.sleep(500);
> +                    } catch (InterruptedException e) {
> +                        // ignore
> +                    }
> +                    r.set(s);
> +                    asyncHandler.handleResponse(r);
> +                }
> +            } .start();
> +            return r;
> +        }
> +    }
> +
>     public static void main(String[] args) {
>         try {
>             Server s = new Server();
> 
> 

-- 
Daniel Kulp
dkulp@apache.org - http://dankulp.com/blog
Talend Community Coder - http://coders.talend.com