You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2012/05/29 18:30:53 UTC

svn commit: r1343822 - in /cxf/trunk: rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/ rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/ systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/ systests/jaxrs/src/test/reso...

Author: sergeyb
Date: Tue May 29 16:30:52 2012
New Revision: 1343822

URL: http://svn.apache.org/viewvc?rev=1343822&view=rev
Log:
[CXF-4349] Making it possible to produce xsi:type for JAXB root classes

Added:
    cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/SuperBook.java   (with props)
Modified:
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/ClientProxyImpl.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/WebClient.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutInterceptor.java
    cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStoreSpring.java
    cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerSpringBookTest.java
    cxf/trunk/systests/jaxrs/src/test/resources/jaxrs/WEB-INF/beans.xml

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java?rev=1343822&r1=1343821&r2=1343822&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java Tue May 29 16:30:52 2012
@@ -382,23 +382,20 @@ public abstract class AbstractClient imp
         state.setResponseBuilder(currentResponseBuilder);
         return rb;
     }
-    protected <T> void writeBody(T o, Message outMessage, Type type, Annotation[] anns,
-                                 MultivaluedMap<String, Object> headers, OutputStream os) {
-        @SuppressWarnings("unchecked")
-        Class<T> cls = (Class<T>)o.getClass();
-        writeBody(o, outMessage, cls, type, anns, headers, os);
-    }       
-    protected <T> void writeBody(T o, Message outMessage, Class<T> cls, Type type, Annotation[] anns, 
+    
+    protected <T> void writeBody(T o, Message outMessage, Class<?> cls, Type type, Annotation[] anns, 
         MultivaluedMap<String, Object> headers, OutputStream os) {
         
         if (o == null) {
             return;
         }
+        @SuppressWarnings("unchecked")
+        Class<T> theClass = (Class<T>)cls;
         
         MediaType contentType = MediaType.valueOf(headers.getFirst("Content-Type").toString()); 
         
         MessageBodyWriter<T> mbw = ProviderFactory.getInstance(outMessage)
-            .createMessageBodyWriter(cls, type, anns, contentType, outMessage);
+            .createMessageBodyWriter(theClass, type, anns, contentType, outMessage);
         if (mbw != null) {
             try {
                 mbw.writeTo(o, cls, type, anns, contentType, headers, os);

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/ClientProxyImpl.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/ClientProxyImpl.java?rev=1343822&r1=1343821&r2=1343822&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/ClientProxyImpl.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/ClientProxyImpl.java Tue May 29 16:30:52 2012
@@ -633,10 +633,11 @@ public class ClientProxyImpl extends Abs
             try {
                 if (bodyIndex != -1) {
                     writeBody(body, outMessage,
+                              method.getParameterTypes()[bodyIndex],
                               method.getGenericParameterTypes()[bodyIndex],
                               anns, headers, os);
                 } else {
-                    writeBody(body, outMessage, body.getClass(), 
+                    writeBody(body, outMessage, body.getClass(), body.getClass(), 
                               anns, headers, os);
                 }
             } catch (Exception ex) {

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/WebClient.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/WebClient.java?rev=1343822&r1=1343821&r2=1343822&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/WebClient.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/WebClient.java Tue May 29 16:30:52 2012
@@ -64,6 +64,7 @@ import org.apache.cxf.phase.Phase;
  *
  */
 public class WebClient extends AbstractClient {
+    private static final String REQUEST_CLASS = "request.class";
     private static final String REQUEST_TYPE = "request.type";
     private static final String RESPONSE_CLASS = "response.class";
     private static final String RESPONSE_TYPE = "response.type";
@@ -345,6 +346,20 @@ public class WebClient extends AbstractC
     }
     
     /**
+     * Does HTTP invocation and returns types response object 
+     * @param httpMethod HTTP method 
+     * @param body request body, can be null
+     * @param requestClass request body class
+     * @param responseClass expected type of response object
+     * @return typed object, can be null. Response status code and headers 
+     *         can be obtained too, see Client.getResponse()
+     */
+    public <T> T invoke(String httpMethod, Object body, Class<?> requestClass, Class<T> responseClass) {
+        Response r = doInvoke(httpMethod, body, requestClass, null, responseClass, responseClass);
+        return responseClass.cast(responseClass == Response.class ? r : r.getEntity());
+    }
+    
+    /**
      * Does HTTP POST invocation and returns typed response object
      * @param body request body, can be null
      * @param responseClass expected type of response object
@@ -694,8 +709,21 @@ public class WebClient extends AbstractC
         return (WebClient)super.reset();
     }
     
-    protected Response doInvoke(String httpMethod, Object body, Type inGenericType,
-                                Class<?> responseClass, Type outGenericType) {
+    protected Response doInvoke(String httpMethod, 
+                                Object body, 
+                                Type inGenericType,
+                                Class<?> responseClass, 
+                                Type outGenericType) {
+        return doInvoke(httpMethod, body, body == null ? null : body.getClass(), inGenericType, 
+            responseClass, outGenericType);
+    }
+    
+    protected Response doInvoke(String httpMethod, 
+                                Object body, 
+                                Class<?> requestClass,
+                                Type inGenericType,
+                                Class<?> responseClass, 
+                                Type outGenericType) {
         
         MultivaluedMap<String, String> headers = getHeaders();
         boolean contentTypeNotSet = headers.getFirst(HttpHeaders.CONTENT_TYPE) == null;
@@ -712,7 +740,7 @@ public class WebClient extends AbstractC
             headers.putSingle(HttpHeaders.ACCEPT, MediaType.APPLICATION_XML_TYPE.toString());
         }
         resetResponse();
-        Response r = doChainedInvocation(httpMethod, headers, body, inGenericType, 
+        Response r = doChainedInvocation(httpMethod, headers, body, requestClass, inGenericType, 
                                          responseClass, outGenericType, null, null);
         if (r.getStatus() >= 400 && responseClass != Response.class) {
             throw new ServerWebApplicationException(r);
@@ -729,16 +757,18 @@ public class WebClient extends AbstractC
         
         Map<String, Object> reqContext = CastUtils.cast((Map<?, ?>)invContext.get(REQUEST_CONTEXT));
         String httpMethod = (String)reqContext.get(Message.HTTP_REQUEST_METHOD);
+        Class<?> requestClass = (Class<?>)reqContext.get(REQUEST_CLASS);
         Type inType = (Type)reqContext.get(REQUEST_TYPE);
         Class<?> respClass = (Class<?>)reqContext.get(RESPONSE_CLASS);
         Type outType = (Type)reqContext.get(RESPONSE_TYPE);
-        return doChainedInvocation(httpMethod, headers, body, inType, 
+        return doChainedInvocation(httpMethod, headers, body, requestClass, inType, 
                                    respClass, outType, exchange, invContext);
     }
     //CHECKSTYLE:OFF
     protected Response doChainedInvocation(String httpMethod, 
                                            MultivaluedMap<String, String> headers, 
                                            Object body, 
+                                           Class<?> requestClass,
                                            Type inGenericType,
                                            Class<?> responseClass, 
                                            Type outGenericType,
@@ -751,6 +781,7 @@ public class WebClient extends AbstractC
         
         Map<String, Object> reqContext = getRequestContext(m);
         reqContext.put(Message.HTTP_REQUEST_METHOD, httpMethod);
+        reqContext.put(REQUEST_CLASS, requestClass);
         reqContext.put(REQUEST_TYPE, inGenericType);
         reqContext.put(RESPONSE_CLASS, responseClass);
         reqContext.put(RESPONSE_TYPE, outGenericType);
@@ -843,12 +874,16 @@ public class WebClient extends AbstractC
             Object body = objs.get(0);
             
             Map<String, Object> requestContext = WebClient.this.getRequestContext(outMessage);
-            Type type = null;
+            Class<?> requestClass = null;
+            Type requestType = null;
             if (requestContext != null) {
-                type = (Type)requestContext.get(REQUEST_TYPE);
+                requestClass = (Class<?>)requestContext.get(REQUEST_CLASS);
+                requestType = (Type)requestContext.get(REQUEST_TYPE);
             }
             try {
-                writeBody(body, outMessage, type == null ? body.getClass() : type, 
+                writeBody(body, outMessage, 
+                          requestClass == null ? body.getClass() : requestClass,
+                          requestType == null ? body.getClass() : requestType, 
                           new Annotation[]{}, headers, os);
                 if (os != null) {
                     os.flush();

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutInterceptor.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutInterceptor.java?rev=1343822&r1=1343821&r2=1343822&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutInterceptor.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutInterceptor.java Tue May 29 16:30:52 2012
@@ -207,8 +207,8 @@ public class JAXRSOutInterceptor extends
                 ? ori.getMethodToInvoke() : ori.getAnnotatedMethod();
         }
         
-        Class<?> targetType = getRawResponseClass(responseObj);
-        Type genericType = getGenericResponseType(ori == null ? null : invoked, responseObj, targetType);
+        Class<?> targetType = getRawResponseClass(invoked, responseObj);
+        Type genericType = getGenericResponseType(invoked, responseObj, targetType);
         if (genericType instanceof TypeVariable) {
             genericType = InjectionUtils.getSuperType(ori.getClassResourceInfo().getServiceClass(), 
                                                        (TypeVariable<?>)genericType);
@@ -432,11 +432,14 @@ public class JAXRSOutInterceptor extends
         
     }
     
-    private Class<?> getRawResponseClass(Object targetObject) {
+    private Class<?> getRawResponseClass(Method invoked, Object targetObject) {
         if (GenericEntity.class.isAssignableFrom(targetObject.getClass())) {
             return ((GenericEntity<?>)targetObject).getRawType();
         } else {
-            return ClassHelper.getRealClassFromClass(targetObject.getClass());
+            Class<?> targetClass = targetObject.getClass();
+            Class<?> responseClass = invoked == null 
+                || !invoked.getReturnType().isAssignableFrom(targetClass) ? targetClass : invoked.getReturnType(); 
+            return ClassHelper.getRealClassFromClass(responseClass);
         }
     }
     

Modified: cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStoreSpring.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStoreSpring.java?rev=1343822&r1=1343821&r2=1343822&view=diff
==============================================================================
--- cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStoreSpring.java (original)
+++ cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStoreSpring.java Tue May 29 16:30:52 2012
@@ -81,6 +81,21 @@ public class BookStoreSpring {
     }
     
     @GET
+    @Path("/books/xsitype")
+    @Produces("application/xml")
+    public Book getBookXsiType() {
+        return new SuperBook("SuperBook", 999L);
+    }
+    
+    @POST
+    @Path("/books/xsitype")
+    @Produces("application/xml")
+    @Consumes("application/xml")
+    public Book postGetBookXsiType(Book book) {
+        return book;
+    }
+    
+    @GET
     @Path("/books/{id}")
     @Produces({"application/json", "application/vnd.example-com.foo+json" })
     public Book getBookById(@PathParam("id") Long id) {

Modified: cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerSpringBookTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerSpringBookTest.java?rev=1343822&r1=1343821&r2=1343822&view=diff
==============================================================================
--- cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerSpringBookTest.java (original)
+++ cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerSpringBookTest.java Tue May 29 16:30:52 2012
@@ -312,6 +312,45 @@ public class JAXRSClientServerSpringBook
     }
     
     @Test
+    public void testGetBookXsiType() throws Exception {
+        String address = "http://localhost:" + PORT + "/the/thebooksxsi/bookstore/books/xsitype";
+        WebClient wc = WebClient.create(address);
+        wc.accept("application/xml");
+        Book book = wc.get(Book.class);
+        assertEquals("SuperBook", book.getName());
+        
+    }
+    
+    @Test
+    public void testPostBookXsiType() throws Exception {
+        String address = "http://localhost:" + PORT + "/the/thebooksxsi/bookstore/books/xsitype";
+        JAXBElementProvider<Book> provider = new JAXBElementProvider<Book>();
+        provider.setExtraClass(new Class[]{SuperBook.class});
+        provider.setJaxbElementClassNames(Collections.singletonList(Book.class.getName()));
+        WebClient wc = WebClient.create(address, Collections.singletonList(provider));
+        wc.accept("application/xml");
+        wc.type("application/xml");
+        SuperBook book = new SuperBook("SuperBook2", 999L);
+        Book book2 = wc.invoke("POST", book, Book.class, Book.class);
+        assertEquals("SuperBook2", book2.getName());
+        
+    }
+    
+    @Test
+    public void testPostBookXsiTypeProxy() throws Exception {
+        String address = "http://localhost:" + PORT + "/the/thebooksxsi/bookstore";
+        JAXBElementProvider<Book> provider = new JAXBElementProvider<Book>();
+        provider.setExtraClass(new Class[]{SuperBook.class});
+        provider.setJaxbElementClassNames(Collections.singletonList(Book.class.getName()));
+        BookStoreSpring bookStore = JAXRSClientFactory.create(address, BookStoreSpring.class, 
+                                                              Collections.singletonList(provider));
+        SuperBook book = new SuperBook("SuperBook2", 999L);
+        Book book2 = bookStore.postGetBookXsiType(book);
+        assertEquals("SuperBook2", book2.getName());
+        
+    }
+    
+    @Test
     public void testGetBookWithEncodedQueryValue() throws Exception {
         String endpointAddress =
             "http://localhost:" + PORT + "/the/bookstore/booksquery?id=12%2B3"; 

Added: cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/SuperBook.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/SuperBook.java?rev=1343822&view=auto
==============================================================================
--- cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/SuperBook.java (added)
+++ cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/SuperBook.java Tue May 29 16:30:52 2012
@@ -0,0 +1,35 @@
+/**
+ * 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.systest.jaxrs;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+
+@XmlRootElement(name = "SuperBook")
+public class SuperBook extends Book {
+    
+    public SuperBook() {
+        
+    }
+    
+    public SuperBook(String name, long id) {
+        super(name, id);
+    }
+}

Propchange: cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/SuperBook.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/SuperBook.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: cxf/trunk/systests/jaxrs/src/test/resources/jaxrs/WEB-INF/beans.xml
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/resources/jaxrs/WEB-INF/beans.xml?rev=1343822&r1=1343821&r2=1343822&view=diff
==============================================================================
--- cxf/trunk/systests/jaxrs/src/test/resources/jaxrs/WEB-INF/beans.xml (original)
+++ cxf/trunk/systests/jaxrs/src/test/resources/jaxrs/WEB-INF/beans.xml Tue May 29 16:30:52 2012
@@ -88,6 +88,19 @@ http://cxf.apache.org/schemas/core.xsd">
     </jaxrs:features>    
   </jaxrs:server>
   
+  <jaxrs:server id="booksxsi"
+		        address="/thebooksxsi/bookstore">
+    <jaxrs:serviceBeans>
+      <ref bean="serviceBean" />
+    </jaxrs:serviceBeans>		  
+    <jaxrs:providers>
+       <ref bean="jaxbProviderXsi"/>
+    </jaxrs:providers> 
+    <jaxrs:features>
+       <cxf:logging/>
+    </jaxrs:features>    
+  </jaxrs:server>
+  
   <jaxrs:server id="bookservice4"
 		        address="/thebooks4/bookstore">
     <jaxrs:serviceBeans>
@@ -239,6 +252,18 @@ http://cxf.apache.org/schemas/core.xsd">
       <property name="schemaHandler" ref="schemaHolder"/>
   </bean>
   
+  <util:list id="jaxbClasses">
+    <value>org.apache.cxf.systest.jaxrs.Book</value>
+  </util:list>
+  <bean id="jaxbProviderXsi" class="org.apache.cxf.jaxrs.provider.JAXBElementProvider">
+      <property name="jaxbElementClassNames" ref="jaxbClasses"/>
+      <property name="extraClass">
+         <list>
+           <value>org.apache.cxf.systest.jaxrs.SuperBook</value>
+         </list>
+      </property>
+  </bean>
+  
   <bean id="schemaHolder" class="org.apache.cxf.jaxrs.utils.schemas.SchemaHandler">
       <property name="schemas" ref="theSchemas"/>
   </bean>