Return-Path: Delivered-To: apmail-cxf-users-archive@www.apache.org Received: (qmail 8502 invoked from network); 10 Apr 2011 02:30:46 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 10 Apr 2011 02:30:46 -0000 Received: (qmail 70843 invoked by uid 500); 10 Apr 2011 02:30:45 -0000 Delivered-To: apmail-cxf-users-archive@cxf.apache.org Received: (qmail 70789 invoked by uid 500); 10 Apr 2011 02:30:45 -0000 Mailing-List: contact users-help@cxf.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: users@cxf.apache.org Delivered-To: mailing list users@cxf.apache.org Received: (qmail 70781 invoked by uid 99); 10 Apr 2011 02:30:45 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 10 Apr 2011 02:30:45 +0000 X-ASF-Spam-Status: No, hits=0.7 required=5.0 tests=RCVD_IN_DNSWL_NONE,SPF_HELO_PASS,SPF_NEUTRAL X-Spam-Check-By: apache.org Received-SPF: neutral (athena.apache.org: local policy) Received: from [212.227.17.8] (HELO moutng.kundenserver.de) (212.227.17.8) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 10 Apr 2011 02:30:37 +0000 Received: from [10.230.24.238] ([1.158.118.213]) by mrelayeu.kundenserver.de (node=mreu4) with ESMTP (Nemesis) id 0LdPLa-1PRTEc04u2-00ijQa; Sun, 10 Apr 2011 04:30:15 +0200 Message-ID: <4DA115C2.10801@kiegeland.com> Date: Sun, 10 Apr 2011 12:28:18 +1000 From: "joerg@kiegeland.com" User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.2.15) Gecko/20110303 Thunderbird/3.1.9 MIME-Version: 1.0 To: users@cxf.apache.org Subject: Re: why JSONProviderTest.testReadQualifiedCollection()/testReadQualifiedArray() disabled? References: <4D843355.3060700@kiegeland.com> <4D8896B7.1020005@kiegeland.com> <4D97287C.9010205@kiegeland.com> <4D983728.2000309@kiegeland.com> <4DA05BCE.40602@kiegeland.com> In-Reply-To: Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Provags-ID: V02:K0:lJ71iR3Ap6npS411Ab8iHQWB/D5awt/aGmLMnjjAHOM 1usbKvaXGdSXozKtriJMCE0BJTfmI0djChDoR33W+TQ8gpstYR VdQRKbMp7Mi9JDBKO8b/lSz35qmk51RquwfTw42j2sIPJnnW46 GrP3NE5yE0lrbl0tBtf87+al3NOqztaTPQ0Q4IKwRFTRGbd5T5 GVutHj3+Gs/tjA0h9F1uEOlF5g1h0tosASs55RO9iE= > I'm confused. > > Can you post a sample resource class, a sample signature and a sample > adapter. In short. > > To be honest, I'm not sure more changes have to be applied. My understanding > was you had adapters converting from String to A. This is not my use case, but is also possible by my previous fix. > Now it appears you need a > conversion from String to A and then from A to B. Why can't yo have adapters > converting from String to B ? Because I use the adapters also for normal webservices. I dont want to have extra String->Something adapters. Here is my example, which I wanted to contribute to CXF, which simulates a "old" webservice by REST calls, and which require my desired behavior of XMLAdapters concerning REST. Would be nice if you include this in trunk. import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.net.URI; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.PathParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.ext.MessageBodyReader; import javax.ws.rs.ext.MessageBodyWriter; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpMethodBase; import org.apache.commons.httpclient.methods.ByteArrayRequestEntity; import org.apache.commons.httpclient.methods.DeleteMethod; import org.apache.commons.httpclient.methods.EntityEnclosingMethod; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.methods.PutMethod; import org.apache.commons.httpclient.methods.RequestEntity; import org.apache.cxf.helpers.IOUtils; import org.apache.cxf.jaxrs.impl.MetadataMap; import org.apache.cxf.jaxrs.impl.UriBuilderImpl; import org.apache.cxf.jaxrs.provider.JAXBElementProvider; import org.apache.cxf.jaxrs.provider.JSONProvider; import org.apache.cxf.jaxrs.utils.AnnotationUtils; import org.apache.cxf.jaxrs.utils.JAXBUtils; /** * Invokes REST operations for a given SEI interface. This assumes that the SEI * interface is exposed as REST service (ideally, the REST service bean * implements the SEI interface). The SEI interface may be additionally exposed * as non-REST webservice, in which case a webservice port can be passed as * first parameter to newInstance(), so that the webservice methods are called * in cases where the called SEI method is not annotated with @GET/@PUT/... . */ public class RESTbyContract implements java.lang.reflect.InvocationHandler { HttpClient httpclient = new HttpClient(); private MessageBodyReader reader; private MessageBodyWriter writer; private final Object obj; private final MediaType mtWrite; private final MediaType mtRead; private final URI baseURI; /** * @param * @param obj * SEI interface instance, may be null * @param c * SEI interface * @param mtWrite * media type to write a message body request * @param mtRead * desired media type to read a message body response * @param baseURI * the base URI of the REST service * @return */ public static T newInstance(T obj, Class c, MediaType mtWrite, MediaType mtRead, URI baseURI) { return (T) java.lang.reflect.Proxy.newProxyInstance(c.getClassLoader(), new Class[] { c }, new RESTbyContract(obj, mtWrite, mtRead, baseURI)); } private RESTbyContract(Object obj, MediaType mtWrite, MediaType mtRead, URI baseURI) { this.obj = obj; this.mtWrite = mtWrite; this.mtRead = mtRead; this.baseURI = baseURI; } public Object invoke(Object proxy, Method m, Object[] args) throws Throwable { try { Annotation[] annotations = m.getAnnotations(); HttpMethodBase method; if (AnnotationUtils.getAnnotation(annotations, POST.class) != null) { method = new PostMethod(); } else if (AnnotationUtils.getAnnotation(annotations, GET.class) != null) { method = new GetMethod(); } else if (AnnotationUtils.getAnnotation(annotations, PUT.class) != null) { method = new PutMethod(""); } else if (AnnotationUtils.getAnnotation(annotations, DELETE.class) != null) { method = new DeleteMethod(); } else { Object result = m.invoke(obj, args); // return an empty list instead of null if a list is expected if (result == null && m.getReturnType() == List.class) result = new ArrayList(); return result; } ByteArrayOutputStream requestBody = null; UriBuilderImpl b = new UriBuilderImpl(baseURI); b.path(m.getDeclaringClass()); b.path(m); Map values = new HashMap(); int i = 0; if (args != null) for (Object arg : args) { Annotation[] annos = m.getParameterAnnotations()[i]; PathParam path = AnnotationUtils.getAnnotation(annos, PathParam.class); if (path != null) { arg = JAXBUtils.useAdapter(arg, AnnotationUtils.getAnnotation(annos, XmlJavaTypeAdapter.class), true); values.put(path.value(), arg); } else if (requestBody != null) { throw new RuntimeException("body already defined!"); } else { if (writer == null) { if ("application/xml".equals(mtWrite.toString())) { writer = new JAXBElementProvider(); } else { writer = new JSONProvider(); } } requestBody = new ByteArrayOutputStream(); writer.writeTo(arg, arg.getClass(), arg.getClass(), annos, mtWrite, new MetadataMap(), requestBody); } i++; } URI restUri = b.buildFromMap(values); method.setURI(new org.apache.commons.httpclient.URI(restUri.toString(), true)); method.addRequestHeader("Accept", mtRead.toString()); if (requestBody != null) { RequestEntity entity = new ByteArrayRequestEntity(requestBody.toByteArray()); ((EntityEnclosingMethod) method).setRequestEntity(entity); method.addRequestHeader("Content-Type", mtWrite.toString()); } int responseCode = httpclient.executeMethod(method); if (responseCode != 200 && responseCode != 204) { throw new RuntimeException(method.getStatusText() + "\n" + method.getResponseBodyAsString()); } Class targetType = m.getReturnType(); if (targetType == Void.TYPE) { return null; } InputStream responseBody = method.getResponseBodyAsStream(); if (reader == null) { if ("application/xml".equals(mtRead.toString())) { reader = new JAXBElementProvider(); } else { reader = new JSONProvider(); } } if (targetType.isPrimitive()) return targetType.getConstructor(String.class).newInstance(IOUtils.toString(responseBody)); if (targetType == String.class) return IOUtils.toString(responseBody); Type genericType = m.getGenericReturnType(); Object result = reader.readFrom(targetType, genericType, annotations, mtRead, new MetadataMap(), responseBody); return result; } catch (InvocationTargetException e) { throw e.getTargetException(); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("unexpected invocation exception: " + e.getMessage()); } } }