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);