This is an automated email from the ASF dual-hosted git repository.

jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git


The following commit(s) were added to refs/heads/master by this push:
     new 4af551e  RestClient tests.
4af551e is described below

commit 4af551ec67088b800c8ef1d2a8625d62e1f82167
Author: JamesBognar <[email protected]>
AuthorDate: Thu Jun 18 17:17:41 2020 -0400

    RestClient tests.
---
 .../apache/juneau/rest/client2/RestClientTest.java | 198 +++++++++--
 .../org/apache/juneau/rest/client2/RestClient.java |  38 ++-
 .../juneau/rest/client2/RestClientBuilder.java     | 105 ++----
 .../apache/juneau/rest/client2/RestRequest.java    | 370 +++++++--------------
 .../juneau/rest/mock2/MockRestClientBuilder.java   |  51 +--
 5 files changed, 391 insertions(+), 371 deletions(-)

diff --git 
a/juneau-rest/juneau-rest-client-utest/src/test/java/org/apache/juneau/rest/client2/RestClientTest.java
 
b/juneau-rest/juneau-rest-client-utest/src/test/java/org/apache/juneau/rest/client2/RestClientTest.java
index fb8b0b5..77b4255 100644
--- 
a/juneau-rest/juneau-rest-client-utest/src/test/java/org/apache/juneau/rest/client2/RestClientTest.java
+++ 
b/juneau-rest/juneau-rest-client-utest/src/test/java/org/apache/juneau/rest/client2/RestClientTest.java
@@ -122,7 +122,7 @@ public class RestClientTest {
                public Bean headBean() {
                        return bean;
                }
-               @RestMethod(path="/echo")
+               @RestMethod(path="/echo/*")
                public String getEcho(org.apache.juneau.rest.RestRequest req) {
                        return req.toString();
                }
@@ -1415,20 +1415,64 @@ public class RestClientTest {
        }
 
        @Test
-       public void c18_miscellaneous_request_scheme() throws Exception {
+       public void c18_miscellaneous_request_uriParts() throws Exception {
                java.net.URI uri = MockRestClient
                        .create(A.class)
                        .simpleJson()
                        .build()
-                       .get("/bean")
+                       .get()
                        .scheme("http")
                        .host("localhost")
                        .port(8080)
                        .userInfo("foo:bar")
+                       .uri("/bean")
+                       .fragment("baz")
+                       .query("foo", "bar")
+                       .run()
+                       .assertBody().is("{f:1}")
+                       .getRequest().getURI();
+               assertEquals("http://foo:bar@localhost:8080/bean?foo=bar#baz";, 
uri.toString());
+
+               uri = MockRestClient
+                       .create(A.class)
+                       .simpleJson()
+                       .build()
+                       .get()
+                       .scheme("http")
+                       .host("localhost")
+                       .port(8080)
+                       .userInfo("foo","bar")
+                       .uri("/bean")
+                       .fragment("baz")
+                       .query("foo", "bar")
                        .run()
                        .assertBody().is("{f:1}")
                        .getRequest().getURI();
-               assertEquals("http://foo:bar@localhost:8080/bean";, 
uri.toString());
+               assertEquals("http://foo:bar@localhost:8080/bean?foo=bar#baz";, 
uri.toString());
+
+               uri = MockRestClient
+                       .create(A.class)
+                       .simpleJson()
+                       .build()
+                       .get()
+                       .uri("http://localhost";)
+                       .uri("http://foo:bar@localhost:8080/bean?foo=bar#baz";)
+                       .run()
+                       .assertBody().is("{f:1}")
+                       .getRequest().getURI();
+               assertEquals("http://foo:bar@localhost:8080/bean?foo=bar#baz";, 
uri.toString());
+
+               uri = MockRestClient
+                       .create(A.class)
+                       .simpleJson()
+                       .build()
+                       .get()
+                       .uri(new java.net.URI(null, null, null, null))
+                       .uri(new 
java.net.URI("http://foo:bar@localhost:8080/bean?foo=bar#baz";))
+                       .run()
+                       .assertBody().is("{f:1}")
+                       .getRequest().getURI();
+               assertEquals("http://foo:bar@localhost:8080/bean?foo=bar#baz";, 
uri.toString());
        }
 
        
//------------------------------------------------------------------------------------------------------------------
@@ -2819,11 +2863,11 @@ public class RestClientTest {
                MockRestClient
                        .create(A.class)
                        .simpleJson()
-                       .query(BasicNameValuePair.of("Foo","f1"))
-                       .query(OMap.of("Foo","f2"))
-                       .query(AMap.of("Foo","f3"))
-                       .query(NameValuePairs.of("Foo","f4","Foo","f5"))
-                       .query(BasicNameValuePair.of("Foo","f6"), 
BasicNameValuePair.of("Foo","f7"))
+                       .queries(BasicNameValuePair.of("Foo","f1"))
+                       .queries(OMap.of("Foo","f2"))
+                       .queries(AMap.of("Foo","f3"))
+                       .queries(NameValuePairs.of("Foo","f4","Foo","f5"))
+                       .queries(BasicNameValuePair.of("Foo","f6"), 
BasicNameValuePair.of("Foo","f7"))
                        .build()
                        .get("/checkQuery")
                        .run()
@@ -2932,7 +2976,7 @@ public class RestClientTest {
                MockRestClient
                        .create(A.class)
                        .simpleJson()
-                       .query(BasicNameValuePair.of("Foo","bar"), null)
+                       .queries(BasicNameValuePair.of("Foo","bar"), null)
                        .build()
                        .get("/checkQuery")
                        .run()
@@ -2945,7 +2989,7 @@ public class RestClientTest {
                        MockRestClient
                                .create(A.class)
                                .simpleJson()
-                               .query(BasicNameValuePair.of("Foo","bar"), 
"Baz");
+                               .queries(BasicNameValuePair.of("Foo","bar"), 
"Baz");
                        fail();
                } catch (Exception e) {
                        assertEquals("Invalid type passed to query(Object...):  
java.lang.String", e.getMessage());
@@ -3010,11 +3054,11 @@ public class RestClientTest {
                MockRestClient
                        .create(A.class)
                        .simpleJson()
-                       .formData(BasicNameValuePair.of("Foo","f1"))
-                       .formData(OMap.of("Foo","f2"))
-                       .formData(AMap.of("Foo","f3"))
-                       .formData(NameValuePairs.of("Foo","f4","Foo","f5"))
-                       .formData(BasicNameValuePair.of("Foo","f6"), 
BasicNameValuePair.of("Foo","f7"))
+                       .formDatas(BasicNameValuePair.of("Foo","f1"))
+                       .formDatas(OMap.of("Foo","f2"))
+                       .formDatas(AMap.of("Foo","f3"))
+                       .formDatas(NameValuePairs.of("Foo","f4","Foo","f5"))
+                       .formDatas(BasicNameValuePair.of("Foo","f6"), 
BasicNameValuePair.of("Foo","f7"))
                        .build()
                        .post("/checkFormData")
                        .run()
@@ -3121,7 +3165,7 @@ public class RestClientTest {
                MockRestClient
                        .create(A.class)
                        .simpleJson()
-                       .formData(BasicNameValuePair.of("Foo","bar"), null)
+                       .formDatas(BasicNameValuePair.of("Foo","bar"), null)
                        .build()
                        .post("/checkFormData")
                        .run()
@@ -3134,7 +3178,7 @@ public class RestClientTest {
                        MockRestClient
                                .create(A.class)
                                .simpleJson()
-                               .formData(BasicNameValuePair.of("Foo","bar"), 
"Baz");
+                               .formDatas(BasicNameValuePair.of("Foo","bar"), 
"Baz");
                        fail();
                } catch (Exception e) {
                        assertEquals("Invalid type passed to 
formData(Object...):  java.lang.String", e.getMessage());
@@ -3911,7 +3955,6 @@ public class RestClientTest {
                        .header("Foo",bean)
                        .partSerializer(XPartSerializer.class)
                        .partParser(XPartParser.class)
-                       .header("")
                        .build();
                Bean b = rc
                        .get("/")
@@ -3937,7 +3980,6 @@ public class RestClientTest {
                        .header("Foo",bean)
                        .partSerializer(new XPartSerializer())
                        .partParser(new XPartParser())
-                       .header("")
                        .build();
                Bean b = rc
                        .get("/")
@@ -6377,9 +6419,123 @@ public class RestClientTest {
        }
 
        
//-----------------------------------------------------------------------------------------------------------------
-       // Remote proxies
+       // Path
        
//-----------------------------------------------------------------------------------------------------------------
 
+       public static class Q01 {
+               public int foo;
+               public Q01 init() {
+                       foo = 1;
+                       return this;
+               }
+
+               @Override
+               public String toString() {
+                       return "xxx";
+               }
+       }
+
+       @Test
+       public void q01_request_path() throws Exception {
+               MockRestClient
+                       .create(A.class)
+                       .simpleJson()
+                       .build()
+                       .get("/echo/{x}")
+                       .path("x", new Q01().init())
+                       .run()
+                       .assertBody().contains("HTTP GET /echo/foo=1")
+               ;
+               MockRestClient
+                       .create(A.class)
+                       .simpleJson()
+                       .build()
+                       .get("/echo/{x}")
+                       .path("x", ()->new Q01().init())
+                       .run()
+                       .assertBody().contains("HTTP GET /echo/foo=1")
+               ;
+               MockRestClient
+                       .create(A.class)
+                       .simpleJson()
+                       .build()
+                       .get("/echo/*")
+                       .path("/*", new Q01().init())
+                       .run()
+                       .assertBody().contains("HTTP GET /echo/foo=1")
+               ;
+               MockRestClient
+                       .create(A.class)
+                       .simpleJson()
+                       .build()
+                       .get("/echo/*")
+                       .path("/*", ()->new Q01().init())
+                       .run()
+                       .assertBody().contains("HTTP GET /echo/foo=1")
+                       ;
+       }
+
+       @Test
+       public void q03_request_path_withSchema() throws Exception {
+               String[] a = new String[]{"foo","bar"};
+
+               MockRestClient
+                       .create(A.class)
+                       .simpleJson()
+                       .build()
+                       .get("/echo/{x}")
+                       .path("x", a, HttpPartSchema.T_ARRAY_PIPES)
+                       .run()
+                       .assertBody().contains("HTTP GET /echo/foo%7Cbar")
+               ;
+               MockRestClient
+                       .create(A.class)
+                       .simpleJson()
+                       .build()
+                       .get("/echo/{x}")
+                       .path("x", ()->a, HttpPartSchema.T_ARRAY_PIPES)
+                       .run()
+                       .assertBody().contains("HTTP GET /echo/foo%7Cbar")
+               ;
+       }
+
+       @Test
+       public void q04_request_path_invalid() throws Exception {
+               try {
+                       MockRestClient
+                               .create(A.class)
+                               .simpleJson()
+                               .build()
+                               .get("/echo/{x}")
+                               .path("y", "foo")
+                               .run()
+                               .assertBody().contains("HTTP GET 
/echo/foo%7Cbar")
+                       ;
+                       fail();
+               } catch (RestCallException e) {
+                       assertEquals("Path variable {y} was not found in 
path.", e.getMessage());
+               }
+       }
+
+
+       @Test
+       public void q05_request_path_invalid() throws Exception {
+               try {
+                       MockRestClient
+                               .create(A.class)
+                               .simpleJson()
+                               .build()
+                               .get("/echo/{x}")
+                               .path("y", "foo")
+                               .run()
+                               .assertBody().contains("HTTP GET 
/echo/foo%7Cbar")
+                       ;
+                       fail();
+               } catch (RestCallException e) {
+                       assertEquals("Path variable {y} was not found in 
path.", e.getMessage());
+               }
+       }
+
        
//-----------------------------------------------------------------------------------------------------------------
        // Other methods
        
//-----------------------------------------------------------------------------------------------------------------
diff --git 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestClient.java
 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestClient.java
index c176909..fa9a63f 100644
--- 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestClient.java
+++ 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestClient.java
@@ -281,7 +281,8 @@ import org.apache.http.client.CookieStore;
  *     <ul>
  *             <li class='jm'>{@link RestClientBuilder#header(String,Object) 
header(String,Object)}
  *             <li class='jm'>{@link 
RestClientBuilder#header(String,Object,HttpPartSchema,HttpPartSerializer) 
header(String,Object,HttpPartSerializer,HttpPartSchema)}
- *             <li class='jm'>{@link RestClientBuilder#header(Object) 
header(Object)}
+ *             <li class='jm'>{@link RestClientBuilder#header(Header) 
header(Header)}
+ *             <li class='jm'>{@link RestClientBuilder#header(NameValuePair) 
header(NameValuePair)}
  *             <li class='jm'>{@link RestClientBuilder#headers(Object...) 
headers(Object...)}
  *             <li class='jm'>{@link RestClientBuilder#headerPairs(Object...) 
headerPairs(Object...)}
  *             <li class='jm'>{@link RestClientBuilder#accept(Object) 
accept(Object)}
@@ -320,7 +321,8 @@ import org.apache.http.client.CookieStore;
  *     <ul>
  *             <li class='jm'>{@link RestRequest#header(String,Object) 
header(String,Object)}
  *             <li class='jm'>{@link RestRequest#header(EnumSet,String,Object) 
header(EnumSet&gt;AddFlag&gt;,String,Object)}
- *             <li class='jm'>{@link RestRequest#header(Object) header(Object)}
+ *             <li class='jm'>{@link RestRequest#header(Header) header(Header)}
+ *             <li class='jm'>{@link RestRequest#header(NameValuePair) 
header(NameValuePair)}
  *             <li class='jm'>{@link RestRequest#header(EnumSet,Object) 
header(EnumSet&gt;AddFlag&gt;,Object)}
  *             <li class='jm'>{@link RestRequest#headers(Object...) 
headers(Object...)}
  *             <li class='jm'>{@link RestRequest#headers(EnumSet,Object...) 
headers(EnumSet&gt;AddFlag&gt;Object...)}
@@ -403,14 +405,14 @@ import org.apache.http.client.CookieStore;
  *     <ul>
  *             <li class='jm'>{@link RestClientBuilder#query(String,Object) 
query(String,Object)}
  *             <li class='jm'>{@link 
RestClientBuilder#query(String,Object,HttpPartSchema,HttpPartSerializer) 
query(String,Object,HttpPartSerializer,HttpPartSchema)}
- *             <li class='jm'>{@link RestClientBuilder#query(Object...) 
query(Object...)}
+ *             <li class='jm'>{@link RestClientBuilder#queries(Object...) 
queries(Object...)}
  *             <li class='jm'>{@link RestClientBuilder#queryPairs(Object...) 
queryPairs(Object...)}
  *     </ul>
  *     <li class='jc'>{@link RestRequest}
  *     <ul>
  *             <li class='jm'>{@link RestRequest#query(String,Object) 
query(String,Object)}
  *             <li class='jm'>{@link RestRequest#query(EnumSet,String,Object) 
query(EnumSet&lt;AddFlag&gt;,String,Object)}
- *             <li class='jm'>{@link RestRequest#query(Object...) 
query(Object...)}
+ *             <li class='jm'>{@link RestRequest#queries(Object...) 
queries(Object...)}
  *             <li class='jm'>{@link RestRequest#query(EnumSet,Object...) 
query(EnumSet&lt;AddFlag&gt;,Object...)}
  *             <li class='jm'>{@link RestRequest#queryPairs(Object...) 
queryPairs(Object...)}
  *             <li class='jm'>{@link RestRequest#queryCustom(Object) 
queryCustom(Object)}
@@ -442,14 +444,14 @@ import org.apache.http.client.CookieStore;
  *     <ul>
  *             <li class='jm'>{@link RestClientBuilder#formData(String,Object) 
formData(String,Object)}
  *             <li class='jm'>{@link 
RestClientBuilder#formData(String,Object,HttpPartSchema,HttpPartSerializer) 
formData(String,Object,HttpPartSerializer,HttpPartSchema)}
- *             <li class='jm'>{@link RestClientBuilder#formData(Object...) 
formData(Object...)}
+ *             <li class='jm'>{@link RestClientBuilder#formDatas(Object...) 
formDatas(Object...)}
  *             <li class='jm'>{@link 
RestClientBuilder#formDataPairs(Object...) formDataPairs(Object...)}
  *     </ul>
  *     <li class='jc'>{@link RestRequest}
  *     <ul>
  *             <li class='jm'>{@link RestRequest#formData(String,Object) 
formData(String,Object)}
  *             <li class='jm'>{@link 
RestRequest#formData(EnumSet,String,Object) 
formData(EnumSet&lt;AddFlag&gt;,String,Object)}
- *             <li class='jm'>{@link RestRequest#formData(Object...) 
formData(Object...)}
+ *             <li class='jm'>{@link RestRequest#formDatas(Object...) 
formDatas(Object...)}
  *             <li class='jm'>{@link RestRequest#formData(EnumSet,Object...) 
formData(EnumSet&lt;AddFlag&gt;,Object...)}
  *             <li class='jm'>{@link RestRequest#formDataPairs(Object...) 
formDataPairs(Object...)}
  *             <li class='jm'>{@link RestRequest#formDataCustom(Object) 
formDataCustom(Object)}
@@ -1158,17 +1160,17 @@ public class RestClient extends BeanContext implements 
HttpClient, Closeable, Re
         *                      <ul>
         *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestClientBuilder#formData(String,Object) 
formData(String,Object)}
         *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestClientBuilder#formData(String,Object,HttpPartSchema,HttpPartSerializer)
 formData(String,Object,HttpPartSerializer,HttpPartSchema)}
-        *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestClientBuilder#formData(Object...) 
formData(Map<String, Object>)}
-        *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestClientBuilder#formDataPairs(Object...) 
formData(Map<String, Object>)}
+        *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestClientBuilder#formDatas(Object...) 
formDatas(Object...)}
+        *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestClientBuilder#formDataPairs(Object...) 
formDataPairs(Map<String, Object>)}
         *                      </ul>
         *                      <li class='jc'>{@link 
org.apache.juneau.rest.client2.RestRequest}
         *                      <ul>
         *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestRequest#formData(String,Object) 
formData(String,Object)}
         *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestRequest#formData(EnumSet,String,Object) 
formData(EnumSet&lt;AddFlag&gt;,String,Object)}
-        *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestRequest#formData(Object...) 
formData(Object...)}
+        *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestRequest#formDatas(Object...) 
formDatas(Object...)}
         *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestRequest#formData(EnumSet,Object...) 
formData(EnumSet&lt;AddFlag&gt;Object...)}
         *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestRequest#formDataPairs(Object...) 
formDataPairs(Object...)}
-        *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestRequest#formDataCustom(Object) 
customFormData(Object)}
+        *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestRequest#formDataCustom(Object) 
formDataCustom(Object)}
         *                      </ul>
         *              </ul>
         * </ul>
@@ -1194,7 +1196,8 @@ public class RestClient extends BeanContext implements 
HttpClient, Closeable, Re
         *                      <ul>
         *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestClientBuilder#header(String,Object) 
header(String,Object)}
         *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestClientBuilder#header(String,Object,HttpPartSchema,HttpPartSerializer)
 header(String,Object,HttpPartSerializer,HttpPartSchema)}
-        *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestClientBuilder#header(Object) header(Object)}
+        *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestClientBuilder#header(Header) header(Header)}
+        *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestClientBuilder#header(NameValuePair) 
header(NameValuePair)}
         *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestClientBuilder#headers(Object...) 
headers(Object...)}
         *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestClientBuilder#headerPairs(Object...) 
headerPairs(Object...)}
         *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestClientBuilder#accept(Object) accept(Object)}
@@ -1233,7 +1236,8 @@ public class RestClient extends BeanContext implements 
HttpClient, Closeable, Re
         *                      <ul>
         *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestRequest#header(String,Object) 
header(String,Object)}
         *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestRequest#header(EnumSet,String,Object) 
header(EnumSet&gt;AddFlag&gt;,String,Object)}
-        *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestRequest#header(Object) header(Object)}
+        *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestRequest#header(Header) header(Header)}
+        *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestRequest#header(NameValuePair) 
header(NameValuePair)}
         *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestRequest#header(EnumSet,Object) 
header(EnumSet&gt;AddFlag&gt;,Object)}
         *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestRequest#headers(Object...) 
headers(Object...)}
         *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestRequest#headers(EnumSet,Object...) 
headers(EnumSet&gt;AddFlag&gt;,Object...)}
@@ -1759,7 +1763,7 @@ public class RestClient extends BeanContext implements 
HttpClient, Closeable, Re
         *              <ul>
         *                      <li class='jc'>{@link 
org.apache.juneau.rest.client2.RestClientBuilder}
         *                      <ul>
-        *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestClientBuilder#query(Object...) 
query(Object...)}
+        *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestClientBuilder#queries(Object...) 
queries(Object...)}
         *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestClientBuilder#query(String,Object) 
query(String,Object)}
         *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestClientBuilder#query(String,Object,HttpPartSchema,HttpPartSerializer)
 query(String,Object,HttpPartSerializer,HttpPartSchema)}
         *                      </ul>
@@ -1767,7 +1771,7 @@ public class RestClient extends BeanContext implements 
HttpClient, Closeable, Re
         *                      <ul>
         *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestRequest#query(String,Object) 
query(String,Object)}
         *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestRequest#query(EnumSet,String,Object) 
query(EnumSet&lt;AddFlag&gt;,String,Object)}
-        *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestRequest#query(Object...) query(Object...)}
+        *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestRequest#queries(Object...) 
queries(Object...)}
         *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestRequest#query(EnumSet,Object...) 
query(EnumSet&lt;AddFlag&gt;,Object...)}
         *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestRequest#queryPairs(Object...) 
queryPairs(Object...)}
         *                              <li class='jm'>{@link 
org.apache.juneau.rest.client2.RestRequest#queryCustom(Object) 
queryCustom(Object)}
@@ -2717,7 +2721,7 @@ public class RestClient extends BeanContext implements 
HttpClient, Closeable, Re
                        RestRequest req = request(method, uri, 
isNotEmpty(content));
                        if (headers != null)
                                for (Map.Entry<String,Object> e : 
OMap.ofJson(headers).entrySet())
-                                       req.headerString(e.getKey(), 
e.getValue());
+                                       
req.header(BasicNameValuePair.of(e.getKey(), e.getValue()));
                        if (isNotEmpty(content))
                                req.bodyString(content);
                        return req;
@@ -2834,7 +2838,7 @@ public class RestClient extends BeanContext implements 
HttpClient, Closeable, Re
                        throw new RestCallException("RestClient.close() has 
already been called.  This client cannot be reused.  Closed location stack 
trace can be displayed by setting the system property 
'org.apache.juneau.rest.client2.RestClient.trackCreation' to true.");
                }
 
-               RestRequest req = createRequest(toURI(url), 
method.toUpperCase(Locale.ENGLISH), hasBody);
+               RestRequest req = createRequest(toURI(url, rootUrl), 
method.toUpperCase(Locale.ENGLISH), hasBody);
 
                for (Object o : headers)
                        req.header(toHeader(o));
@@ -3609,7 +3613,7 @@ public class RestClient extends BeanContext implements 
HttpClient, Closeable, Re
 
        private Pattern absUrlPattern = Pattern.compile("^\\w+\\:\\/\\/.*");
 
-       URI toURI(Object url) throws RestCallException {
+       URI toURI(Object url, String rootUrl) throws RestCallException {
                try {
                        if (url instanceof URI)
                                return (URI)url;
diff --git 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestClientBuilder.java
 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestClientBuilder.java
index 19717da..5bb4302 100644
--- 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestClientBuilder.java
+++ 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestClientBuilder.java
@@ -1222,15 +1222,11 @@ public class RestClientBuilder extends 
BeanContextBuilder {
        /**
         * Sets a header on all requests.
         *
-        * <p>
-        * Unlike {@link #header(String,Object)} which converts the value to a 
string using the part serializer, this
-        * method converts the value to a string using {@link 
Object#toString()}.
-        *
         * <h5 class='section'>Example:</h5>
         * <p class='bcode w800'>
         *      RestClient c = RestClient
         *              .<jsm>create</jsm>()
-        *              .headerString(<js>"Foo"</js>, <js>"bar"</js>);
+        *              .header(<js>"Foo"</js>, ()-&gt;<js>"bar"</js>);
         *              .build();
         * </p>
         *
@@ -1239,17 +1235,17 @@ public class RestClientBuilder extends 
BeanContextBuilder {
         * </ul>
         *
         * @param name The header name.
-        * @param value The header value.
+        * @param value The header value supplier.
         *      <ul>
         *              <li>Can be any POJO.
-        *              <li>Converted to a string using {@link 
Object#toString()}.
+        *              <li>Converted to a string using the specified part 
serializer.
         *              <li>Values are converted to strings at runtime to allow 
them to be modified externally.
         *      </ul>
         * @return This object (for method chaining).
         */
        @FluentSetter
-       public RestClientBuilder headerString(String name, Object value) {
-               return header(BasicStringHeader.of(name, value));
+       public RestClientBuilder header(String name, Supplier<?> value) {
+               return header(name, value, (HttpPartSchema)null, null);
        }
 
        /**
@@ -1259,26 +1255,16 @@ public class RestClientBuilder extends 
BeanContextBuilder {
         * <p class='bcode w800'>
         *      RestClient c = RestClient
         *              .<jsm>create</jsm>()
-        *              .header(<js>"Foo"</js>, ()-&gt;<js>"bar"</js>);
+        *              .header(BasicHeader.<jsm>of</jsm>(<js>"Foo"</js>, 
<js>"bar"</js>))
         *              .build();
         * </p>
         *
-        * <ul class='seealso'>
-        *      <li class='jf'>{@link RestClient#RESTCLIENT_headers}
-        * </ul>
-        *
-        * @param name The header name.
-        * @param value The header value supplier.
-        *      <ul>
-        *              <li>Can be any POJO.
-        *              <li>Converted to a string using the specified part 
serializer.
-        *              <li>Values are converted to strings at runtime to allow 
them to be modified externally.
-        *      </ul>
+        * @param header The header to set.
         * @return This object (for method chaining).
         */
        @FluentSetter
-       public RestClientBuilder header(String name, Supplier<?> value) {
-               return header(name, value, (HttpPartSchema)null, null);
+       public RestClientBuilder header(Header header) {
+               return appendTo(RESTCLIENT_headers, header);
        }
 
        /**
@@ -1288,23 +1274,16 @@ public class RestClientBuilder extends 
BeanContextBuilder {
         * <p class='bcode w800'>
         *      RestClient c = RestClient
         *              .<jsm>create</jsm>()
-        *              .header(<jk>new</jk> BasicHeader(<js>"Foo"</js>, 
<js>"bar"</js>))
+        *              
.header(BasicNameValuePair.<jsm>of</jsm>(<js>"Foo"</js>, <js>"bar"</js>))
         *              .build();
         * </p>
         *
-        * <p>
-        * Can be any of the following types:
-        * <ul>
-        *      <li>{@link Header} (including any subclasses such as {@link 
Accept})
-        *      <li>{@link NameValuePair}
-        * </ul>
-        *
-        * @param header The header to set.
+        * @param pair The header to set.
         * @return This object (for method chaining).
         */
        @FluentSetter
-       public RestClientBuilder header(Object header) {
-               return appendTo(RESTCLIENT_headers, header);
+       public RestClientBuilder header(NameValuePair pair) {
+               return appendTo(RESTCLIENT_headers, pair);
        }
 
        /**
@@ -1314,7 +1293,7 @@ public class RestClientBuilder extends BeanContextBuilder 
{
         * <p class='bcode w800'>
         *      RestClient c = RestClient
         *              .<jsm>create</jsm>()
-        *              .headers(<jk>new</jk> BasicHeader(<js>"Foo"</js>, 
<js>"bar"</js>))
+        *              .headers(BasicHeader.<jsm>of</jsm>(<js>"Foo"</js>, 
<js>"bar"</js>))
         *              .build();
         * </p>
         *
@@ -1344,8 +1323,10 @@ public class RestClientBuilder extends 
BeanContextBuilder {
        @FluentSetter
        public RestClientBuilder headers(Object...headers) {
                for (Object h : headers) {
-                       if (h instanceof Header || h instanceof NameValuePair)
-                               header(h);
+                       if (h instanceof Header)
+                               header((Header)h);
+                       else if (h instanceof NameValuePair)
+                               header((NameValuePair)h);
                        else if (h instanceof Map) {
                                Map m = (Map)h;
                                for (Map.Entry e : (Set<Map.Entry>)m.entrySet())
@@ -2018,30 +1999,20 @@ public class RestClientBuilder extends 
BeanContextBuilder {
        /**
         * Adds a query parameter to the URI.
         *
-        * <p>
-        * Unlike {@link #query(String,Object)} which converts the value to a 
string using the part serializer, this
-        * method converts the value to a string using {@link 
Object#toString()}.
-        *
         * <h5 class='section'>Example:</h5>
         * <p class='bcode w800'>
         *      RestClient c = RestClient
         *              .<jsm>create</jsm>()
-        *              .queryString(<js>"foo"</js>, <js>"bar"</js>)
+        *              .query(BasicNameValuePair.<jsm>of</jsm>(<js>"foo"</js>, 
<js>"bar"</js>))
         *              .build();
         * </p>
         *
-        * @param name The parameter name.
-        * @param value The parameter value.
-        *      <ul>
-        *              <li>Can be any POJO.
-        *              <li>Converted to a string using {@link 
Object#toString()}.
-        *              <li>Values are converted to strings at runtime to allow 
them to be modified externally.
-        *      </ul>
+        * @param pair The query parameter.
         * @return This object (for method chaining).
         */
        @FluentSetter
-       public RestClientBuilder queryString(String name, Object value) {
-               return query(BasicNameValuePair.of(name, value));
+       public RestClientBuilder query(NameValuePair pair) {
+               return queries(pair);
        }
 
        /**
@@ -2076,7 +2047,7 @@ public class RestClientBuilder extends BeanContextBuilder 
{
         * <p class='bcode w800'>
         *      RestClient c = RestClient
         *              .<jsm>create</jsm>()
-        *              .query(<jk>new</jk> BasicNameValuePair(<js>"foo"</js>, 
<js>"bar"</js>))
+        *              
.queries(BasicNameValuePair.<jsm>of</jsm>(<js>"foo"</js>, <js>"bar"</js>))
         *              .build();
         * </p>
         *
@@ -2103,7 +2074,7 @@ public class RestClientBuilder extends BeanContextBuilder 
{
         */
        @SuppressWarnings("rawtypes")
        @FluentSetter
-       public RestClientBuilder query(Object...params) {
+       public RestClientBuilder queries(Object...params) {
                for (Object p : params) {
                        if (p instanceof NameValuePair) {
                                appendTo(RESTCLIENT_query, p);
@@ -2113,7 +2084,7 @@ public class RestClientBuilder extends BeanContextBuilder 
{
                                        query(stringify(e.getKey()), 
e.getValue(), null, null);
                        } else if (p instanceof NameValuePairs) {
                                for (NameValuePair nvp : (NameValuePairs)p)
-                                       query(nvp);
+                                       queries(nvp);
                        } else if (p != null) {
                                throw new RuntimeException("Invalid type passed 
to query(Object...):  " + p.getClass().getName());
                        }
@@ -2317,30 +2288,20 @@ public class RestClientBuilder extends 
BeanContextBuilder {
        /**
         * Adds a form-data parameter to all request bodies.
         *
-        * <p>
-        * Unlike {@link #formData(String,Object)} which converts the value to 
a string using the part serializer, this
-        * method converts the value to a string using {@link 
Object#toString()}.
-
         * <h5 class='section'>Example:</h5>
         * <p class='bcode w800'>
         *      RestClient c = RestClient
         *              .<jsm>create</jsm>()
-        *              .formDataString(<js>"foo"</js>, <js>"bar"</js>)
+        *              
.formData(BasicNameValuePair.<jsm>of</jsm>(<js>"foo"</js>, <js>"bar"</js>))
         *              .build();
         * </p>
         *
-        * @param name The parameter name.
-        * @param value The parameter value.
-        *      <ul>
-        *              <li>Can be any POJO.
-        *              <li>Converted to a string using {@link 
Object#toString()}.
-        *              <li>Values are converted to strings at runtime to allow 
them to be modified externally.
-        *      </ul>
+        * @param pair The form data parameter.
         * @return This object (for method chaining).
         */
-        @FluentSetter
-       public RestClientBuilder formDataString(String name, Object value) {
-               return formData(BasicNameValuePair.of(name, value));
+       @FluentSetter
+       public RestClientBuilder formData(NameValuePair pair) {
+               return formDatas(pair);
        }
 
        /**
@@ -2375,7 +2336,7 @@ public class RestClientBuilder extends BeanContextBuilder 
{
         * <p class='bcode w800'>
         *      RestClient c = RestClient
         *              .<jsm>create</jsm>()
-        *              .formData(<jk>new</jk> 
BasicNameValuePair(<js>"foo"</js>, <js>"bar"</js>))
+        *              
.formData(BasicNameValuePair.<jsm>of</jsm>(<js>"foo"</js>, <js>"bar"</js>))
         *              .build();
         * </p>
         *
@@ -2402,7 +2363,7 @@ public class RestClientBuilder extends BeanContextBuilder 
{
         */
        @SuppressWarnings("rawtypes")
        @FluentSetter
-       public RestClientBuilder formData(Object...params) {
+       public RestClientBuilder formDatas(Object...params) {
                for (Object p : params) {
                        if (p instanceof NameValuePair) {
                                appendTo(RESTCLIENT_formData, p);
@@ -2412,7 +2373,7 @@ public class RestClientBuilder extends BeanContextBuilder 
{
                                        formData(stringify(e.getKey()), 
e.getValue(), null, null);
                        } else if (p instanceof NameValuePairs) {
                                for (NameValuePair nvp : (NameValuePairs)p)
-                                       formData(nvp);
+                                       formDatas(nvp);
                        } else if (p != null) {
                                throw new RuntimeException("Invalid type passed 
to formData(Object...):  " + p.getClass().getName());
                        }
diff --git 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestRequest.java
 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestRequest.java
index 3f4f2af..b834687 100644
--- 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestRequest.java
+++ 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestRequest.java
@@ -770,7 +770,20 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
         * @throws RestCallException Invalid URI syntax detected.
         */
        public RestRequest uri(Object uri) throws RestCallException {
-               uriBuilder = new URIBuilder(client.toURI(uri));
+               URI x = client.toURI(uri, null);
+               if (x.getScheme() != null)
+                       uriBuilder.setScheme(x.getScheme());
+               if (x.getHost() != null)
+                       uriBuilder.setHost(x.getHost());
+               if (x.getPort() != -1)
+                       uriBuilder.setPort(x.getPort());
+               if (x.getUserInfo() != null)
+                       uriBuilder.setUserInfo(x.getUserInfo());
+               if (x.getFragment() != null)
+                       uriBuilder.setFragment(x.getFragment());
+               if (x.getQuery() != null)
+                       uriBuilder.setCustomQuery(x.getQuery());
+               uriBuilder.setPath(x.getPath());
                return this;
        }
 
@@ -867,37 +880,26 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
         * @throws RestCallException Invalid input.
         */
        public RestRequest path(String name, Object value) throws 
RestCallException {
-               return path(name, value, null, null);
+               return path(name, value, null, partSerializer);
        }
 
        /**
         * Replaces a path parameter of the form <js>"{name}"</js> in the URL.
         *
-        * <p>
-        * Unlike {@link #path(String,Object)} which converts the value to a 
string using the part serializer, this
-        * method converts the value to a string using {@link 
Object#toString()}.
-        *
         * <h5 class='section'>Example:</h5>
         * <p class='bcode w800'>
         *      client
         *              .get(<js>"/{foo}"</js>)
-        *              .pathString(<js>"foo"</js>, <js>"bar"</js>)
+        *              .path(BasicNameValuePair.<jsm>of</jsm>(<js>"foo"</js>, 
<js>"bar"</js>))
         *              .run();
         * </p>
         *
-        * @param name The parameter name.
-        * @param value The parameter value.
-        *      <ul>
-        *              <li>Can be any POJO.
-        *              <li>Converted to a string using {@link 
Object#toString()}.
-        *              <li>Values are converted to strings at runtime to allow 
them to be modified externally.
-        *      </ul>
+        * @param pair The parameter.
         * @return This object (for method chaining).
         * @throws RestCallException Invalid input.
         */
-       @FluentSetter
-       public RestRequest pathString(String name, Object value) throws 
RestCallException {
-               return path(BasicNameValuePair.of(name, value));
+       public RestRequest path(NameValuePair pair) throws RestCallException {
+               return innerPath(pair);
        }
 
        /**
@@ -911,7 +913,9 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
         *              .run();
         * </p>
         *
-        * @param name The parameter name.
+        * @param name
+        *      The parameter name.
+        *      <br>Can also be <js>"/*"</js> to replace the remainder in a 
path of the form <js>"/foo/*"</js>.
         * @param value The parameter value supplier.
         *      <ul>
         *              <li>Can be any POJO.
@@ -922,7 +926,7 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
         * @throws RestCallException Invalid input.
         */
        public RestRequest path(String name, Supplier<?> value) throws 
RestCallException {
-               return path(name, value, null, null);
+               return path(name, value, null, partSerializer);
        }
 
        /**
@@ -940,7 +944,9 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
         *              .run();
         * </p>
         *
-        * @param name The parameter name.
+        * @param name
+        *      The parameter name.
+        *      <br>Can also be <js>"/*"</js> to replace the remainder in a 
path of the form <js>"/foo/*"</js>.
         * @param value The parameter value.
         *      <ul>
         *              <li>Can be any POJO.
@@ -952,7 +958,7 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
         * @throws RestCallException Invalid input.
         */
        public RestRequest path(String name, Object value, HttpPartSchema 
schema) throws RestCallException {
-               return path(name, value, schema, null);
+               return path(name, value, schema, partSerializer);
        }
 
        /**
@@ -970,7 +976,9 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
         *              .run();
         * </p>
         *
-        * @param name The parameter name.
+        * @param name
+        *      The parameter name.
+        *      <br>Can also be <js>"/*"</js> to replace the remainder in a 
path of the form <js>"/foo/*"</js>.
         * @param value The parameter value supplier.
         *      <ul>
         *              <li>Can be any POJO.
@@ -982,156 +990,62 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
         * @throws RestCallException Invalid input.
         */
        public RestRequest path(String name, Supplier<?> value, HttpPartSchema 
schema) throws RestCallException {
-               return path(name, value, schema, null);
-       }
-
-       /**
-        * Replaces a path parameter of the form <js>"{name}"</js> in the URL.
-        *
-        * <h5 class='section'>Example:</h5>
-        * <p class='bcode w800'>
-        *      client
-        *              .get(<js>"/{foo}"</js>)
-        *              .path(<jk>new</jk> BasicNameValuePair(<js>"foo"</js>, 
<js>"bar"</js>))
-        *              .run();
-        * </p>
-        *
-        * @param param The path parameter.
-        * @return This object (for method chaining).
-        * @throws RestCallException Invalid input.
-        */
-       public RestRequest path(NameValuePair param) throws RestCallException {
-               String path = uriBuilder.getPath();
-               String name = param.getName(), value = param.getValue();
-               String var = "{" + name + "}";
-               if (path.indexOf(var) == -1 && ! name.equals("/*"))
-                       throw new RestCallException("Path variable {"+name+"} 
was not found in path.");
-               String p = null;
-               if (name.equals("/*"))
-                       p = path.replaceAll("\\/\\*$", value);
-               else
-                       p = path.replace(var, String.valueOf(value));
-               uriBuilder.setPath(p);
-               return this;
+               return path(name, value, schema, partSerializer);
        }
 
        /**
-        * Replaces path parameters of the form <js>"{name}"</js> in the URL.
+        * Replaces multiple path parameter of the form <js>"{name}"</js> in 
the URL.
         *
         * <h5 class='section'>Example:</h5>
         * <p class='bcode w800'>
         *      client
-        *              .get(<js>"/{foo}"</js>)
-        *              .path(OMap.<jsm>of</js>(<js>"foo"</js>, <js>"bar"</js>))
-        *              .run();
-        * </p>
-        *
-        * @param params The path parameters.
-        *      <ul>
-        *              <li>Values can be any POJO.
-        *              <li>Values converted to a string using the configured 
part serializer.
-        *              <li>Values are converted to strings at runtime to allow 
them to be modified externally.
-        *      </ul>
-        * @return This object (for method chaining).
-        * @throws RestCallException Invalid input.
-        */
-       public RestRequest path(OMap params) throws RestCallException {
-               return path((Map<String,Object>)params);
-       }
-
-       /**
-        * Replaces path parameters of the form <js>"{name}"</js> in the URL.
-        *
-        * <h5 class='section'>Example:</h5>
-        * <p class='bcode w800'>
-        *      client
-        *              .get(<js>"/{foo}"</js>)
-        *              .path(AMap.<jsm>create</jsm>().append(<js>"foo"</js>, 
<js>"bar"</js>))
+        *              .get(<jsf>URL</jsf>)
+        *              .path(BasicNameValuePair.<jsm>of</jsm>(<js>"foo"</js>, 
<js>"bar"</js>))
         *              .run();
         * </p>
         *
-        * @param params The path parameters.
+        * @param params The parameters to set.
+        *      <br>Can be any of the following types:
         *      <ul>
-        *              <li>Values can be any POJO.
-        *              <li>Values converted to a string using the configured 
part serializer.
-        *              <li>Values are converted to strings at runtime to allow 
them to be modified externally.
+        *              <li>{@link NameValuePair}
+        *              <li>{@link Map} / {@link OMap} / bean
+        *              <ul>
+        *                      <li>Values can be any POJO.
+        *                      <li>Values converted to a string using the 
configured part serializer.
+        *                      <li>Values are converted to strings at runtime 
to allow them to be modified externally.
+        *              </ul>
+        *              <li>{@link NameValuePairs}
+        *              <ul>
+        *                      <li>Values converted directly to strings.
+        *              </ul>
+        *              <li><jk>null</jk> - Will be a no-op.
         *      </ul>
         * @return This object (for method chaining).
         * @throws RestCallException Invalid input.
         */
-       public RestRequest path(Map<String,Object> params) throws 
RestCallException {
-               for (Map.Entry<String,Object> e : params.entrySet())
-                       path(e.getKey(), e.getValue(), null, null);
-               return this;
-       }
-
-       /**
-        * Replaces path parameters of the form <js>"{name}"</js> in the URL.
-        *
-        * <h5 class='section'>Example:</h5>
-        * <p class='bcode w800'>
-        *      client
-        *              .get(<js>"/{foo}"</js>)
-        *              .path(<jk>new</jk> NameValuePairs(<js>"foo"</js>, 
<js>"bar"</js>))
-        *              .run();
-        * </p>
-        *
-        * @param params The path parameters.
-        * @return This object (for method chaining).
-        * @throws RestCallException Invalid input.
-        */
-       public RestRequest path(NameValuePairs params) throws RestCallException 
{
-               for (NameValuePair p : params)
-                       path(p);
-               return this;
-       }
-
-       /**
-        * Replaces path parameters of the form <js>"{name}"</js> in the URL.
-        *
-        * <h5 class='section'>Example:</h5>
-        * <p class='bcode w800'>
-        *      client
-        *              .get(<js>"/{foo}"</js>)
-        *              .path(<jk>new</jk> BasicNameValuePair(<js>"foo"</js>, 
<js>"bar"</js>))
-        *              .run();
-        * </p>
-        *
-        * @param params The path parameters.
-        * @return This object (for method chaining).
-        * @throws RestCallException Invalid input.
-        */
-       public RestRequest path(NameValuePair...params) throws 
RestCallException {
-               for (NameValuePair p : params)
-                       path(p);
+       @SuppressWarnings("rawtypes")
+       public RestRequest paths(Object...params) throws RestCallException {
+               for (Object o : params) {
+                       if (o instanceof NameValuePair) {
+                               innerPath((NameValuePair)o);
+                       } else if (o instanceof NameValuePairs) {
+                               for (NameValuePair p : (NameValuePairs)o)
+                                       innerPath(p);
+                       } else if (o instanceof Map) {
+                               Map m = (Map)o;
+                               for (Map.Entry e : (Set<Map.Entry>)m.entrySet())
+                                       innerPath(new 
SerializedNameValuePair(stringify(e.getKey()), e.getValue(), PATH, 
partSerializer, null, false));
+                       } else if (isBean(o)) {
+                               for (Map.Entry<String,Object> e : 
toBeanMap(o).entrySet())
+                                       innerPath(new 
SerializedNameValuePair(stringify(e.getKey()), e.getValue(), PATH, 
partSerializer, null, false));
+                       } else {
+                               throw new RestCallException("Invalid type 
passed to path(): " + o.getClass().getName());
+                       }
+               }
                return this;
        }
 
        /**
-        * Replaces path parameters of the form <js>"{name}"</js> in the URL 
using a bean with key/value properties.
-        *
-        * <h5 class='section'>Example:</h5>
-        * <p class='bcode w800'>
-        *      client
-        *              .get(<js>"/{foo}"</js>)
-        *              .path(<jk>new</jk> MyBean())
-        *              .run();
-        * </p>
-        *
-        * @param bean The path bean.
-        *      <ul>
-        *              <li>Values can be any POJO.
-        *              <li>Values converted to a string using the configured 
part serializer.
-        *              <li>Values are converted to strings at runtime to allow 
them to be modified externally.
-        *      </ul>
-        * @return This object (for method chaining).
-        * @throws RestCallException Invalid input.
-        */
-       public RestRequest path(Object bean) throws RestCallException {
-               return path(toBeanMap(bean));
-       }
-
-       /**
         * Replaces path parameters of the form <js>"{name}"</js> in the URL 
using free-form key/value pairs.
         *
         * <h5 class='section'>Example:</h5>
@@ -1155,7 +1069,7 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
                if (pairs.length % 2 != 0)
                        throw new RestCallException("Odd number of parameters 
passed into path(Object...)");
                for (int i = 0; i < pairs.length; i+=2)
-                       path(new SerializedNameValuePair(stringify(pairs[i]), 
pairs[i+1], PATH, partSerializer, null, false));
+                       paths(new SerializedNameValuePair(stringify(pairs[i]), 
pairs[i+1], PATH, partSerializer, null, false));
                return this;
        }
 
@@ -1164,16 +1078,16 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
                serializer = (serializer == null ? partSerializer : serializer);
                boolean isMulti = isEmpty(name) || "*".equals(name) || value 
instanceof NameValuePairs;
                if (! isMulti) {
-                       path(new SerializedNameValuePair(name, value, PATH, 
serializer, schema, false));
+                       innerPath(new SerializedNameValuePair(name, value, 
PATH, serializer, schema, false));
                } else if (value instanceof NameValuePairs) {
                        for (NameValuePair p : (NameValuePairs)value)
-                               path(p);
+                               innerPath(p);
                } else if (value instanceof Map) {
                        for (Map.Entry<String,Object> p : ((Map<String,Object>) 
value).entrySet()) {
                                String n = p.getKey();
                                Object v = p.getValue();
                                HttpPartSchema s = schema == null ? null : 
schema.getProperty(n);
-                               path(new SerializedNameValuePair(n, v, PATH, 
serializer, s, false));
+                               innerPath(new SerializedNameValuePair(n, v, 
PATH, serializer, s, false));
                        }
                } else if (isBean(value)) {
                        return path(name, toBeanMap(value), schema, serializer);
@@ -1183,6 +1097,21 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
                return this;
        }
 
+       private RestRequest innerPath(NameValuePair param) throws 
RestCallException {
+               String path = uriBuilder.getPath();
+               String name = param.getName(), value = param.getValue();
+               String var = "{" + name + "}";
+               if (path.indexOf(var) == -1 && ! name.equals("/*"))
+                       throw new RestCallException("Path variable {"+name+"} 
was not found in path.");
+               String p = null;
+               if (name.equals("/*"))
+                       p = path.replaceAll("\\/\\*$", "/" + value);
+               else
+                       p = path.replace(var, String.valueOf(value));
+               uriBuilder.setPath(p);
+               return this;
+       }
+
        
//------------------------------------------------------------------------------------------------------------------
        // Query
        
//------------------------------------------------------------------------------------------------------------------
@@ -1342,31 +1271,20 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
        /**
         * Adds a query parameter to the URI.
         *
-        * <p>
-        * Unlike {@link #query(String,Object)} which converts the value to a 
string using the part serializer, this
-        * method converts the value to a string using {@link 
Object#toString()}.
-        *
         * <h5 class='section'>Example:</h5>
         * <p class='bcode w800'>
         *      client
         *              .get(<jsf>URL</jsf>)
-        *              .queryString(<js>"foo"</js>, <js>"bar"</js>)
+        *              .query(BasicNameValuePair.<jsm>of</jsm>(<js>"foo"</js>, 
<js>"bar"</js>))
         *              .run();
         * </p>
         *
-        * @param name The parameter name.
-        * @param value The parameter value.
-        *      <ul>
-        *              <li>Can be any POJO.
-        *              <li>Converted to a string using {@link 
Object#toString()}.
-        *              <li>Values are converted to strings at runtime to allow 
them to be modified externally.
-        *      </ul>
+        * @param pair The parameter.
         * @return This object (for method chaining).
         * @throws RestCallException Invalid input.
         */
-       @FluentSetter
-       public RestRequest queryString(String name, Object value) throws 
RestCallException {
-               return query(BasicNameValuePair.of(name, value));
+       public RestRequest query(NameValuePair pair) throws RestCallException {
+               return queries(pair);
        }
 
        /**
@@ -1640,7 +1558,7 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
         * <p class='bcode w800'>
         *      client
         *              .get(<jsf>URL</jsf>)
-        *              .query(<jk>new</jk> BasicNameValuePair(<js>"foo"</js>, 
<js>"bar"</js>))
+        *              .query(BasicNameValuePair.<jsm>of</jsm>(<js>"foo"</js>, 
<js>"bar"</js>))
         *              .run();
         * </p>
         *
@@ -1663,7 +1581,7 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
         * @return This object (for method chaining).
         * @throws RestCallException Invalid input.
         */
-       public RestRequest query(Object...params) throws RestCallException {
+       public RestRequest queries(Object...params) throws RestCallException {
                return query(DEFAULT_FLAGS, params);
        }
 
@@ -1674,7 +1592,7 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
         * <p class='bcode w800'>
         *      client
         *              .get(<jsf>URL</jsf>)
-        *              
.query(EnumSet.<jsm>of</jsm>(<jsf>REPLACE</jsf>,<jsf>SKIP_IF_EMPTY</jsf>),<jk>new</jk>
 BasicNameValuePair(<js>"Foo"</js>, <js>"bar"</js>))
+        *              
.query(EnumSet.<jsm>of</jsm>(<jsf>REPLACE</jsf>,<jsf>SKIP_IF_EMPTY</jsf>),BasicNameValuePair.<jsm>of</jsm>(<js>"Foo"</js>,
 <js>"bar"</js>))
         *              .run();
         * </p>
         *
@@ -1753,7 +1671,7 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
                if (pairs.length % 2 != 0)
                        throw new RestCallException("Odd number of parameters 
passed into query(Object...)");
                for (int i = 0; i < pairs.length; i+=2)
-                       query(new SerializedNameValuePair(stringify(pairs[i]), 
pairs[i+1], QUERY, partSerializer, null, false));
+                       queries(new 
SerializedNameValuePair(stringify(pairs[i]), pairs[i+1], QUERY, partSerializer, 
null, false));
                return this;
        }
 
@@ -1805,7 +1723,7 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
                flags = AddFlag.orDefault(flags);
                boolean isMulti = isEmpty(name) || "*".equals(name) || value 
instanceof NameValuePairs;
                if (! isMulti) {
-                       innerQuery(flags, toQuery(flags, name, value, 
serializer, schema));
+                       innerQuery(flags, AList.of(toQuery(flags, name, value, 
serializer, schema)));
                } else if (value instanceof NameValuePairs) {
                        innerQuery(flags, AList.of((NameValuePairs)value));
                } else if (value instanceof Map) {
@@ -1820,10 +1738,6 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
                return this;
        }
 
-       private RestRequest innerQuery(EnumSet<AddFlag> flags, NameValuePair 
param) {
-               return innerQuery(flags, AList.of(param));
-       }
-
        private RestRequest innerQuery(EnumSet<AddFlag> flags, 
List<NameValuePair> params) {
                flags = AddFlag.orDefault(flags);
                params.removeIf(x -> x == null || x.getValue() == null);
@@ -2010,31 +1924,20 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
        /**
         * Adds a form-data parameter to the request body.
         *
-        * <p>
-        * Unlike {@link #formData(String,Object)} which converts the value to 
a string using the part serializer, this
-        * method converts the value to a string using {@link 
Object#toString()}.
-        *
         * <h5 class='section'>Example:</h5>
         * <p class='bcode w800'>
         *      client
         *              .formPost(<jsf>URL</jsf>)
-        *              .formDataString(<js>"foo"</js>, <js>"bar"</js>)
+        *              
.formData(BasicNameValuePair.<jsm>of</jsm>(<js>"foo"</js>, <js>"bar"</js>))
         *              .run();
         * </p>
         *
-        * @param name The parameter name.
-        * @param value The parameter value.
-        *      <ul>
-        *              <li>Can be any POJO.
-        *              <li>Converted to a string using {@link 
Object#toString()}.
-        *              <li>Values are converted to strings at runtime to allow 
them to be modified externally.
-        *      </ul>
+        * @param pair The parameter.
         * @return This object (for method chaining).
         * @throws RestCallException Invalid input.
         */
-       @FluentSetter
-       public RestRequest formDataString(String name, Object value) throws 
RestCallException {
-               return formData(BasicNameValuePair.of(name, value));
+       public RestRequest formData(NameValuePair pair) throws 
RestCallException {
+               return formDatas(pair);
        }
 
        /**
@@ -2308,7 +2211,7 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
         * <p class='bcode w800'>
         *      client
         *              .formPost(<jsf>URL</jsf>)
-        *              .formData(<jk>new</jk> 
BasicNameValuePair(<js>"foo"</js>, <js>"bar"</js>))
+        *              
.formData(BasicNameValuePair.<jsm>of</jsm>(<js>"foo"</js>, <js>"bar"</js>))
         *              .run();
         * </p>
         *
@@ -2331,7 +2234,7 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
         * @return This object (for method chaining).
         * @throws RestCallException Invalid input.
         */
-       public RestRequest formData(Object...params) throws RestCallException {
+       public RestRequest formDatas(Object...params) throws RestCallException {
                return formData(DEFAULT_FLAGS, params);
        }
 
@@ -2342,7 +2245,7 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
         * <p class='bcode w800'>
         *      client
         *              .formPost(<jsf>URL</jsf>)
-        *              
.formData(EnumSet.<jsm>of</jsm>(<jsf>REPLACE</jsf>,<jsf>SKIP_IF_EMPTY</jsf>), 
<jk>new</jk> BasicNameValuePair(<js>"foo"</js>, <js>"bar"</js>))
+        *              
.formData(EnumSet.<jsm>of</jsm>(<jsf>REPLACE</jsf>,<jsf>SKIP_IF_EMPTY</jsf>), 
BasicNameValuePair.<jsm>of</jsm>(<js>"foo"</js>, <js>"bar"</js>))
         *              .run();
         * </p>
         *
@@ -2421,7 +2324,7 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
                if (pairs.length % 2 != 0)
                        throw new RestCallException("Odd number of parameters 
passed into formData(Object...)");
                for (int i = 0; i < pairs.length; i+=2)
-                       formData(new 
SerializedNameValuePair(stringify(pairs[i]), pairs[i+1], FORMDATA, 
partSerializer, null, false));
+                       formDatas(new 
SerializedNameValuePair(stringify(pairs[i]), pairs[i+1], FORMDATA, 
partSerializer, null, false));
                return this;
        }
 
@@ -2772,36 +2675,6 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
        /**
         * Appends a header on the request.
         *
-        * <p>
-        * Unlike {@link #header(String,Object)} which converts the value to a 
string using the part serializer, this
-        * method converts the value to a string using {@link 
Object#toString()}.
-        *
-        * <h5 class='section'>Example:</h5>
-        * <p class='bcode w800'>
-        *      client
-        *              .get(<jsf>URL</jsf>)
-        *              .headerString(<js>"Foo"</js>, <js>"bar"</js>)
-        *              .run();
-        * </p>
-        *
-        * @param name The header name.
-        * @param value The header value.
-        *      <ul>
-        *              <li>Can be any POJO.
-        *              <li>Converted to a string using {@link 
Object#toString()}.
-        *              <li>Values are converted to strings at runtime to allow 
them to be modified externally.
-        *      </ul>
-        * @return This object (for method chaining).
-        * @throws RestCallException Invalid input.
-        */
-       @FluentSetter
-       public RestRequest headerString(String name, Object value) throws 
RestCallException {
-               return header(BasicStringHeader.of(name, value));
-       }
-
-       /**
-        * Appends a header on the request.
-        *
         * <h5 class='section'>Example:</h5>
         * <p class='bcode w800'>
         *      client
@@ -3050,21 +2923,34 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
         * <p class='bcode w800'>
         *      client
         *              .get(<jsf>URL</jsf>)
-        *              .header(<jk>new</jk> BasicHeader(<js>"Foo"</js>, 
<js>"bar"</js>))
+        *              .header(BasicHeader.<jsm>of</jsm>(<js>"Foo"</js>, 
<js>"bar"</js>))
+        *              .run();
+        * </p>
+        *
+        * @param header The header to set.
+        * @return This object (for method chaining).
+        * @throws RestCallException Invalid input.
+        */
+       public RestRequest header(Header header) throws RestCallException {
+               return header(DEFAULT_FLAGS, header);
+       }
+
+       /**
+        * Appends a header on the request.
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bcode w800'>
+        *      client
+        *              .get(<jsf>URL</jsf>)
+        *              
.header(BasicNameValuePair.<jsm>of</jsm>(BasicHeader.<jsm>of</jsm>(<js>"Foo"</js>,
 <js>"bar"</js>)))
         *              .run();
         * </p>
         *
         * @param header The header to set.
-        *      <br>Can be any of the following types:
-        *      <ul>
-        *              <li>{@link Header} (including any subclasses such as 
{@link Accept})
-        *              <li>{@link NameValuePair}
-        *              <li><jk>null</jk> - Will be a no-op.
-        *      </ul>
         * @return This object (for method chaining).
         * @throws RestCallException Invalid input.
         */
-       public RestRequest header(Object header) throws RestCallException {
+       public RestRequest header(NameValuePair header) throws 
RestCallException {
                return header(DEFAULT_FLAGS, header);
        }
 
@@ -3075,7 +2961,7 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
         * <p class='bcode w800'>
         *      client
         *              .get(<jsf>URL</jsf>)
-        *              
.header(EnumSet.<jsm>of</jsm>(<jsf>REPLACE</jsf>,<jsf>SKIP_IF_EMPTY</jsf>),<jk>new</jk>
 BasicHeader(<js>"Foo"</js>, <js>"bar"</js>))
+        *              
.header(EnumSet.<jsm>of</jsm>(<jsf>REPLACE</jsf>,<jsf>SKIP_IF_EMPTY</jsf>),BasicHeader.<jsm>of</jsm>(<js>"Foo"</js>,
 <js>"bar"</js>))
         *              .run();
         * </p>
         *
@@ -3112,7 +2998,7 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
         * <p class='bcode w800'>
         *      client
         *              .get(<jsf>URL</jsf>)
-        *              .headers(<jk>new</jk> BasicHeader(<js>"Foo"</js>, 
<js>"bar"</js>))
+        *              .headers(BasicHeader.<jsm>of</jsm>(<js>"Foo"</js>, 
<js>"bar"</js>))
         *              .run();
         * </p>
         *
@@ -3147,7 +3033,7 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
         * <p class='bcode w800'>
         *      client
         *              .get(<jsf>URL</jsf>)
-        *              
.headers(EnumSet.<jsm>of</jsm>(<jsf>REPLACE</jsf>,<jsf>SKIP_IF_EMPTY</jsf>),<jk>new</jk>
 BasicHeader(<js>"Foo"</js>, <js>"bar"</js>))
+        *              
.headers(EnumSet.<jsm>of</jsm>(<jsf>REPLACE</jsf>,<jsf>SKIP_IF_EMPTY</jsf>),BasicHeader.<jsm>of</jsm>(<js>"Foo"</js>,
 <js>"bar"</js>))
         *              .run();
         * </p>
         *
@@ -4199,7 +4085,7 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
         * The header will be appended to the end of the list.
         *
         * <ul class='notes'>
-        *      <li>{@link #header(Object)} is an equivalent method and the 
preferred method for fluent-style coding.
+        *      <li>{@link #header(Header)} is an equivalent method and the 
preferred method for fluent-style coding.
         * </ul>
         *
         * @param header The header to append.
diff --git 
a/juneau-rest/juneau-rest-mock/src/main/java/org/apache/juneau/rest/mock2/MockRestClientBuilder.java
 
b/juneau-rest/juneau-rest-mock/src/main/java/org/apache/juneau/rest/mock2/MockRestClientBuilder.java
index 72cbead..0c164a5 100644
--- 
a/juneau-rest/juneau-rest-mock/src/main/java/org/apache/juneau/rest/mock2/MockRestClientBuilder.java
+++ 
b/juneau-rest/juneau-rest-mock/src/main/java/org/apache/juneau/rest/mock2/MockRestClientBuilder.java
@@ -21,6 +21,7 @@ import java.util.logging.*;
 
 import static org.apache.juneau.rest.util.RestUtils.*;
 
+import java.io.*;
 import java.lang.annotation.*;
 import java.lang.reflect.Method;
 
@@ -699,6 +700,18 @@ public class MockRestClientBuilder extends 
RestClientBuilder {
        }
 
        @Override /* GENERATED - RestClientBuilder */
+       public MockRestClientBuilder console(PrintStream value) {
+               super.console(value);
+               return this;
+       }
+
+       @Override /* GENERATED - RestClientBuilder */
+       public MockRestClientBuilder console(Class<? extends 
java.io.PrintStream> value) {
+               super.console(value);
+               return this;
+       }
+
+       @Override /* GENERATED - RestClientBuilder */
        public MockRestClientBuilder 
contentDecoderRegistry(Map<String,InputStreamFactory> contentDecoderMap) {
                super.contentDecoderRegistry(contentDecoderMap);
                return this;
@@ -855,8 +868,8 @@ public class MockRestClientBuilder extends 
RestClientBuilder {
        }
 
        @Override /* GENERATED - RestClientBuilder */
-       public MockRestClientBuilder formData(Object...params) {
-               super.formData(params);
+       public MockRestClientBuilder formData(NameValuePair pair) {
+               super.formData(pair);
                return this;
        }
 
@@ -903,8 +916,8 @@ public class MockRestClientBuilder extends 
RestClientBuilder {
        }
 
        @Override /* GENERATED - RestClientBuilder */
-       public MockRestClientBuilder formDataString(String name, Object value) {
-               super.formDataString(name, value);
+       public MockRestClientBuilder formDatas(Object...params) {
+               super.formDatas(params);
                return this;
        }
 
@@ -921,7 +934,13 @@ public class MockRestClientBuilder extends 
RestClientBuilder {
        }
 
        @Override /* GENERATED - RestClientBuilder */
-       public MockRestClientBuilder header(Object header) {
+       public MockRestClientBuilder header(Header header) {
+               super.header(header);
+               return this;
+       }
+
+       @Override /* GENERATED - RestClientBuilder */
+       public MockRestClientBuilder header(NameValuePair header) {
                super.header(header);
                return this;
        }
@@ -969,12 +988,6 @@ public class MockRestClientBuilder extends 
RestClientBuilder {
        }
 
        @Override /* GENERATED - RestClientBuilder */
-       public MockRestClientBuilder headerString(String name, Object value) {
-               super.headerString(name, value);
-               return this;
-       }
-
-       @Override /* GENERATED - RestClientBuilder */
        public MockRestClientBuilder headers(Object...headers) {
                super.headers(headers);
                return this;
@@ -1318,8 +1331,14 @@ public class MockRestClientBuilder extends 
RestClientBuilder {
        }
 
        @Override /* GENERATED - RestClientBuilder */
-       public MockRestClientBuilder query(Object...params) {
-               super.query(params);
+       public MockRestClientBuilder queries(Object...params) {
+               super.queries(params);
+               return this;
+       }
+
+       @Override /* GENERATED - RestClientBuilder */
+       public MockRestClientBuilder query(NameValuePair pair) {
+               super.query(pair);
                return this;
        }
 
@@ -1366,12 +1385,6 @@ public class MockRestClientBuilder extends 
RestClientBuilder {
        }
 
        @Override /* GENERATED - RestClientBuilder */
-       public MockRestClientBuilder queryString(String name, Object value) {
-               super.queryString(name, value);
-               return this;
-       }
-
-       @Override /* GENERATED - RestClientBuilder */
        public MockRestClientBuilder quoteChar(char value) {
                super.quoteChar(value);
                return this;

Reply via email to