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, [email protected] 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 [email protected] - http://dankulp.com/blog Talend Community Coder - http://coders.talend.com
