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 2009/03/04 12:07:50 UTC

svn commit: r749963 - in /cxf/trunk: rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/ rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/fortest/jaxb/ rt/frontend/jaxrs/src/tes...

Author: sergeyb
Date: Wed Mar  4 11:07:50 2009
New Revision: 749963

URL: http://svn.apache.org/viewvc?rev=749963&view=rev
Log:
JAXRS: CXF-2058 plus support for XmlJavaTypeAdapter on the inbound path

Added:
    cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/fortest/jaxb/
    cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/fortest/jaxb/Book.java   (with props)
    cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/fortest/jaxb/ObjectFactory.java   (with props)
Modified:
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AbstractJAXBProvider.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JAXBElementProvider.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JSONProvider.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java
    cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/JAXBElementProviderTest.java
    cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java
    cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AbstractJAXBProvider.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AbstractJAXBProvider.java?rev=749963&r1=749962&r2=749963&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AbstractJAXBProvider.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AbstractJAXBProvider.java Wed Mar  4 11:07:50 2009
@@ -70,12 +70,11 @@
     }
     
     public boolean isWriteable(Class<?> type, Type genericType, Annotation[] anns, MediaType mt) {
-        return isSupported(type, genericType, anns)
-               || AnnotationUtils.getAnnotation(anns, XmlJavaTypeAdapter.class) != null;
+        return isSupported(type, genericType, anns);
     }
     
-    public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mt) {
-        return isSupported(type, genericType, annotations);
+    public boolean isReadable(Class<?> type, Type genericType, Annotation[] anns, MediaType mt) {
+        return isSupported(type, genericType, anns);
     }
 
     public void setSchemaLocations(List<String> locations) {
@@ -133,7 +132,7 @@
         }
     }
     
-    private JAXBContext getPackageContext(Class<?> type) {
+    protected JAXBContext getPackageContext(Class<?> type) {
         if (type == null) {
             return null;
         }
@@ -144,27 +143,38 @@
                 try {
                     context = JAXBContext.newInstance(packageName, type.getClassLoader());
                     packageContexts.put(packageName, context);
-                    return context;
                 } catch (JAXBException ex) {
                     LOG.fine("Error creating a JAXBContext using ObjectFactory : " 
                                 + ex.getMessage());
                     return null;
                 }
             }
+            return context;
         }
-        return null;
     }
     
-    protected boolean isSupported(Class<?> type, Type genericType, Annotation[] annotations) {
+    protected boolean isSupported(Class<?> type, Type genericType, Annotation[] anns) {
+        // TODO : Shall we just return true and let readFrom/writeTo 
+        // fail if JAXB can't handle a given type ?
+        
+        // TODO: still not checked : 
+        // - XmlJavaTypeAdapter at package level
+        // - anything else ?
         
         return type.getAnnotation(XmlRootElement.class) != null
             || JAXBElement.class.isAssignableFrom(type)
             || objectFactoryForClass(type)
-            || (type != genericType && objectFactoryForType(genericType));
+            || (type != genericType && objectFactoryForType(genericType))
+            || adapterAvailable(type, anns);
+    
+    }
     
+    protected boolean adapterAvailable(Class<?> type, Annotation[] anns) {
+        return AnnotationUtils.getAnnotation(anns, XmlJavaTypeAdapter.class) != null
+               || type.getAnnotation(XmlJavaTypeAdapter.class) != null;
     }
     
-    private boolean objectFactoryForClass(Class<?> type) {
+    protected boolean objectFactoryForClass(Class<?> type) {
         try {
             return type.getClassLoader().loadClass(PackageUtils.getPackageName(type) 
                                         + ".ObjectFactory") != null;
@@ -201,24 +211,39 @@
         return marshaller;
     }
     
-    protected Class<?> getActualType(Class<?> type, Type genericType) {
+    protected Class<?> getActualType(Class<?> type, Type genericType, Annotation[] anns) {
         Class<?> theType = null;
         if (JAXBElement.class.isAssignableFrom(type)) {
             theType = InjectionUtils.getActualType(genericType);
         } else {
             theType = type;
         }
+        XmlJavaTypeAdapter adapter = getAdapter(theType, anns);
+        if (adapter != null) {
+            if (adapter.type() != XmlJavaTypeAdapter.DEFAULT.class) {
+                theType = adapter.type();
+            } else {
+                Type[] types = InjectionUtils.getActualTypes(adapter.value().getGenericSuperclass());
+                if (types != null && types.length == 2) {
+                    theType = (Class)types[0];
+                }
+            }
+        }
         
         return theType;
     }
     
     @SuppressWarnings("unchecked")
-    protected Object checkAdapter(Object obj, Annotation[] anns) {
-        XmlJavaTypeAdapter typeAdapter = AnnotationUtils.getAnnotation(anns, XmlJavaTypeAdapter.class);
+    protected Object checkAdapter(Object obj, Annotation[] anns, boolean marshal) {
+        XmlJavaTypeAdapter typeAdapter = getAdapter(obj.getClass(), anns); 
         if (typeAdapter != null) {
             try {
                 XmlAdapter xmlAdapter = typeAdapter.value().newInstance();
-                return xmlAdapter.marshal(obj);
+                if (marshal) {
+                    return xmlAdapter.marshal(obj);
+                } else {
+                    return xmlAdapter.unmarshal(obj);
+                }
             } catch (Exception ex) {
                 LOG.warning("Problem using the XmlJavaTypeAdapter");
                 ex.printStackTrace();
@@ -227,9 +252,24 @@
         return obj;
     }
     
+    protected XmlJavaTypeAdapter getAdapter(Class<?> type, Annotation[] anns) {
+        XmlJavaTypeAdapter typeAdapter = AnnotationUtils.getAnnotation(anns, XmlJavaTypeAdapter.class);
+        if (typeAdapter == null) {
+            typeAdapter = type.getAnnotation(XmlJavaTypeAdapter.class);
+        }
+        return typeAdapter;
+    }
+    
+    
     protected Schema getSchema() {
         return schema;
     }
+
+    
+    static void clearContexts() {
+        classContexts.clear();
+        packageContexts.clear();
+    }
     
     protected static void handleJAXBException(JAXBException e) {
         Throwable t = e.getLinkedException() != null 

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JAXBElementProvider.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JAXBElementProvider.java?rev=749963&r1=749962&r2=749963&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JAXBElementProvider.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JAXBElementProvider.java Wed Mar  4 11:07:50 2009
@@ -84,14 +84,17 @@
         MultivaluedMap<String, String> headers, InputStream is) 
         throws IOException {
         try {
-            Class<?> theType = getActualType(type, genericType);
+            Class<?> theType = getActualType(type, genericType, anns);
             Unmarshaller unmarshaller = createUnmarshaller(theType, genericType);
             
+            Object response = null;
             if (JAXBElement.class.isAssignableFrom(type)) {
-                return unmarshaller.unmarshal(new StreamSource(is), theType);
+                response = unmarshaller.unmarshal(new StreamSource(is), theType);
             } else {
-                return unmarshaller.unmarshal(is);
+                response = unmarshaller.unmarshal(is);
             }
+            response = checkAdapter(response, anns, false);
+            return response;
             
         } catch (JAXBException e) {
             handleJAXBException(e);
@@ -109,7 +112,7 @@
         MediaType m, MultivaluedMap<String, Object> headers, OutputStream os) 
         throws IOException {
         try {
-            Object actualObject = checkAdapter(obj, anns);
+            Object actualObject = checkAdapter(obj, anns, true);
             Class<?> actualClass = actualObject.getClass();
             if (cls == genericType) {
                 genericType = actualClass;
@@ -122,6 +125,10 @@
             
         } catch (JAXBException e) {
             throw new WebApplicationException(e);
+        }  catch (WebApplicationException e) {
+            throw e;
+        } catch (Exception e) {
+            throw new WebApplicationException(e);        
         }
     }
 

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JSONProvider.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JSONProvider.java?rev=749963&r1=749962&r2=749963&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JSONProvider.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JSONProvider.java Wed Mar  4 11:07:50 2009
@@ -103,7 +103,8 @@
         throws IOException {
         
         try {
-            Class<?> theType = getActualType(type, genericType);
+            Class<?> theType = getActualType(type, genericType, anns);
+            
             Unmarshaller unmarshaller = createUnmarshaller(theType, genericType);
             
             MappedXMLInputFactory factory = new MappedXMLInputFactory(namespaceMap);
@@ -114,6 +115,7 @@
             } else {
                 response = unmarshaller.unmarshal(xsw);
             }
+            response = checkAdapter(response, anns, false);
             return response;
             
         } catch (JAXBException e) {
@@ -134,7 +136,7 @@
         throws IOException {
         try {
             
-            Object actualObject = checkAdapter(obj, anns);
+            Object actualObject = checkAdapter(obj, anns, true);
             Class<?> actualClass = actualObject.getClass();
             if (cls == genericType) {
                 genericType = actualClass;
@@ -164,6 +166,8 @@
             throw new WebApplicationException(e);
         } catch (XMLStreamException e) {
             throw new WebApplicationException(e);
+        } catch (Exception e) {
+            throw new WebApplicationException(e);
         }
     }
 

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java?rev=749963&r1=749962&r2=749963&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java Wed Mar  4 11:07:50 2009
@@ -132,6 +132,15 @@
         return (Class<?>)paramType.getActualTypeArguments()[0];
     }
     
+    public static Type[] getActualTypes(Type genericType) {
+        if (genericType == null 
+            || !ParameterizedType.class.isAssignableFrom(genericType.getClass())) {
+            return null;
+        }
+        ParameterizedType paramType = (ParameterizedType)genericType;
+        return paramType.getActualTypeArguments();
+    }
+    
     public static void injectThroughMethod(Object requestObject,
                                            Method method,
                                            Object parameterValue) {

Added: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/fortest/jaxb/Book.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/fortest/jaxb/Book.java?rev=749963&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/fortest/jaxb/Book.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/fortest/jaxb/Book.java Wed Mar  4 11:07:50 2009
@@ -0,0 +1,45 @@
+/**
+ * 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.jaxrs.fortest.jaxb;
+
+
+public class Book {
+    private String name;
+    private long id;
+    
+    public Book() {
+    }
+    
+    public void setName(String n) {
+        name = n;
+    }
+
+    public String getName() {
+        return name;
+    }
+    
+    public void setId(long i) {
+        id = i;
+    }
+    public long getId() {
+        return id;
+    }
+   
+}

Propchange: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/fortest/jaxb/Book.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/fortest/jaxb/Book.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/fortest/jaxb/ObjectFactory.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/fortest/jaxb/ObjectFactory.java?rev=749963&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/fortest/jaxb/ObjectFactory.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/fortest/jaxb/ObjectFactory.java Wed Mar  4 11:07:50 2009
@@ -0,0 +1,26 @@
+/**
+ * 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.jaxrs.fortest.jaxb;
+
+
+public class ObjectFactory {
+    public Book createBook() {
+        return new Book();
+    }
+}

Propchange: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/fortest/jaxb/ObjectFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/fortest/jaxb/ObjectFactory.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/JAXBElementProviderTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/JAXBElementProviderTest.java?rev=749963&r1=749962&r2=749963&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/JAXBElementProviderTest.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/JAXBElementProviderTest.java Wed Mar  4 11:07:50 2009
@@ -31,6 +31,7 @@
 import java.util.Map;
 
 import javax.ws.rs.core.MediaType;
+import javax.xml.bind.JAXBContext;
 import javax.xml.bind.JAXBException;
 import javax.xml.bind.Marshaller;
 import javax.xml.bind.PropertyException;
@@ -43,6 +44,7 @@
 import javax.xml.validation.Schema;
 
 import org.w3c.dom.Node;
+
 import org.xml.sax.ContentHandler;
 
 import org.junit.Assert;
@@ -71,6 +73,21 @@
         assertNotNull("schema can not be read from disk", s);
     }
     
+    @Test 
+    public void testPackageContext() {
+        JAXBElementProvider p = new JAXBElementProvider();
+        try {
+            JAXBContext context = p.getPackageContext(org.apache.cxf.jaxrs.fortest.jaxb.Book.class);
+            JAXBContext context2 = p.getPackageContext(org.apache.cxf.jaxrs.fortest.jaxb.Book.class);
+            assertNotNull(context);
+            assertNotNull(context2);
+            assertSame(context, context2);
+        } finally {
+            JAXBElementProvider.clearContexts();
+        }
+        
+    }
+    
     @Test
     public void testSetMarshallProperties() throws Exception {
         

Modified: cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java?rev=749963&r1=749962&r2=749963&view=diff
==============================================================================
--- cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java (original)
+++ cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java Wed Mar  4 11:07:50 2009
@@ -315,6 +315,15 @@
 
         return Response.ok(book).build();
     }
+    
+    @POST
+    @Path("/booksinfo")
+    @Produces("text/xml")
+    @Consumes("application/xml")
+    public Response addBook(@XmlJavaTypeAdapter(BookInfoAdapter.class) 
+                            BookInfo bookInfo) {
+        return Response.ok(bookInfo.asBook()).build();
+    }
 
     @POST
     @Path("/binarybooks")
@@ -455,9 +464,16 @@
         private String name;
         private long id;
         
+        public BookInfo() {
+            
+        }
+        
         public BookInfo(Book b) {
             this.name = b.getName();
             this.id = b.getId();
+            if (id == 0) {
+                id = 124;
+            }
         }
         
         public String getName() {
@@ -467,6 +483,13 @@
         public long getId() {
             return id;
         }
+       
+        public Book asBook() {
+            Book b = new Book();
+            b.setId(id);
+            b.setName(name);
+            return b;
+        }
     }
     
     public static class BookInfoAdapter extends XmlAdapter<Book, BookInfo> {
@@ -477,9 +500,8 @@
         }
 
         @Override
-        public BookInfo unmarshal(Book v) throws Exception {
-            // TODO Auto-generated method stub
-            return null;
+        public BookInfo unmarshal(Book b) throws Exception {
+            return new BookInfo(b);
         }
         
     }

Modified: cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java?rev=749963&r1=749962&r2=749963&view=diff
==============================================================================
--- cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java (original)
+++ cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java Wed Mar  4 11:07:50 2009
@@ -357,11 +357,17 @@
     
     @Test
     public void testAddBook() throws Exception {
-        String endpointAddress =
-            "http://localhost:9080/bookstore/books";
-
+        doAddBook("http://localhost:9080/bookstore/books");               
+    }
+    
+    @Test
+    public void testAddBookXmlAdapter() throws Exception {
+        doAddBook("http://localhost:9080/bookstore/booksinfo");               
+    }
+    
+    private void doAddBook(String address) throws Exception {
         File input = new File(getClass().getResource("resources/add_book.txt").toURI());         
-        PostMethod post = new PostMethod(endpointAddress);
+        PostMethod post = new PostMethod(address);
         post.setRequestHeader("Content-Type", "application/xml");
         RequestEntity entity = new FileRequestEntity(input, "text/xml; charset=ISO-8859-1");
         post.setRequestEntity(entity);
@@ -377,8 +383,8 @@
         } finally {
             // Release current connection to the connection pool once you are done
             post.releaseConnection();
-        }               
-    }  
+        }
+    }
     
     @Test
     public void testUpdateBook() throws Exception {