You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by dk...@apache.org on 2009/12/15 03:37:41 UTC

svn commit: r890605 - in /cxf/trunk/rt/frontend: jaxws/src/main/java/org/apache/cxf/jaxws/ jaxws/src/main/java/org/apache/cxf/jaxws/support/ jaxws/src/test/java/org/apache/cxf/jaxws/ jaxws/src/test/java/org/apache/cxf/jaxws/service/ simple/src/main/jav...

Author: dkulp
Date: Tue Dec 15 02:37:40 2009
New Revision: 890605

URL: http://svn.apache.org/viewvc?rev=890605&view=rev
Log:
[CXF-1758] Allow some more advanced usages of Generics with JAX-WS

Added:
    cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/service/GenericsService2.java   (with props)
Modified:
    cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/JAXWSMethodDispatcher.java
    cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/WrapperClassGenerator.java
    cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/support/JaxWsImplementorInfo.java
    cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/support/JaxWsServiceFactoryBean.java
    cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/CodeFirstTest.java
    cxf/trunk/rt/frontend/simple/src/main/java/org/apache/cxf/service/factory/ReflectionServiceFactoryBean.java

Modified: cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/JAXWSMethodDispatcher.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/JAXWSMethodDispatcher.java?rev=890605&r1=890604&r2=890605&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/JAXWSMethodDispatcher.java (original)
+++ cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/JAXWSMethodDispatcher.java Tue Dec 15 02:37:40 2009
@@ -20,6 +20,9 @@
 package org.apache.cxf.jaxws;
 
 import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
 import java.util.logging.Logger;
 
 import org.apache.cxf.common.i18n.Message;
@@ -71,8 +74,32 @@
         
         if (!endpointClass.isAssignableFrom(method.getDeclaringClass())) {
             try {
-                method = endpointClass.getMethod(method.getName(), 
+                Method m2 = endpointClass.getMethod(method.getName(), 
                                                  (Class[])method.getParameterTypes());
+                if (Modifier.isVolatile(m2.getModifiers())) {
+                    //bridge method, need to map the generics
+                    Class params[] = method.getParameterTypes();
+                    for (Type t : method.getGenericParameterTypes()) {
+                        if (t instanceof TypeVariable) {
+                            TypeVariable tv = (TypeVariable)t;
+                            for (int x = 0; x < implInfo.getSEIClass().getTypeParameters().length; x++) {
+                                TypeVariable t2 = implInfo.getSEIClass().getTypeParameters()[x];
+                                if (t2.getName().equals(tv.getName())) {
+                                    params[x] = (Class)implInfo.getSEIType().getActualTypeArguments()[x];
+                                }
+                            }
+                        }
+                    }
+                    method = endpointClass.getMethod(method.getName(),
+                                                     params);
+                } else {
+                    method = m2;
+                }
+                try {
+                    method.setAccessible(true);
+                } catch (Throwable t) {
+                    //ignore
+                }                
             } catch (SecurityException e) {
                 throw new ServiceConstructionException(e);
             }

Modified: cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/WrapperClassGenerator.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/WrapperClassGenerator.java?rev=890605&r1=890604&r2=890605&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/WrapperClassGenerator.java (original)
+++ cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/WrapperClassGenerator.java Tue Dec 15 02:37:40 2009
@@ -181,10 +181,18 @@
         }
         
         def = findClass(className, method.getDeclaringClass());
-        if (def != null) {
-            wrapperPart.setTypeClass(def);
-            wrapperBeans.add(def);
-            return;
+        String origClassName = className;
+        int count = 0;
+        while (def != null) {
+            Boolean b = messageInfo.getProperty("parameterized", Boolean.class);
+            if (b != null && b) {
+                className = origClassName + (++count);
+                def = findClass(className, method.getDeclaringClass());
+            } else {
+                wrapperPart.setTypeClass(def);
+                wrapperBeans.add(def);
+                return;
+            }
         }
         String classFileName = periodToSlashes(className);
         cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, classFileName, null,

Modified: cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/support/JaxWsImplementorInfo.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/support/JaxWsImplementorInfo.java?rev=890605&r1=890604&r2=890605&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/support/JaxWsImplementorInfo.java (original)
+++ cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/support/JaxWsImplementorInfo.java Tue Dec 15 02:37:40 2009
@@ -49,6 +49,7 @@
 
     private Class<?> implementorClass;
     private Class<?> seiClass;
+    private ParameterizedType seiType;
     private List<WebService> wsAnnotations = new ArrayList<WebService>(2);
     private WebServiceProvider wsProviderAnnotation;
 
@@ -60,6 +61,9 @@
     public Class<?> getSEIClass() {
         return seiClass;
     }
+    public ParameterizedType getSEIType() {
+        return seiType;
+    }
 
     public Class<?> getImplementorClass() {
         return implementorClass;
@@ -287,6 +291,15 @@
                 throw new WebServiceException(expString);
             }
             wsAnnotations.add(seiAnnotation);
+            
+            for (int x = implementorClass.getInterfaces().length - 1; x >= 0; x--) {
+                if (seiClass.equals(implementorClass.getInterfaces()[x])) {
+                    Type type = implementorClass.getGenericInterfaces()[x];
+                    if (type instanceof ParameterizedType) {
+                        seiType = (ParameterizedType)type;
+                    }
+                }
+            }
         }
         wsProviderAnnotation = implementorClass.getAnnotation(WebServiceProvider.class);
     }

Modified: cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/support/JaxWsServiceFactoryBean.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/support/JaxWsServiceFactoryBean.java?rev=890605&r1=890604&r2=890605&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/support/JaxWsServiceFactoryBean.java (original)
+++ cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/support/JaxWsServiceFactoryBean.java Tue Dec 15 02:37:40 2009
@@ -117,6 +117,7 @@
         this.implInfo = implInfo;
         initConfiguration(implInfo);
         this.serviceClass = implInfo.getEndpointClass();
+        this.serviceType = implInfo.getSEIType();
         loadWSFeatureAnnotation(implInfo.getSEIClass(), implInfo.getImplementorClass());
     }
     
@@ -192,6 +193,7 @@
         }
         setJaxWsImplementorInfo(new JaxWsImplementorInfo(serviceClass));
         super.setServiceClass(getJaxWsImplementorInfo().getEndpointClass());
+        super.setServiceType(getJaxWsImplementorInfo().getSEIType());
     }
     @Override
     protected void checkServiceClassAnnotations(Class<?> sc) {

Modified: cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/CodeFirstTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/CodeFirstTest.java?rev=890605&r1=890604&r2=890605&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/CodeFirstTest.java (original)
+++ cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/CodeFirstTest.java Tue Dec 15 02:37:40 2009
@@ -47,6 +47,7 @@
 import org.apache.cxf.jaxws.service.Entity;
 import org.apache.cxf.jaxws.service.FooServiceImpl;
 import org.apache.cxf.jaxws.service.GenericsService;
+import org.apache.cxf.jaxws.service.GenericsService2;
 import org.apache.cxf.jaxws.service.Hello;
 import org.apache.cxf.jaxws.service.HelloInterface;
 import org.apache.cxf.jaxws.service.QueryResult;
@@ -339,6 +340,63 @@
     }
     
     @Test
+    public void testCXF1758() throws Exception {
+        JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean(); 
+        factory.setServiceBean(new GenericsService2Impl()); 
+        factory.setAddress("local://localhost/test"); 
+        Server server = null;
+        server = factory.create();
+        Document doc = getWSDLDocument(server);
+        org.apache.cxf.helpers.XMLUtils.printDOM(doc);
+        assertValid("//xsd:schema/xsd:complexType[@name='convert']/xsd:sequence/xsd:element[@type='xs:int']",
+                    doc);
+        
+        factory = new JaxWsServerFactoryBean(); 
+        factory.setServiceBean(new GenericsService2<Float, Double>() {
+            public Double convert(Float t) {
+                return t.doubleValue();
+            }
+
+            public GenericsService2.Value<Double> convert2(GenericsService2.Value<Float> in) {
+                return new GenericsService2.Value<Double>(in.getValue().doubleValue());
+            }
+        });
+        factory.setAddress("local://localhost/test2"); 
+        server = factory.create();
+        Document doc2 = getWSDLDocument(server);
+        //org.apache.cxf.helpers.XMLUtils.printDOM(doc2);
+        assertValid("//xsd:schema/xsd:complexType[@name='convert']/xsd:sequence/"
+                    + "xsd:element[@type='xs:float']",
+                    doc2);
+        
+        QName serviceName = new QName("http://service.jaxws.cxf.apache.org/", "Generics2");
+        QName portName = new QName("http://service.jaxws.cxf.apache.org/", "Generics2Port");
+
+        ServiceImpl service = new ServiceImpl(getBus(), (URL)null, serviceName, null);
+        service.addPort(portName, "http://schemas.xmlsoap.org/soap/",
+                        "local://localhost/test2"); 
+        
+        GenericsService2Typed proxy = service.getPort(portName,
+                                                      GenericsService2Typed.class);
+        assertEquals("", 3.14d, proxy.convert(3.14f), 0.00001);
+        assertEquals("", 3.14d, proxy.convert2(new GenericsService2.Value<Float>(3.14f)).getValue(), 0.00001);
+
+    }
+
+    public static interface GenericsService2Typed extends GenericsService2<Float, Double> {
+        
+    }
+    public static class GenericsService2Impl implements GenericsService2<Integer, String> {
+        public String convert(Integer t) {
+            return t.toString();
+        }
+
+        public GenericsService2.Value<String> convert2(GenericsService2.Value<Integer> in) {
+            return new GenericsService2.Value<String>(in.getValue().toString());
+        }
+    }
+    
+    @Test
     public void testCXF1510() throws Exception {
         JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean(); 
         factory.setServiceClass(NoRootBare.class); 

Added: cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/service/GenericsService2.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/service/GenericsService2.java?rev=890605&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/service/GenericsService2.java (added)
+++ cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/service/GenericsService2.java Tue Dec 15 02:37:40 2009
@@ -0,0 +1,51 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.jaxws.service;
+
+import javax.jws.WebService;
+
+/**
+ * 
+ */
+@WebService(targetNamespace = "http://jaxws.cxf.apache.org/")
+public interface GenericsService2<T, P> {
+    P convert(T t);
+    
+    Value<P> convert2(Value<T> in);
+    
+    public static class Value<V> {
+        V val;
+        
+        public Value() {
+            
+        }
+        public Value(V v) {
+            val = v;
+        }
+        
+        public V getValue() {
+            return val;
+        }
+        
+        public void setValue(V v) {
+            val = v;
+        }
+    }
+}

Propchange: cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/service/GenericsService2.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/service/GenericsService2.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: cxf/trunk/rt/frontend/simple/src/main/java/org/apache/cxf/service/factory/ReflectionServiceFactoryBean.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/simple/src/main/java/org/apache/cxf/service/factory/ReflectionServiceFactoryBean.java?rev=890605&r1=890604&r2=890605&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/simple/src/main/java/org/apache/cxf/service/factory/ReflectionServiceFactoryBean.java (original)
+++ cxf/trunk/rt/frontend/simple/src/main/java/org/apache/cxf/service/factory/ReflectionServiceFactoryBean.java Tue Dec 15 02:37:40 2009
@@ -28,6 +28,7 @@
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Proxy;
 import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
 import java.net.MalformedURLException;
 import java.net.URI;
 import java.net.URL;
@@ -153,7 +154,9 @@
     protected String wsdlURL;
 
     protected Class<?> serviceClass;
-
+    protected ParameterizedType serviceType;
+    protected Map<Type, Map<String, Class<?>>> parameterizedTypes;
+    
     protected final Map<String, String> schemaLocationMapping = new HashMap<String, String>();
 
     private List<AbstractServiceConfiguration> serviceConfigurations = 
@@ -1463,6 +1466,9 @@
             if (isInParam(method, j)) {
                 final QName q = getInParameterName(op, method, j);
                 MessagePartInfo part = inMsg.addMessagePart(getInPartName(op, method, j));
+                
+                
+                
                 initializeParameter(part, paramClasses[j], method.getGenericParameterTypes()[j]);
                 //TODO:remove method param annotations
                 part.setProperty(METHOD_PARAM_ANNOTATIONS, method.getParameterAnnotations());
@@ -1734,6 +1740,21 @@
                 rawClass = getClass(type);
             }
         }
+        if (type instanceof TypeVariable) {
+            if (parameterizedTypes == null) {
+                processParameterizedTypes();
+            }
+            TypeVariable var = (TypeVariable)type;
+            Map<String, Class<?>> mp = parameterizedTypes.get(var.getGenericDeclaration());
+            if (mp != null) {
+                Class<?> c = parameterizedTypes.get(var.getGenericDeclaration()).get(var.getName());
+                if (c != null) {
+                    rawClass = c;
+                    type = c;
+                    part.getMessageInfo().setProperty("parameterized", Boolean.TRUE);
+                }
+            }
+        }
         part.setProperty(GENERIC_TYPE, type);
         // if rawClass is List<String>, it will be converted to array
         // and set it to type class
@@ -2263,7 +2284,35 @@
     public Class<?> getServiceClass() {
         return serviceClass;
     }
-
+    private void processParameterizedTypes() {
+        parameterizedTypes = new HashMap<Type, Map<String, Class<?>>>();
+        if (serviceClass.isInterface()) {
+            processTypes(serviceClass, serviceType);
+        } else {
+            for (int x = 0; x < serviceClass.getInterfaces().length; x++) {
+                processTypes(serviceClass.getInterfaces()[x], serviceClass.getGenericInterfaces()[x]);
+            }
+            processTypes(serviceClass.getSuperclass(), serviceClass.getGenericSuperclass());            
+        }
+    }
+    protected void processTypes(Class sc, Type tp) {
+        if (tp != null && tp instanceof ParameterizedType) { 
+            ParameterizedType ptp = (ParameterizedType)tp;
+            Type c = (Class)ptp.getRawType();
+            Map<String, Class<?>> m = new HashMap<String, Class<?>>();
+            parameterizedTypes.put(c, m);
+            for (int x = 0; x < ptp.getActualTypeArguments().length; x++) {
+                Type t = ptp.getActualTypeArguments()[x];
+                TypeVariable<?> tv = sc.getTypeParameters()[x];
+                if (t instanceof Class) {
+                    m.put(tv.getName(), (Class)t);
+                }
+            }
+        }
+    }
+    public void setServiceType(ParameterizedType servicetype) {
+        serviceType = servicetype;
+    }
     public void setServiceClass(Class<?> serviceClass) {
         this.serviceClass = serviceClass;
         checkServiceClassAnnotations(serviceClass);