Hi CXF JAX-RS client API supports generating the proxies from given interfaces/impl classes, have you tried it ?
thanks, Sergey On Sun, Apr 10, 2011 at 3:28 AM, [email protected] <[email protected]>wrote: > 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 <T> > * @param obj > * SEI interface instance, may be <code>null</code> > * @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> T newInstance(T obj, Class<T> 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<String, Object> values = new HashMap<String, > Object>(); > 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<String, > Object>(), 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<String, String>(), > responseBody); > return result; > > } catch (InvocationTargetException e) { > throw e.getTargetException(); > } catch (Exception e) { > e.printStackTrace(); > throw new RuntimeException("unexpected invocation > exception: " + e.getMessage()); > } > } > > } > >
