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/10 13:55:46 UTC

svn commit: r752099 - in /cxf/trunk: rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/ rt/frontend/jaxrs/src/main/resources/schemas/ rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/client/ systests/src/test/java/org/apache/cxf/systest/j...

Author: sergeyb
Date: Tue Mar 10 12:55:44 2009
New Revision: 752099

URL: http://svn.apache.org/viewvc?rev=752099&view=rev
Log:
JAXRS: client api updates

Added:
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/InvocationHandlerAware.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/Client.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/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/client/WebClient.java
    cxf/trunk/rt/frontend/jaxrs/src/main/resources/schemas/jaxrs.xsd
    cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/client/WebClientTest.java
    cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSSoapBookTest.java
    cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/security/JAXRSHttpsBookTest.java
    cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/security/JAXRSSpringSecurityInterfaceTest.java

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=752099&r1=752098&r2=752099&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 Mar 10 12:55:44 2009
@@ -72,7 +72,7 @@
  * Common proxy and http-centric client implementation
  *
  */
-public class AbstractClient implements Client {
+public class AbstractClient implements Client, InvocationHandlerAware {
 
     private static final Logger LOG = LogUtils.getL7dLogger(AbstractClient.class);
     private static final ResourceBundle BUNDLE = BundleUtils.getBundle(AbstractClient.class);
@@ -93,14 +93,6 @@
         this.currentBuilder = new UriBuilderImpl(currentURI);
     }
     
-    protected AbstractClient(Client client, boolean inheritHeaders) {
-        this.baseURI = client.getCurrentURI();
-        this.currentBuilder = new UriBuilderImpl(client.getCurrentURI());
-        if (inheritHeaders) {
-            this.requestHeaders = client.getHeaders();
-        }
-    }
-    
     /**
      * {@inheritDoc}
      */
@@ -251,11 +243,9 @@
      */
     public Response getResponse() {
         if (responseBuilder == null) {
-            throw new IllegalStateException();
+            return null;
         }
-        Response r = responseBuilder.build();
-        responseBuilder = null;
-        return r;
+        return responseBuilder.build();
     }
     
     /**
@@ -532,4 +522,8 @@
         }
         
     }
+
+    public Object getInvocationHandler() {
+        return this;
+    }
 }

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/Client.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/Client.java?rev=752099&r1=752098&r2=752099&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/Client.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/Client.java Tue Mar 10 12:55:44 2009
@@ -154,7 +154,6 @@
     /**
      * Gets the response state if any
      * @return JAXRS Response response
-     * @throws IllegalStateException if no request has been made or this method called more than once 
      */
     Response getResponse();
 }

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=752099&r1=752098&r2=752099&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 Mar 10 12:55:44 2009
@@ -90,13 +90,12 @@
      */
     public Object invoke(Object o, Method m, Object[] params) throws Throwable {
         
-        resetResponse();
-        
         Class<?> declaringClass = m.getDeclaringClass();
-        if (Client.class == declaringClass || Object.class == declaringClass) {
+        if (Client.class == declaringClass || InvocationHandlerAware.class == declaringClass
+            || Object.class == declaringClass) {
             return m.invoke(this, params);
         }
-        
+        resetResponse();
         OperationResourceInfo ori = cri.getMethodDispatcher().getOperationResourceInfo(m);
         if (ori == null) {
             reportInvalidResourceMethod(m, "INVALID_RESOURCE_METHOD");
@@ -146,11 +145,8 @@
         setRequestHeaders(headers, ori, types.containsKey(ParameterType.FORM), 
             bodyIndex == -1 ? null : params[bodyIndex].getClass(), m.getReturnType());
         
-        if (conduitSelector == null) {
-            return doDirectInvocation(uri, headers, ori, params, bodyIndex, types);
-        } else {
-            return doChainedInvocation(uri, headers, ori, params, bodyIndex, types);
-        }
+        return doChainedInvocation(uri, headers, ori, params, bodyIndex, types);
+        
     }
 
     private static MultivaluedMap<ParameterType, Parameter> getParametersInfo(OperationResourceInfo ori, 
@@ -369,33 +365,6 @@
         
     }
     
-    protected Object doDirectInvocation(URI uri, MultivaluedMap<String, String> headers, 
-        OperationResourceInfo ori, Object[] params, int bodyIndex, 
-        MultivaluedMap<ParameterType, Parameter> types) throws Throwable {
-
-        // TODO : we need to refactor bits of HTTPConduit such that it can be reused
-        
-        Message message = createSimpleMessage();
-        
-        HttpURLConnection connect = createHttpConnection(uri, ori.getHttpMethod());
-        setAllHeaders(headers, connect);
-        Method m = ori.getMethodToInvoke();
-        if (bodyIndex != -1 || types.containsKey(ParameterType.FORM)) {
-            if (bodyIndex != -1) {
-                writeBody(params[bodyIndex], message, params[bodyIndex].getClass(), 
-                          m.getGenericParameterTypes()[bodyIndex],
-                          m.getParameterAnnotations()[bodyIndex], headers, connect.getOutputStream());
-            } else {
-                MultivaluedMap<String, String> form = handleForm(types, params);
-                writeBody(form, message, form.getClass(), form.getClass(), m.getDeclaredAnnotations(),
-                          headers, connect.getOutputStream());
-            }
-        }
-        
-        return handleResponse(connect, message, ori);
-        
-    }
-    
     private Object doChainedInvocation(URI uri, MultivaluedMap<String, String> headers, 
                           OperationResourceInfo ori, Object[] params, int bodyIndex, 
                           MultivaluedMap<ParameterType, Parameter> types) throws Throwable {

Added: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/InvocationHandlerAware.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/InvocationHandlerAware.java?rev=752099&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/InvocationHandlerAware.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/InvocationHandlerAware.java Tue Mar 10 12:55:44 2009
@@ -0,0 +1,28 @@
+/**
+ * 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.client;
+
+/**
+ * Utiliy interface which helps to retrieve 
+ * the invoiation handler from a CGLIB proxy  
+ *
+ */
+public interface InvocationHandlerAware {
+    Object getInvocationHandler();
+}

Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/InvocationHandlerAware.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/InvocationHandlerAware.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

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=752099&r1=752098&r2=752099&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 Tue Mar 10 12:55:44 2009
@@ -20,16 +20,11 @@
 
 import java.lang.reflect.InvocationHandler;
 import java.net.URI;
+import java.util.List;
 
-import javax.ws.rs.Path;
 import javax.ws.rs.core.MediaType;
 
-import org.apache.cxf.Bus;
-import org.apache.cxf.bus.spring.SpringBusFactory;
 import org.apache.cxf.common.util.ProxyHelper;
-import org.apache.cxf.jaxrs.model.ClassResourceInfo;
-import org.apache.cxf.jaxrs.utils.AnnotationUtils;
-import org.apache.cxf.jaxrs.utils.ResourceUtils;
 
 /**
  * Factory for creating proxy clients.
@@ -65,58 +60,71 @@
      * Creates a proxy
      * @param baseURI baseURI
      * @param cls proxy class, if not interface then a CGLIB proxy will be created
-     * @param inheritHeaders if true then subresource proxies will inherit the headers
-     *        set on parent proxies 
+     * @param inheritHeaders if true then existing proxy headers will be inherited by 
+     *        subresource proxies if any
      * @return typed proxy
      */
     public static <T> T create(URI baseURI, Class<T> cls, boolean inheritHeaders) {
         
-        return create(baseURI, cls, inheritHeaders, false);
+        JAXRSClientFactoryBean bean = getBean(baseURI.toString(), cls, null);
+        bean.setInheritHeaders(inheritHeaders);
+        return bean.create(cls);
+        
     }
     
-    
     /**
      * Creates a proxy
-     * @param baseURI baseURI
+     * @param baseAddress baseAddress
      * @param cls proxy class, if not interface then a CGLIB proxy will be created
-     * @param config Spring configuration file location
+     * @param config classpath location of Spring configuration resource
      * @return typed proxy
      */
-    public static <T> T create(URI baseURI, Class<T> cls, String configLocation) {
-        SpringBusFactory bf = new SpringBusFactory();
-        Bus bus = bf.createBus(configLocation);
-        JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean();
-        bean.setAddress(baseURI.toString());
-        bean.setServiceClass(cls);
-        bean.setBus(bus);
+    public static <T> T create(String baseAddress, Class<T> cls, String configLocation) {
+        JAXRSClientFactoryBean bean = getBean(baseAddress, cls, configLocation);
         return bean.create(cls);
     }
     
+    
     /**
      * Creates a proxy
-     * @param baseURI baseURI
+     * @param baseAddress baseAddress
      * @param cls proxy 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
-     * @param direct if true then no bus and chains will be created
+     * @param providers list of providers
      * @return typed proxy
      */
-    public static <T> T create(URI baseURI, Class<T> cls, boolean inheritHeaders, boolean direct) {
-        
-        if (!direct) {
-            JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean();
-            bean.setAddress(baseURI.toString());
-            bean.setServiceClass(cls);
-            bean.setInheritHeaders(inheritHeaders);
-            return bean.create(cls);
-        } else {
-            boolean isRoot = AnnotationUtils.getClassAnnotation(cls, Path.class) != null;
-            ClassResourceInfo cri = ResourceUtils.createClassResourceInfo(cls, cls, isRoot, true);
-            
-            return cls.cast(ProxyHelper.getProxy(cls.getClassLoader(),
-                            new Class[]{cls, Client.class}, 
-                            new ClientProxyImpl(baseURI, baseURI, cri, isRoot, inheritHeaders)));
-        }
+    public static <T> T create(String baseAddress, Class<T> cls, List<?> providers) {
+        return create(baseAddress, cls, providers, null);
+    }
+    
+    /**
+     * Creates a proxy
+     * @param baseAddress baseAddress
+     * @param cls proxy class, if not interface then a CGLIB proxy will be created
+     * @param providers list of providers
+     * @param config classpath location of Spring configuration resource
+     * @return typed proxy
+     */
+    public static <T> T create(String baseAddress, Class<T> cls, List<?> providers, String configLocation) {
+        JAXRSClientFactoryBean bean = getBean(baseAddress, cls, configLocation);
+        bean.setProviders(providers);
+        return bean.create(cls);
+    }
+    
+    /**
+     * Creates a proxy which will do basic authentication
+     * @param baseAddress baseAddress
+     * @param cls proxy class, if not interface then a CGLIB proxy will be created
+     * @param username username
+     * @param password password
+     * @param config classpath location of Spring configuration resource
+     * @return typed proxy
+     */
+    public static <T> T create(String baseAddress, Class<T> cls, String username,
+                               String password, String configLocation) {
+        JAXRSClientFactoryBean bean = getBean(baseAddress, cls, configLocation);
+        bean.setUsername(username);
+        bean.setPassword(password);
+        return bean.create(cls);
     }
     
     /**
@@ -142,9 +150,6 @@
      * @return typed proxy
      */
     public static <T> T fromClient(Client client, Class<T> cls) {
-        if (cls.isAssignableFrom(client.getClass())) {
-            return cls.cast(client);
-        }
         return fromClient(client, cls, false);
     }
     
@@ -157,24 +162,12 @@
      * @return typed proxy
      */
     public static <T> T fromClient(Client client, Class<T> cls, boolean inheritHeaders) {
-        return fromClient(client, cls, inheritHeaders, false);
-    }
-    
-    /**
-     * Creates a proxy, baseURI will be set to Client currentURI
-     * @param client Client instance
-     * @param cls proxy class, if not interface then a CGLIB proxy will be created
-     * @param inheritHeaders if true then existing Client headers will be inherited by new proxy 
-     *        and subresource proxies if any 
-     * @param direct if true then no bus and chains will be created       
-     * @return typed proxy
-     */
-    public static <T> T fromClient(Client client, Class<T> cls, boolean inheritHeaders, boolean direct) {
         
-        T proxy = create(client.getCurrentURI(), cls, inheritHeaders, direct);
+        T proxy = create(client.getCurrentURI(), cls, inheritHeaders);
         if (inheritHeaders) {
             WebClient.client(proxy).headers(client.getHeaders());
         }
+        WebClient.copyProperties(WebClient.client(proxy), client);
         return proxy;
     }
     
@@ -182,4 +175,12 @@
         
         return cls.cast(ProxyHelper.getProxy(cls.getClassLoader(), new Class[]{cls, Client.class}, handler));
     }
+    
+    private static JAXRSClientFactoryBean getBean(String baseAddress, Class<?> cls, String configLocation) {
+        JAXRSClientFactoryBean bean = WebClient.getBean(baseAddress, configLocation);
+        bean.setServiceClass(cls);
+        return bean;
+    }
+    
+    
 }

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=752099&r1=752098&r2=752099&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 Tue Mar 10 12:55:44 2009
@@ -26,6 +26,7 @@
 import javax.ws.rs.core.MultivaluedMap;
 
 import org.apache.cxf.common.util.ProxyHelper;
+import org.apache.cxf.configuration.security.AuthorizationPolicy;
 import org.apache.cxf.endpoint.ConduitSelector;
 import org.apache.cxf.endpoint.Endpoint;
 import org.apache.cxf.endpoint.UpfrontConduitSelector;
@@ -40,6 +41,8 @@
 
 public class JAXRSClientFactoryBean extends AbstractJAXRSFactoryBean {
     
+    private String username;
+    private String password;
     private boolean inheritHeaders; 
     private MultivaluedMap<String, String> headers;
     
@@ -53,6 +56,22 @@
         
     }
     
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+    
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+    
     public void setInheritHeaders(boolean ih) {
         inheritHeaders = ih;
     }
@@ -109,7 +128,8 @@
             initClient(proxyImpl, ep);    
             
             return (Client)ProxyHelper.getProxy(cri.getServiceClass().getClassLoader(),
-                                        new Class[]{cri.getServiceClass(), Client.class}, 
+                                        new Class[]{cri.getServiceClass(), Client.class, 
+                                                    InvocationHandlerAware.class}, 
                                         proxyImpl);
         } catch (Exception ex) {
             throw new WebApplicationException();
@@ -126,6 +146,15 @@
     }
     
     protected void initClient(AbstractClient client, Endpoint ep) {
+        
+        if (username != null) {
+            AuthorizationPolicy authPolicy = new AuthorizationPolicy();
+            authPolicy.setUserName(username);
+            authPolicy.setPassword(password);
+            ep.getEndpointInfo().addExtensor(authPolicy);
+        }
+        
+        
         client.setConduitSelector(getConduitSelector(ep));
         client.setBus(getBus());
         client.setOutInterceptors(getOutInterceptors());

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=752099&r1=752098&r2=752099&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 Mar 10 12:55:44 2009
@@ -18,7 +18,6 @@
  */
 package org.apache.cxf.jaxrs.client;
 
-import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.lang.annotation.Annotation;
@@ -57,28 +56,90 @@
  */
 public class WebClient extends AbstractClient {
     
+    protected WebClient(String baseAddress) {
+        this(URI.create(baseAddress));
+    }
+    
+    protected WebClient(URI baseAddress) {
+        super(baseAddress, baseAddress);
+    }
+    
     /**
      * Creates WebClient
      * @param baseAddress baseAddress
      */
-    public WebClient(String baseAddress) {
-        this(URI.create(baseAddress));
+    public static WebClient create(String baseAddress) {
+        JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean();
+        bean.setAddress(baseAddress);
+        return bean.createWebClient();
+    }
+    
+    /**
+     * Creates WebClient
+     * @param baseURI baseURI
+     */
+    public static WebClient create(URI baseURI) {
+        return create(baseURI.toString());
     }
     
     /**
      * Creates WebClient
      * @param baseURI baseURI
+     * @param providers list of providers
+     */
+    public static WebClient create(String baseAddress, List<?> providers) {
+        return create(baseAddress, providers, null);        
+    }
+    
+    /**
+     * Creates a Spring-configuration aware WebClient
+     * @param baseAddress baseAddress
+     * @param providers list of providers
+     * @param configLocation classpath location of Spring configuration resource, can be null  
+     * @return WebClient instance
+     */
+    public static WebClient create(String baseAddress, List<?> providers, String configLocation) {
+        JAXRSClientFactoryBean bean = getBean(baseAddress, configLocation);
+        bean.setProviders(providers);
+        return bean.createWebClient();
+    }
+    
+    /**
+     * Creates a Spring-configuration aware WebClient
+     * @param baseAddress baseAddress
+     * @param configLocation classpath location of Spring configuration resource, can be null  
+     * @return WebClient instance
      */
-    public WebClient(URI baseURI) {
-        super(baseURI, baseURI);
+    public static WebClient create(String baseAddress, String configLocation) {
+        JAXRSClientFactoryBean bean = getBean(baseAddress, configLocation);
+        
+        return bean.createWebClient();
+    }
+    
+    /**
+     * Creates a Spring-configuration aware WebClient which will do basic authentication
+     * @param baseAddress baseAddress
+     * @param username username
+     * @param password password
+     * @param configLocation classpath location of Spring configuration resource, can be null  
+     * @return WebClient instance
+     */
+    public static WebClient create(String baseAddress, String username, String password, 
+                                         String configLocation) {
+        JAXRSClientFactoryBean bean = getBean(baseAddress, configLocation);
+        
+        bean.setUsername(username);
+        bean.setPassword(password);
+        
+        return bean.createWebClient();
     }
     
     /**
      * Creates WebClient, baseURI will be set to Client currentURI
      * @param client existing client
      */
-    public WebClient(Client client) {
-        this(client, false);
+    public static WebClient fromClient(Client client) {
+        return fromClient(client, false);
     }
     
     /**
@@ -87,8 +148,25 @@
      * @param inheritHeaders  if existing Client headers can be inherited by new proxy 
      *        and subresource proxies if any 
      */
-    public WebClient(Client client, boolean inheritHeaders) {
-        super(client, inheritHeaders);
+    public static WebClient fromClient(Client client, boolean inheritHeaders) {
+        WebClient webClient = create(client.getCurrentURI());
+        if (inheritHeaders) {
+            webClient.headers(client.getHeaders());
+        }
+        copyProperties(webClient, client);
+        return webClient;
+    }
+    
+    /**
+     * Converts proxy to Client
+     * @param proxy the proxy
+     * @return proxy as a Client 
+     */
+    public static Client client(Object proxy) {
+        if (proxy instanceof Client) {
+            return (Client)proxy;
+        }
+        return null;
     }
     
     /**
@@ -285,34 +363,6 @@
         return this;
     }
     
-    /**
-     * Converts proxy to Client
-     * @param proxy the proxy
-     * @return proxy as a Client 
-     */
-    public static Client client(Object proxy) {
-        if (proxy instanceof Client) {
-            return (Client)proxy;
-        }
-        return null;
-    }
-    
-    
-    public static WebClient createClient(String baseAddress, String configLocation) {
-        SpringBusFactory bf = new SpringBusFactory();
-        Bus bus = bf.createBus(configLocation);
-        JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean();
-        bean.setBus(bus);
-        bean.setAddress(baseAddress);
-        return bean.createWebClient();
-    }
-    
-    public static WebClient createClient(String baseAddress) {
-        JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean();
-        bean.setAddress(baseAddress);
-        return bean.createWebClient();
-    }
-    
     @Override
     public WebClient type(MediaType ct) {
         return (WebClient)super.type(ct);
@@ -383,7 +433,7 @@
         return (WebClient)super.reset();
     }
     
-    private Response doInvoke(String httpMethod, Object body, Class<?> responseClass) {
+    protected Response doInvoke(String httpMethod, Object body, Class<?> responseClass) {
         
         MultivaluedMap<String, String> headers = getHeaders();
         if (body != null && headers.getFirst(HttpHeaders.CONTENT_TYPE) == null) {
@@ -392,34 +442,14 @@
         if (responseClass != null && headers.getFirst(HttpHeaders.ACCEPT) == null) {
             headers.putSingle(HttpHeaders.ACCEPT, MediaType.APPLICATION_XML_TYPE.toString());
         }
-        if (conduitSelector == null) {
-            return doDirectInvocation(httpMethod, headers, body, responseClass);
-        } else {
-            return doChainedInvocation(httpMethod, headers, body, responseClass);
-        }
-    }
-
-    protected Response doDirectInvocation(String httpMethod, 
-        MultivaluedMap<String, String> headers, Object body, Class<?> responseClass) {
+        resetResponse();
+        return doChainedInvocation(httpMethod, headers, body, responseClass);
         
-        HttpURLConnection conn = getConnection(httpMethod);
-        
-        setAllHeaders(headers, conn);
-        Message message = createSimpleMessage();
-        if (body != null) {
-            try {
-                writeBody(body, message, body.getClass(), body.getClass(), 
-                      new Annotation[]{}, headers, conn.getOutputStream());
-            } catch (IOException ex) {
-                throw new WebApplicationException(ex);
-            }
-        }
-        return handleResponse(conn, message, responseClass);
     }
-    
+
     protected Response doChainedInvocation(String httpMethod, 
         MultivaluedMap<String, String> headers, Object body, Class<?> responseClass) {
-
+        
         Message m = createMessage(httpMethod, headers, getCurrentURI());
         
         if (body != null) {
@@ -482,10 +512,35 @@
             } catch (Exception ex) {
                 throw new Fault(ex);
             }
-            
         }
-        
     }
 
+    static void copyProperties(Client toClient, Client fromClient) {
+        AbstractClient newClient = toAbstractClient(toClient);
+        AbstractClient oldClient = toAbstractClient(fromClient);
+        newClient.bus = oldClient.bus;
+        newClient.conduitSelector = oldClient.conduitSelector;
+        newClient.inInterceptors = oldClient.inInterceptors;
+        newClient.outInterceptors = oldClient.outInterceptors;
+    }
+    
+    private static AbstractClient toAbstractClient(Client client) {
+        if (client instanceof AbstractClient) {
+            return (AbstractClient)client;
+        } else {
+            return (AbstractClient)((InvocationHandlerAware)client).getInvocationHandler();
+        }
+    }
     
+    static JAXRSClientFactoryBean getBean(String baseAddress, String configLocation) {
+        JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean();
+        
+        if (configLocation != null) {
+            SpringBusFactory bf = new SpringBusFactory();
+            Bus bus = bf.createBus(configLocation);
+            bean.setBus(bus);
+        }
+        bean.setAddress(baseAddress);
+        return bean;
+    }
 }

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/resources/schemas/jaxrs.xsd
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/resources/schemas/jaxrs.xsd?rev=752099&r1=752098&r2=752099&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/resources/schemas/jaxrs.xsd (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/resources/schemas/jaxrs.xsd Tue Mar 10 12:55:44 2009
@@ -87,6 +87,8 @@
           <xsd:attribute name="serviceClass" type="xsd:string"/>
           <xsd:attribute name="inheritHeaders" type="xsd:boolean"/>
           <xsd:attribute name="bus" type="xsd:string" />
+          <xsd:attribute name="username" type="xsd:string"/>
+          <xsd:attribute name="password" type="xsd:string"/>
         </xsd:extension>
       </xsd:complexContent>
     </xsd:complexType>

Modified: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/client/WebClientTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/client/WebClientTest.java?rev=752099&r1=752098&r2=752099&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/client/WebClientTest.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/client/WebClientTest.java Tue Mar 10 12:55:44 2009
@@ -29,13 +29,13 @@
 
     @Test 
     public void testBaseCurrentPath() {
-        assertEquals(URI.create("http://foo"), new WebClient("http://foo").getBaseURI());
-        assertEquals(URI.create("http://foo"), new WebClient("http://foo").getCurrentURI());
+        assertEquals(URI.create("http://foo"), WebClient.create("http://foo").getBaseURI());
+        assertEquals(URI.create("http://foo"), WebClient.create("http://foo").getCurrentURI());
     }
     
     @Test 
     public void testNewBaseCurrentPath() {
-        WebClient wc = new WebClient("http://foo");
+        WebClient wc = WebClient.create("http://foo");
         assertEquals(URI.create("http://foo"), wc.getBaseURI());
         assertEquals(URI.create("http://foo"), wc.getCurrentURI());
         wc.to("http://bar", false);
@@ -45,7 +45,7 @@
     
     @Test 
     public void testForward() {
-        WebClient wc = new WebClient("http://foo");
+        WebClient wc = WebClient.create("http://foo");
         wc.to("http://foo/bar", true);
         assertEquals(URI.create("http://foo"), wc.getBaseURI());
         assertEquals(URI.create("http://foo/bar"), wc.getCurrentURI());
@@ -53,13 +53,13 @@
     
     @Test(expected = IllegalArgumentException.class) 
     public void testWrongForward() {
-        WebClient wc = new WebClient("http://foo");
+        WebClient wc = WebClient.create("http://foo");
         wc.to("http://bar", true);
     }
     
     @Test 
     public void testBaseCurrentPathAfterChange() {
-        WebClient wc = new WebClient(URI.create("http://foo"));
+        WebClient wc = WebClient.create(URI.create("http://foo"));
         wc.path("bar").path("baz").matrix("m1", "m1value").query("q1", "q1value");
         assertEquals(URI.create("http://foo"), wc.getBaseURI());
         assertEquals(URI.create("http://foo/bar/baz;m1=m1value?q1=q1value"), wc.getCurrentURI());
@@ -68,16 +68,16 @@
     
     @Test 
     public void testBaseCurrentPathAfterCopy() {
-        WebClient wc = new WebClient(URI.create("http://foo"));
+        WebClient wc = WebClient.create(URI.create("http://foo"));
         wc.path("bar").path("baz").matrix("m1", "m1value").query("q1", "q1value");
-        WebClient wc1 = new WebClient(wc);
+        WebClient wc1 = WebClient.fromClient(wc);
         assertEquals(URI.create("http://foo/bar/baz;m1=m1value?q1=q1value"), wc1.getBaseURI());
         assertEquals(URI.create("http://foo/bar/baz;m1=m1value?q1=q1value"), wc1.getCurrentURI());
     }
     
     @Test 
     public void testHeaders() {
-        WebClient wc = new WebClient(URI.create("http://foo"));
+        WebClient wc = WebClient.create(URI.create("http://foo"));
         wc.header("h1", "h1value").header("h2", "h2value");
         assertEquals(1, wc.getHeaders().get("h1").size());
         assertEquals("h1value", wc.getHeaders().getFirst("h1"));
@@ -94,7 +94,7 @@
     
     @Test
     public void testBackFast() {
-        WebClient wc = new WebClient(URI.create("http://foo"));
+        WebClient wc = WebClient.create(URI.create("http://foo"));
         wc.path("bar").path("baz").matrix("m1", "m1value");
         assertEquals(URI.create("http://foo"), wc.getBaseURI());
         assertEquals(URI.create("http://foo/bar/baz;m1=m1value"), wc.getCurrentURI());
@@ -104,7 +104,7 @@
     
     @Test
     public void testBack() {
-        WebClient wc = new WebClient(URI.create("http://foo"));
+        WebClient wc = WebClient.create(URI.create("http://foo"));
         wc.path("bar").path("baz");
         assertEquals(URI.create("http://foo"), wc.getBaseURI());
         assertEquals(URI.create("http://foo/bar/baz"), wc.getCurrentURI());

Modified: cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSSoapBookTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSSoapBookTest.java?rev=752099&r1=752098&r2=752099&view=diff
==============================================================================
--- cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSSoapBookTest.java (original)
+++ cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSSoapBookTest.java Tue Mar 10 12:55:44 2009
@@ -23,6 +23,7 @@
 import java.io.InputStream;
 import java.net.URL;
 import java.net.URLConnection;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
@@ -45,7 +46,6 @@
 import org.apache.cxf.jaxrs.client.WebClient;
 import org.apache.cxf.jaxrs.ext.form.Form;
 import org.apache.cxf.jaxrs.impl.MetadataMap;
-import org.apache.cxf.jaxrs.provider.ProviderFactory;
 import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
 
 import org.junit.BeforeClass;
@@ -92,7 +92,7 @@
     @Test
     public void testGetBook123WebClient() throws Exception {
         String baseAddress = "http://localhost:9092/test/services/rest";
-        WebClient client = new WebClient(baseAddress);
+        WebClient client = WebClient.create(baseAddress);
         client.path("/bookstore/123").accept(MediaType.APPLICATION_XML_TYPE);
         Book b = client.get(Book.class);
         assertEquals(123, b.getId());
@@ -102,7 +102,7 @@
     @Test
     public void testGetBook123WebClientBean() throws Exception {
         String baseAddress = "http://localhost:9092/test/services/rest";
-        WebClient client = WebClient.createClient(baseAddress);
+        WebClient client = WebClient.create(baseAddress);
         client.path("/bookstore/123").accept(MediaType.APPLICATION_XML_TYPE);
         Book b = client.get(Book.class);
         assertEquals(123, b.getId());
@@ -112,7 +112,7 @@
     @Test
     public void testNoBookWebClient() throws Exception {
         String baseAddress = "http://localhost:9092/test/services/rest";
-        WebClient client = new WebClient(baseAddress);
+        WebClient client = WebClient.create(baseAddress);
         client.path("/bookstore/books/0/subresource").accept(MediaType.APPLICATION_XML_TYPE);
         Book b = client.get(Book.class);
         assertNull(b);
@@ -122,7 +122,7 @@
     @Test
     public void testGetBook123WebClientResponse() throws Exception {
         String baseAddress = "http://localhost:9092/test/services/rest";
-        WebClient client = new WebClient(baseAddress);
+        WebClient client = WebClient.create(baseAddress);
         client.path("/bookstore/123").accept(MediaType.APPLICATION_XML_TYPE);
         Book b = readBook((InputStream)client.get().getEntity());
         assertEquals(123, b.getId());
@@ -134,9 +134,9 @@
         
         String baseAddress = "http://localhost:9092/test/services/rest";
         BookStoreJaxrsJaxws proxy = JAXRSClientFactory.create(baseAddress,
-                                                              BookStoreJaxrsJaxws.class);
+                                          BookStoreJaxrsJaxws.class,
+                                          Collections.singletonList(new TestResponseExceptionMapper()));
         
-        ProviderFactory.getInstance().registerUserProvider(new TestResponseExceptionMapper());
         try {
             proxy.getBook(356L);
             fail();
@@ -172,26 +172,9 @@
     }
     
     @Test
-    public void testGetBookSubresourceWebClientProxyDirect() throws Exception {
-        
-        WebClient client = new WebClient("http://localhost:9092/test/services/rest");
-        client.type(MediaType.TEXT_PLAIN_TYPE)
-              .accept(MediaType.APPLICATION_XML_TYPE, MediaType.TEXT_XML_TYPE);
-        BookStoreJaxrsJaxws proxy = 
-            JAXRSClientFactory.fromClient(client, BookStoreJaxrsJaxws.class, true, true);
-        
-        doTestSubresource(proxy);
-        
-        BookStoreJaxrsJaxws proxy2 = JAXRSClientFactory.fromClient(
-            WebClient.client(proxy), BookStoreJaxrsJaxws.class);
-        doTestSubresource(proxy2);
-        
-    }
-    
-    @Test
     public void testGetBookSubresourceWebClientProxyBean() throws Exception {
         
-        WebClient client = new WebClient("http://localhost:9092/test/services/rest");
+        WebClient client = WebClient.create("http://localhost:9092/test/services/rest");
         client.type(MediaType.TEXT_PLAIN_TYPE)
             .accept(MediaType.APPLICATION_XML_TYPE, MediaType.TEXT_XML_TYPE);
         BookStoreJaxrsJaxws proxy = 
@@ -209,7 +192,7 @@
     @Test
     public void testGetBookSubresourceWebClientProxy2() throws Exception {
         
-        WebClient client = new WebClient("http://localhost:9092/test/services/rest/bookstore")
+        WebClient client = WebClient.create("http://localhost:9092/test/services/rest/bookstore")
             .path("/books/378");
         client.type(MediaType.TEXT_PLAIN_TYPE).accept(MediaType.APPLICATION_XML_TYPE);
         BookSubresource proxy = JAXRSClientFactory.fromClient(client, BookSubresource.class);
@@ -240,7 +223,7 @@
     public void testGetBookWebClientForm() throws Exception {
         
         String baseAddress = "http://localhost:9092/test/services/rest/bookstore/books/679/subresource3";
-        WebClient wc = new WebClient(baseAddress);
+        WebClient wc = WebClient.create(baseAddress);
         MultivaluedMap<String, Object> map = new MetadataMap<String, Object>();
         map.putSingle("id", "679");
         map.putSingle("name", "CXF in Action - 679");
@@ -254,7 +237,7 @@
     public void testGetBookWebClientForm2() throws Exception {
         
         String baseAddress = "http://localhost:9092/test/services/rest/bookstore/books/679/subresource3";
-        WebClient wc = new WebClient(baseAddress);
+        WebClient wc = WebClient.create(baseAddress);
         Form f = new Form();
         f.set("id", "679").set("name", "CXF in Action - 679");
         Book b = readBook((InputStream)wc.accept("application/xml")
@@ -278,7 +261,7 @@
     @Test
     public void testAddGetBook123WebClient() throws Exception {
         String baseAddress = "http://localhost:9092/test/services/rest";
-        WebClient client = new WebClient(baseAddress);
+        WebClient client = WebClient.create(baseAddress);
         client.path("/bookstore/books").accept(MediaType.APPLICATION_XML_TYPE)
             .type(MediaType.APPLICATION_XML_TYPE);
         Book b = new Book();

Modified: cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/security/JAXRSHttpsBookTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/security/JAXRSHttpsBookTest.java?rev=752099&r1=752098&r2=752099&view=diff
==============================================================================
--- cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/security/JAXRSHttpsBookTest.java (original)
+++ cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/security/JAXRSHttpsBookTest.java Tue Mar 10 12:55:44 2009
@@ -21,11 +21,7 @@
 
 import javax.ws.rs.core.MediaType;
 
-import org.apache.cxf.Bus;
-import org.apache.cxf.BusFactory;
-import org.apache.cxf.bus.spring.SpringBusFactory;
 import org.apache.cxf.jaxrs.client.JAXRSClientFactory;
-import org.apache.cxf.jaxrs.client.JAXRSClientFactoryBean;
 import org.apache.cxf.jaxrs.client.WebClient;
 import org.apache.cxf.systest.jaxrs.Book;
 import org.apache.cxf.systest.jaxrs.BookStore;
@@ -46,34 +42,59 @@
     }
     
     @Test
-    public void testGetBook123Client() throws Exception {
+    public void testGetBook123Proxy() throws Exception {
         
-        SpringBusFactory bf = new SpringBusFactory();
-        Bus bus = bf.createBus(CLIENT_CONFIG_FILE);
-        BusFactory.setDefaultBus(bus);
-        
-        BookStore bs = JAXRSClientFactory.create("https://localhost:9095", BookStore.class);
+        BookStore bs = JAXRSClientFactory.create("https://localhost:9095", BookStore.class, 
+                                                 CLIENT_CONFIG_FILE);
         // just to verify the interface call goes through CGLIB proxy too
         assertEquals("https://localhost:9095", WebClient.client(bs).getBaseURI().toString());
         Book b = bs.getSecureBook("123");
         assertEquals(b.getId(), 123);
+        b = bs.getSecureBook("123");
+        assertEquals(b.getId(), 123);
+    }
+    
+    @Test
+    public void testGetBook123ProxyToWebClient() throws Exception {
+        
+        BookStore bs = JAXRSClientFactory.create("https://localhost:9095", BookStore.class, 
+                                                 CLIENT_CONFIG_FILE);
+        Book b = bs.getSecureBook("123");
+        assertEquals(b.getId(), 123);
+        WebClient wc = WebClient.fromClient(WebClient.client(bs));
+        wc.path("/bookstore/securebooks/123").accept(MediaType.APPLICATION_XML_TYPE);
+        Book b2 = wc.get(Book.class);
+        assertEquals(123, b2.getId());
     }
     
+    
+    @Test
+    public void testGetBook123WebClientToProxy() throws Exception {
+        
+        WebClient wc = WebClient.create("https://localhost:9095", CLIENT_CONFIG_FILE);
+        wc.path("/bookstore/securebooks/123").accept(MediaType.APPLICATION_XML_TYPE);
+        Book b = wc.get(Book.class);
+        assertEquals(123, b.getId());
+        
+        wc.back(true);
+        
+        BookStore bs = JAXRSClientFactory.fromClient(wc, BookStore.class);
+        Book b2 = bs.getSecureBook("123");
+        assertEquals(b2.getId(), 123);
+        
+    }
+    
+    
     @Test
     public void testGetBook123WebClient() throws Exception {
         
-        SpringBusFactory bf = new SpringBusFactory();
-        Bus bus = bf.createBus(CLIENT_CONFIG_FILE);
-        BusFactory.setDefaultBus(bus);
-        
-        JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean();
-        bean.setAddress("https://localhost:9095");
-        WebClient client = bean.createWebClient();
+        WebClient client = WebClient.create("https://localhost:9095", CLIENT_CONFIG_FILE);
         assertEquals("https://localhost:9095", client.getBaseURI().toString());
         
         client.path("/bookstore/securebooks/123").accept(MediaType.APPLICATION_XML_TYPE);
         Book b = client.get(Book.class);
         assertEquals(123, b.getId());
+        
     }
     
 }

Modified: cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/security/JAXRSSpringSecurityInterfaceTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/security/JAXRSSpringSecurityInterfaceTest.java?rev=752099&r1=752098&r2=752099&view=diff
==============================================================================
--- cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/security/JAXRSSpringSecurityInterfaceTest.java (original)
+++ cxf/trunk/systests/src/test/java/org/apache/cxf/systest/jaxrs/security/JAXRSSpringSecurityInterfaceTest.java Tue Mar 10 12:55:44 2009
@@ -19,6 +19,13 @@
 
 package org.apache.cxf.systest.jaxrs.security;
 
+import javax.ws.rs.core.Response;
+
+import org.apache.cxf.jaxrs.client.JAXRSClientFactory;
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.cxf.systest.jaxrs.Book;
+import org.apache.cxf.systest.jaxrs.BookNotFoundFault;
+
 import org.junit.BeforeClass;
 import org.junit.Test;
 
@@ -68,4 +75,48 @@
         getBook(endpointAddress, "foo", "bar", 200); 
         getBook(endpointAddress, "bob", "bobspassword", 403);
     }   
+    
+    @Test
+    public void testWebClientAdmin() throws Exception {
+        String address = "http://localhost:9080/bookstorestorage/thosebooks";
+        doGetBookWebClient(address, "foo", "bar",  200);
+    }
+    
+    @Test
+    public void testProxyClientAdmin() throws Exception {
+        String address = "http://localhost:9080/bookstorestorage";
+        doGetBookProxyClient(address, "foo", "bar",  200);
+    }
+    
+    @Test
+    public void testWebClientUserUnauthorized() throws Exception {
+        String address = "http://localhost:9080/bookstorestorage/thosebooks";
+        doGetBookWebClient(address, "bob", "bobspassword", 403);
+    }
+    
+    @Test
+    public void testWebClientUserAuthorized() throws Exception {
+        String address = "http://localhost:9080/bookstorestorage/thosebooks/123/123";
+        doGetBookWebClient(address, "bob", "bobspassword", 200);
+    }
+    
+    private void doGetBookWebClient(String address, String username, String password, int expectedStatus) {
+        WebClient wc = WebClient.create(address, username, password, null);
+        Response r = wc.get();
+        assertEquals(expectedStatus, r.getStatus());
+        WebClient wc2 = WebClient.fromClient(wc);
+        r = wc2.get();
+        assertEquals(expectedStatus, r.getStatus());    
+    }
+    
+    private void doGetBookProxyClient(String address, String username, String password, int expectedStatus) 
+        throws BookNotFoundFault {
+        SecureBookInterface books = JAXRSClientFactory.create(address, SecureBookInterface.class, 
+                                                       username, password, null);
+        Book b = books.getThatBook();
+        assertEquals(123, b.getId());
+        Response r = WebClient.client(books).getResponse();
+        assertEquals(expectedStatus, r.getStatus());
+            
+    }
 }