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/13 15:05:50 UTC

svn commit: r753274 - in /cxf/trunk: rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/ rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ rt/frontend/jaxrs/src/test/java/org/a...

Author: sergeyb
Date: Fri Mar 13 14:05:49 2009
New Revision: 753274

URL: http://svn.apache.org/viewvc?rev=753274&view=rev
Log:
JAXRS : support for proxies with root classes containing template variables

Added:
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/MultipartProvider.java
      - copied, changed from r752412, cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ActivationProvider.java
    cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/BookStoreSubresourcesOnly.java   (with props)
Removed:
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ActivationProvider.java
Modified:
    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/JAXRSClientFactory.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/JAXRSClientFactoryBean.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java
    cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/JAXRSServiceFactoryBeanTest.java
    cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/Chapter.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/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=753274&r1=753273&r2=753274&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 Fri Mar 13 14:05:49 2009
@@ -24,9 +24,12 @@
 import java.lang.reflect.Method;
 import java.net.HttpURLConnection;
 import java.net.URI;
-import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 import java.util.ResourceBundle;
 import java.util.logging.Logger;
 
@@ -72,13 +75,34 @@
     private ClassResourceInfo cri;
     private boolean inheritHeaders;
     private boolean isRoot;
+    private Map<String, Object> valuesMap;
     
     public ClientProxyImpl(URI baseURI, URI currentURI, ClassResourceInfo cri, boolean isRoot, 
-                           boolean inheritHeaders) {
+                           boolean inheritHeaders, Object... varValues) {
         super(baseURI, currentURI);
         this.cri = cri;
         this.isRoot = isRoot;
         this.inheritHeaders = inheritHeaders;
+        initValuesMap(varValues);
+    }
+    
+    private void initValuesMap(Object... varValues) {
+        if (isRoot && varValues.length != 0) {
+            valuesMap = new LinkedHashMap<String, Object>();
+            List<String> vars = cri.getURITemplate().getVariables();
+            for (int i = 0; i < vars.size(); i++) {
+                if (i < varValues.length) {
+                    valuesMap.put(vars.get(i), varValues[i]);
+                } else {
+                    org.apache.cxf.common.i18n.Message msg = new org.apache.cxf.common.i18n.Message(
+                         "ROOT_VARS_MISMATCH", BUNDLE, vars.size(), varValues.length);
+                    LOG.info(msg.toString());
+                    break;
+                }
+            }
+        } else {
+            valuesMap = Collections.emptyMap();
+        }
     }
     
     /**
@@ -102,7 +126,7 @@
         
         MultivaluedMap<ParameterType, Parameter> types = 
             getParametersInfo(ori, m, params);
-        List<Object> pathParams = getParamValues(types, params, ParameterType.PATH);
+        List<Object> pathParams = getPathParamValues(types, params, ori);
         
         int bodyIndex = getBodyIndex(types, ori);
         
@@ -242,12 +266,32 @@
         return headers;
     }
     
-    private static List<Object> getParamValues(MultivaluedMap<ParameterType, Parameter> map, 
-                                               Object[] params, ParameterType key) {
-        List<Parameter> indexList =  getParameters(map, key);
-        List<Object> list = new ArrayList<Object>(indexList.size());
-        for (Parameter p : indexList) {
-            list.add(params[p.getIndex()].toString());
+    private List<Object> getPathParamValues(MultivaluedMap<ParameterType, Parameter> map,
+                                            Object[] params,
+                                            OperationResourceInfo ori) {
+        List<Parameter> paramsList =  getParameters(map, ParameterType.PATH);
+        List<Object> list = new LinkedList<Object>();
+        if (isRoot) {
+            list.addAll(valuesMap.values());
+        }
+        List<String> vars = ori.getURITemplate().getVariables();
+        // TODO : unfortunately, UriBuilder will lose a method-scoped parameter 
+        // if a same name variable exists in a class scope which is an api bug.
+        // It's a rare case but we might want just to use UriBuilderImpl() directly 
+        // on the client side and tell it to choose the last variable value
+        for (Parameter p : paramsList) {
+            if (valuesMap.containsKey(p.getValue()) && !vars.contains(p.getValue())) {
+                int index = 0; 
+                for (Iterator<String> it = valuesMap.keySet().iterator(); it.hasNext(); index++) {
+                    if (it.next().equals(p.getValue())) {
+                        list.remove(index);
+                        list.add(index, params[p.getIndex()]);
+                        break;
+                    }
+                }
+            } else {
+                list.add(params[p.getIndex()]);
+            }
         }
         return list;
     }

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/JAXRSClientFactory.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/JAXRSClientFactory.java?rev=753274&r1=753273&r2=753274&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/JAXRSClientFactory.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/JAXRSClientFactory.java Fri Mar 13 14:05:49 2009
@@ -22,8 +22,6 @@
 import java.net.URI;
 import java.util.List;
 
-import javax.ws.rs.core.MediaType;
-
 import org.apache.cxf.common.util.ProxyHelper;
 
 /**
@@ -39,7 +37,7 @@
     /**
      * Creates a proxy
      * @param baseAddress baseAddress
-     * @param cls proxy class, if not interface then a CGLIB proxy will be created
+     * @param cls resource class, if not interface then a CGLIB proxy will be created
      * @return typed proxy
      */
     public static <T> T create(String baseAddress, Class<T> cls) {
@@ -49,7 +47,7 @@
     /**
      * Creates a proxy
      * @param baseURI baseURI
-     * @param cls proxy class, if not interface then a CGLIB proxy will be created
+     * @param cls resource class, if not interface then a CGLIB proxy will be created
      * @return typed proxy
      */
     public static <T> T create(URI baseURI, Class<T> cls) {
@@ -59,7 +57,7 @@
     /**
      * Creates a proxy
      * @param baseURI baseURI
-     * @param cls proxy class, if not interface then a CGLIB proxy will be created
+     * @param cls resource class, if not interface then a CGLIB proxy will be created
      * @param inheritHeaders if true then existing proxy headers will be inherited by 
      *        subresource proxies if any
      * @return typed proxy
@@ -75,7 +73,7 @@
     /**
      * Creates a proxy
      * @param baseAddress baseAddress
-     * @param cls proxy class, if not interface then a CGLIB proxy will be created
+     * @param cls resource class, if not interface then a CGLIB proxy will be created
      * @param config classpath location of Spring configuration resource
      * @return typed proxy
      */
@@ -84,6 +82,22 @@
         return bean.create(cls);
     }
     
+    /**
+     * Creates a proxy
+     * @param baseAddress baseAddress
+     * @param cls resource class, if not interface then a CGLIB proxy will be created
+     *        This class is expected to have a root JAXRS Path annotation containing
+     *        template variables, for ex, "/path/{id1}/{id2}"  
+     * @param config classpath location of Spring configuration resource
+     * @param varValues values to replace root Path template variables   
+     * @return typed proxy
+     */
+    public static <T> T create(String baseAddress, Class<T> cls, String configLocation, 
+                               Object... varValues) {
+        JAXRSClientFactoryBean bean = getBean(baseAddress, cls, configLocation);
+        return bean.create(cls, varValues);
+    }
+    
     
     /**
      * Creates a proxy
@@ -128,21 +142,6 @@
     }
     
     /**
-     * Creates a proxy
-     * @param baseAddress baseAddress
-     * @param cls proxy class, if not interface then a CGLIB proxy will be created
-     * @param contentType JAXRS MediaType representing HTTP Content-Type header, can be null
-     * @param acceptTypes JAXRS MediaTypes representing HTTP Accept header, can be null
-     * @return typed proxy
-     */
-    public static <T> T create(String baseAddress, Class<T> cls, MediaType contentType, 
-                               MediaType... acceptTypes) {
-        T proxy = create(baseAddress, cls);
-        WebClient.client(proxy).type(contentType).accept(acceptTypes);
-        return proxy;
-    }
-    
-    /**
      * Creates a proxy, baseURI will be set to Client currentURI
      *   
      * @param client Client instance

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/JAXRSClientFactoryBean.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/JAXRSClientFactoryBean.java?rev=753274&r1=753273&r2=753274&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/JAXRSClientFactoryBean.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/JAXRSClientFactoryBean.java Fri Mar 13 14:05:49 2009
@@ -111,11 +111,15 @@
         }
     }
     
-    public <T> T create(Class<T> cls) {
-        return cls.cast(create());
+    public <T> T create(Class<T> cls, Object... varValues) {
+        return cls.cast(createWithValues(varValues));
     }
     
-    public Client create() {
+    public Client create() { 
+        return createWithValues();
+    }
+    
+    public Client createWithValues(Object... varValues) {
         checkResources();
         
         try {
@@ -123,7 +127,8 @@
             URI baseURI = URI.create(getAddress());
             ClassResourceInfo cri = serviceFactory.getClassResourceInfo().get(0);
             boolean isRoot = AnnotationUtils.getClassAnnotation(cri.getServiceClass(), Path.class) != null;
-            ClientProxyImpl proxyImpl = new ClientProxyImpl(baseURI, baseURI, cri, isRoot, inheritHeaders);
+            ClientProxyImpl proxyImpl = new ClientProxyImpl(baseURI, baseURI, cri, isRoot, inheritHeaders,
+                                                            varValues);
             initClient(proxyImpl, ep);    
             
             return (Client)ProxyHelper.getProxy(cri.getServiceClass().getClassLoader(),

Copied: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/MultipartProvider.java (from r752412, cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ActivationProvider.java)
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/MultipartProvider.java?p2=cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/MultipartProvider.java&p1=cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ActivationProvider.java&r1=752412&r2=753274&rev=753274&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ActivationProvider.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/MultipartProvider.java Fri Mar 13 14:05:49 2009
@@ -44,7 +44,7 @@
 
 @Provider
 @Consumes({"multipart/related", "multipart/mixed", "multipart/alternative" })
-public class ActivationProvider implements MessageBodyReader<Object> {
+public class MultipartProvider implements MessageBodyReader<Object> {
 
     @Context
     private MessageContext mc;

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java?rev=753274&r1=753273&r2=753274&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java Fri Mar 13 14:05:49 2009
@@ -28,6 +28,7 @@
 import java.util.Comparator;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.logging.Logger;
 
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.ext.ContextResolver;
@@ -35,6 +36,7 @@
 import javax.ws.rs.ext.MessageBodyReader;
 import javax.ws.rs.ext.MessageBodyWriter;
 
+import org.apache.cxf.common.logging.LogUtils;
 import org.apache.cxf.endpoint.Endpoint;
 import org.apache.cxf.jaxrs.client.ResponseExceptionMapper;
 import org.apache.cxf.jaxrs.ext.ParameterHandler;
@@ -49,17 +51,26 @@
 import org.apache.cxf.message.Message;
 
 public final class ProviderFactory {
-    
+    private static final Logger LOG = LogUtils.getL7dLogger(ProviderFactory.class);
     private static final ProviderFactory SHARED_FACTORY = new ProviderFactory();
     
     static {
+        // TODO : do dynamic instantiation of JSON and few other default providers
+        JSONProvider jsonProvider = null;
+        try {
+            jsonProvider = new JSONProvider();
+        } catch (Throwable ex) {
+            ex.printStackTrace();
+            LOG.fine("Problem with instantiating the default JSON provider");
+        }
+        
         SHARED_FACTORY.setProviders(new JAXBElementProvider(),
-                                    new JSONProvider(),
+                                    jsonProvider,
                                     new BinaryDataProvider(),
                                     new SourceProvider(),
                                     new FormEncodingProvider(),
                                     new PrimitiveTextProvider(),
-                                    new ActivationProvider(),
+                                    new MultipartProvider(),
                                     new WebApplicationExceptionMapper(),
                                     new SystemQueryHandler());
     }
@@ -272,6 +283,9 @@
     private void setProviders(Object... providers) {
         
         for (Object o : providers) {
+            if (o == null) {
+                continue;
+            }
             if (MessageBodyReader.class.isAssignableFrom(o.getClass())) {
                 messageReaders.add(new ProviderInfo<MessageBodyReader>((MessageBodyReader)o)); 
             }

Modified: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/JAXRSServiceFactoryBeanTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/JAXRSServiceFactoryBeanTest.java?rev=753274&r1=753273&r2=753274&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/JAXRSServiceFactoryBeanTest.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/JAXRSServiceFactoryBeanTest.java Fri Mar 13 14:05:49 2009
@@ -28,6 +28,7 @@
 import org.apache.cxf.jaxrs.model.MethodDispatcher;
 import org.apache.cxf.jaxrs.model.OperationResourceInfo;
 import org.apache.cxf.jaxrs.model.URITemplate;
+
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
@@ -69,6 +70,16 @@
     }
 
     @Test
+    public void testSubresourcesOnlyDynamicResolution() throws Exception {
+        JAXRSServiceFactoryBean sf = new JAXRSServiceFactoryBean();
+        sf.setResourceClasses(org.apache.cxf.jaxrs.resources.BookStoreSubresourcesOnly.class);
+        sf.create();
+        
+        List<ClassResourceInfo> resources = ((JAXRSServiceImpl)sf.getService()).getClassResourceInfos();
+        assertEquals(1, resources.size());
+    }
+    
+    @Test
     public void testSubResources() throws Exception {
         JAXRSServiceFactoryBean sf = new JAXRSServiceFactoryBean();
         sf.setEnableStaticResolution(true);

Added: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/BookStoreSubresourcesOnly.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/BookStoreSubresourcesOnly.java?rev=753274&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/BookStoreSubresourcesOnly.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/resources/BookStoreSubresourcesOnly.java Fri Mar 13 14:05:49 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.resources;
+
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+
+@Path("/bookstore/{id}/{id2}/{id3}")
+public class BookStoreSubresourcesOnly {
+
+    @Path("/sub1")
+    public BookStoreSubresourcesOnly getItself() { 
+        return this;
+    }
+    
+    @Path("/sub2")
+    public BookStoreSubresourcesOnly getItself2(@PathParam("id") String id1, @PathParam("id3") String id3) { 
+        return this;
+    }
+    
+    @Path("/{id4}/sub3")
+    public BookStoreSubresourcesOnly getItself3(@PathParam("id4") String id4) { 
+        return this;
+    }
+}
+
+

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

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

Modified: cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/Chapter.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/Chapter.java?rev=753274&r1=753273&r2=753274&view=diff
==============================================================================
--- cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/Chapter.java (original)
+++ cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/Chapter.java Fri Mar 13 14:05:49 2009
@@ -61,6 +61,11 @@
         return this;
     }
     
+    @Path("/recurse2")
+    public Chapter getItself2() {
+        return this;
+    }
+    
     @GET
     @Produces("application/xml;charset=ISO-8859-1")
     public Chapter get() {

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=753274&r1=753273&r2=753274&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 Fri Mar 13 14:05:49 2009
@@ -358,6 +358,9 @@
         getAndCompareAsStrings("http://localhost:9080/bookstore/booksubresource/123/chapters/sub/1/recurse",
                                "resources/expected_get_chapter1_utf.txt",
                                "application/xml", 200);
+        getAndCompareAsStrings("http://localhost:9080/bookstore/booksubresource/123/chapters/sub/1/recurse2",
+                               "resources/expected_get_chapter1.txt",
+                               "application/xml", 200);
     }
     
     @Test