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 c44d2fb JUNEAU-232 c44d2fb is described below commit c44d2fb36d77d8ee76ed11fd45b2d72ae0b99e67 Author: JamesBognar <james.bog...@salesforce.com> AuthorDate: Sat May 23 10:44:32 2020 -0400 JUNEAU-232 BEAN_isIgnoreUnknownNullBeanProperties doesn't always work correctly. --- .../org/apache/juneau/jena/RdfParserSession.java | 4 +- .../main/java/org/apache/juneau/BeanContext.java | 3 +- .../java/org/apache/juneau/BeanContextBuilder.java | 3 +- .../org/apache/juneau/html/HtmlParserSession.java | 3 +- .../org/apache/juneau/json/JsonParserSession.java | 3 +- .../juneau/msgpack/MsgPackParserSession.java | 2 +- .../org/apache/juneau/parser/ParserSession.java | 10 +- .../org/apache/juneau/uon/UonParserSession.java | 5 +- .../urlencoding/UrlEncodingParserSession.java | 5 +- .../org/apache/juneau/xml/XmlParserSession.java | 17 +- .../juneau/rest/test/client/RestClientTest.java | 50 ++++- .../apache/juneau/rest/client2/RestClientTest.java | 249 +++++++++++++++------ .../org/apache/juneau/rest/client2/RestClient.java | 2 +- .../apache/juneau/rest/client2/RestRequest.java | 2 +- .../apache/juneau/rest/client2/RestResponse.java | 15 ++ .../juneau/rest/client2/RestResponseBody.java | 58 ++--- 16 files changed, 290 insertions(+), 141 deletions(-) diff --git a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfParserSession.java b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfParserSession.java index 65c58fb..b71c6b5 100644 --- a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfParserSession.java +++ b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfParserSession.java @@ -202,7 +202,9 @@ public class RdfParserSession extends ReaderParserSession { } } } else if (! (p.equals(pRoot) || p.equals(pType))) { - onUnknownProperty(key, m); + RDFNode o = st.getObject(); + Object value = parseAnything(object(), o, m.getBean(false), null); + onUnknownProperty(key, m, value); } setCurrentProperty(null); } diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java index 5375f66..15db6b3 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java @@ -1567,8 +1567,7 @@ public class BeanContext extends Context implements MetaProvider { * <h5 class='section'>Description:</h5> * * <p> - * When enabled, methods and fields marked as <jk>transient</jk> or annotated with {@link java.beans.Transient} - * will be ignored as bean properties. + * When enabled, methods and fields marked as <jk>transient</jk> will be ignored as bean properties. * * <h5 class='section'>Example:</h5> * <p class='bcode w800'> diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContextBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContextBuilder.java index f33cd5e..51d946f 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContextBuilder.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContextBuilder.java @@ -2292,8 +2292,7 @@ public class BeanContextBuilder extends ContextBuilder { * <i><l>BeanContext</l> configuration property:</i> Ignore transient fields. * * <p> - * When enabled, methods and fields marked as <jk>transient</jk> or annotated with {@link java.beans.Transient} - * will be ignored as bean properties. + * When enabled, methods and fields marked as <jk>transient</jk> will be ignored as bean properties. * * <h5 class='section'>Example:</h5> * <p class='bcode w800'> diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlParserSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlParserSession.java index b549fc4..bdd0e7f 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlParserSession.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlParserSession.java @@ -515,8 +515,7 @@ public final class HtmlParserSession extends XmlParserSession { nextTag(r, TD); BeanPropertyMeta pMeta = m.getPropertyMeta(key); if (pMeta == null) { - onUnknownProperty(key, m); - parseAnything(object(), r, null, false, null); + onUnknownProperty(key, m, parseAnything(object(), r, null, false, null)); } else { ClassMeta<?> cm = pMeta.getClassMeta(); Object value = parseAnything(cm, r, m.getBean(false), false, pMeta); diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParserSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParserSession.java index 3b056b2..d4d85d9 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParserSession.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParserSession.java @@ -513,9 +513,8 @@ public final class JsonParserSession extends ReaderParserSession { BeanPropertyMeta pMeta = m.getPropertyMeta(currAttr); setCurrentProperty(pMeta); if (pMeta == null) { - onUnknownProperty(currAttr, m); + onUnknownProperty(currAttr, m, parseAnything(object(), r.unread(), m.getBean(false), null)); unmark(); - parseAnything(object(), r.unread(), m.getBean(false), null); // Read content anyway to ignore it } else { unmark(); ClassMeta<?> cm = pMeta.getClassMeta(); diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParserSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParserSession.java index 7ae1e7c..c9c619b 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParserSession.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParserSession.java @@ -133,7 +133,7 @@ public final class MsgPackParserSession extends InputStreamParserSession { if (pName.equals(getBeanTypePropertyName(eType))) parseAnything(string(), is, null, null); else - onUnknownProperty(pName, m); + onUnknownProperty(pName, m, parseAnything(string(), is, null, null)); } else { ClassMeta<?> cm = bpm.getClassMeta(); Object value = parseAnything(cm, is, m.getBean(false), bpm); diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserSession.java index b2f588e..9e64b19 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserSession.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserSession.java @@ -316,18 +316,20 @@ public abstract class ParserSession extends BeanSession { * * @param propertyName The unknown bean property name. * @param beanMap The bean that doesn't have the expected property. + * @param value The parsed value. * @throws ParseException * Automatically thrown if {@link BeanContext#BEAN_ignoreUnknownBeanProperties} setting on this parser is * <jk>false</jk> * @param <T> The class type of the bean map that doesn't have the expected property. */ - protected final <T> void onUnknownProperty(String propertyName, BeanMap<T> beanMap) throws ParseException { + protected final <T> void onUnknownProperty(String propertyName, BeanMap<T> beanMap, Object value) throws ParseException { if (propertyName.equals(getBeanTypePropertyName(beanMap.getClassMeta()))) return; if (! isIgnoreUnknownBeanProperties()) - throw new ParseException(this, - "Unknown property ''{0}'' encountered while trying to parse into class ''{1}''", propertyName, - beanMap.getClassMeta()); + if (value != null || ! isIgnoreUnknownNullBeanProperties()) + throw new ParseException(this, + "Unknown property ''{0}'' encountered while trying to parse into class ''{1}''", propertyName, + beanMap.getClassMeta()); if (listener != null) listener.onUnknownBeanProperty(this, propertyName, beanMap.getClassMeta().getInnerClass(), beanMap.getBean()); } diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserSession.java index dbfc4de..f432e31 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserSession.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserSession.java @@ -539,7 +539,7 @@ public class UonParserSession extends ReaderParserSession implements HttpPartPar if (! currAttr.equals(getBeanTypePropertyName(m.getClassMeta()))) { BeanPropertyMeta pMeta = m.getPropertyMeta(currAttr); if (pMeta == null) { - onUnknownProperty(currAttr, m); + onUnknownProperty(currAttr, m, null); unmark(); } else { unmark(); @@ -559,9 +559,8 @@ public class UonParserSession extends ReaderParserSession implements HttpPartPar if (! currAttr.equals(getBeanTypePropertyName(m.getClassMeta()))) { BeanPropertyMeta pMeta = m.getPropertyMeta(currAttr); if (pMeta == null) { - onUnknownProperty(currAttr, m); + onUnknownProperty(currAttr, m, parseAnything(object(), r.unread(), m.getBean(false), false, null)); unmark(); - parseAnything(object(), r.unread(), m.getBean(false), false, null); // Read content anyway to ignore it } else { unmark(); setCurrentProperty(pMeta); diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserSession.java index eb3b487..72ed9c9 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserSession.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserSession.java @@ -289,7 +289,7 @@ public class UrlEncodingParserSession extends UonParserSession { if (! currAttr.equals(getBeanTypePropertyName(m.getClassMeta()))) { BeanPropertyMeta pMeta = m.getPropertyMeta(currAttr); if (pMeta == null) { - onUnknownProperty(currAttr, m); + onUnknownProperty(currAttr, m, null); unmark(); } else { unmark(); @@ -315,9 +315,8 @@ public class UrlEncodingParserSession extends UonParserSession { if (! currAttr.equals(getBeanTypePropertyName(m.getClassMeta()))) { BeanPropertyMeta pMeta = m.getPropertyMeta(currAttr); if (pMeta == null) { - onUnknownProperty(currAttr, m); + onUnknownProperty(currAttr, m, parseAnything(object(), r.unread(), m.getBean(false), true, null)); unmark(); - parseAnything(object(), r.unread(), m.getBean(false), true, null); // Read content anyway to ignore it } else { unmark(); setCurrentProperty(pMeta); diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParserSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParserSession.java index c4fce6b..3a623c1 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParserSession.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParserSession.java @@ -495,7 +495,7 @@ public class XmlParserSession extends ReaderParserSession { if (xmlMeta.getAttrsProperty() != null) { xmlMeta.getAttrsProperty().add(m, key, key, val); } else if (ns == null) { - onUnknownProperty(key, m); + onUnknownProperty(key, m, val); } } else { try { @@ -581,8 +581,8 @@ public class XmlParserSession extends ReaderParserSession { currAttr = getElementName(r); BeanPropertyMeta pMeta = xmlMeta.getPropertyMeta(currAttr); if (pMeta == null) { - onUnknownProperty(currAttr, m); - skipCurrentTag(r); + Object value = parseAnything(object(), currAttr, r, m.getBean(false), false, null); + onUnknownProperty(currAttr, m, value); } else { setCurrentProperty(pMeta); XmlFormat xf = getXmlBeanPropertyMeta(pMeta).getXmlFormat(); @@ -637,17 +637,6 @@ public class XmlParserSession extends ReaderParserSession { return m; } - private static void skipCurrentTag(XmlReader r) throws XMLStreamException { - int depth = 1; - do { - int event = r.next(); - if (event == START_ELEMENT) - depth++; - else if (event == END_ELEMENT) - depth--; - } while (depth > 0); - } - private boolean isSpecialAttr(String key) { return key.equals(getBeanTypePropertyName(null)) || key.equals(getNamePropertyName()); } diff --git a/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/client/RestClientTest.java b/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/client/RestClientTest.java index 17779fe..1e8cdbe 100644 --- a/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/client/RestClientTest.java +++ b/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/client/RestClientTest.java @@ -36,12 +36,20 @@ public class RestClientTest extends RestTestcase { Mutable<Integer> rc = new Mutable<>(); Mutable<String> r = new Mutable<>(); - c.post(URL, new StringEntity("xxxSUCCESSxxx")).run().getStatusCode(rc).getBody().cache().assertContains("SUCCESS").getBody().asString(r); + c.post(URL, new StringEntity("xxxSUCCESSxxx")) + .run() + .getStatusCode(rc) + .cacheBody() + .getBody().assertContains("SUCCESS") + .getBody().asString(r); assertEquals("xxxSUCCESSxxx", r.get()); assertEquals(200, rc.get().intValue()); try { - c.post(URL, new StringEntity("xxxFAILURExxx")).run().getBody().assertContains("SUCCESS"); + c.post(URL, new StringEntity("xxxFAILURExxx")) + .run() + .getBody() + .assertContains("SUCCESS"); fail(); } catch (AssertionError e) { assertTrue(e.getLocalizedMessage().contains("Response did not have the expected substring for body.")); @@ -57,12 +65,20 @@ public class RestClientTest extends RestTestcase { Mutable<Integer> rc = new Mutable<>(); Mutable<String> r = new Mutable<>(); - c.post(URL, new StringEntity("xxxSUCCESSxxx")).run().getStatusCode(rc).getBody().cache().assertValue(x -> ! x.contains("FAILURE")).getBody().asString(r); + c.post(URL, new StringEntity("xxxSUCCESSxxx")) + .run() + .getStatusCode(rc) + .cacheBody() + .getBody().assertValue(x -> ! x.contains("FAILURE")) + .getBody().asString(r); assertEquals("xxxSUCCESSxxx", r.get()); assertEquals(200, rc.get().intValue()); try { - c.post(URL, new StringEntity("xxxFAILURExxx")).run().getBody().assertValue(x -> ! x.contains("FAILURE")); + c.post(URL, new StringEntity("xxxFAILURExxx")) + .run() + .getBody() + .assertValue(x -> ! x.contains("FAILURE")); fail(); } catch (AssertionError e) { assertTrue(e.getLocalizedMessage().contains("Response did not have the expected value for body.")); @@ -75,7 +91,11 @@ public class RestClientTest extends RestTestcase { @Test public void testCaptureResponse() throws Exception { RestClient c = TestMicroservice.DEFAULT_CLIENT; - RestResponse r = c.post(URL, new StringEntity("xxx")).run().getBody().cache().toResponse(); + RestResponse r = c + .post(URL, new StringEntity("xxx")) + .run() + .cacheBody() + .getBody().toResponse(); assertEquals("xxx", r.getBody().asString()); assertEquals("xxx", r.getBody().asString()); @@ -87,7 +107,7 @@ public class RestClientTest extends RestTestcase { r.getBody().asString(); fail(); } catch (IllegalStateException e) { - assertEquals("Method cannot be called. Response has already been consumed.", e.getLocalizedMessage()); + assertEquals("Method cannot be called. Response has already been consumed. Consider using the RestResponse.cacheBody() method.", e.getLocalizedMessage()); } } @@ -100,12 +120,20 @@ public class RestClientTest extends RestTestcase { String r; Mutable<Matcher> m = Mutable.create(); - r = c.post(URL, new StringEntity("x=1,y=2")).run().getBody().cache().asMatcher(m, "x=(\\d+),y=(\\S+)").getBody().asString(); + r = c.post(URL, new StringEntity("x=1,y=2")) + .run() + .cacheBody() + .getBody().asMatcher(m, "x=(\\d+),y=(\\S+)") + .getBody().asString(); assertEquals("x=1,y=2", r); assertTrue(m.get().matches()); assertObjectEquals("['x=1,y=2','1','2']", m.get().toMatchResult()); - r = c.post(URL, new StringEntity("x=1,y=2\nx=3,y=4")).run().getBody().cache().asMatcher(m, "x=(\\d+),y=(\\S+)").getBody().asString(); + r = c.post(URL, new StringEntity("x=1,y=2\nx=3,y=4")) + .run() + .cacheBody() + .getBody().asMatcher(m, "x=(\\d+),y=(\\S+)") + .getBody().asString(); assertEquals("x=1,y=2\nx=3,y=4", r); assertTrue(m.get().find()); assertObjectEquals("['x=1,y=2','1','2']", m.get().toMatchResult()); @@ -116,7 +144,11 @@ public class RestClientTest extends RestTestcase { assertFalse(m.get().find()); Mutable<Matcher> m2 = Mutable.create(); - c.post(URL, new StringEntity("x=1,y=2")).run().getBody().cache().asMatcher(m, "x=(\\d+),y=(\\S+)").getBody().asMatcher(m2, "x=(\\d+),y=(\\S+)"); + c.post(URL, new StringEntity("x=1,y=2")) + .run() + .cacheBody() + .getBody().asMatcher(m, "x=(\\d+),y=(\\S+)") + .getBody().asMatcher(m2, "x=(\\d+),y=(\\S+)"); assertTrue(m.get().matches()); assertTrue(m2.get().matches()); assertObjectEquals("['x=1,y=2','1','2']", m.get().toMatchResult()); 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 b724e11..1f15acb 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 @@ -30,6 +30,7 @@ import org.apache.http.client.methods.*; import org.apache.http.impl.client.*; import org.apache.http.protocol.*; import org.apache.juneau.*; +import org.apache.juneau.Visibility; import org.apache.juneau.annotation.*; import org.apache.juneau.collections.*; import org.apache.juneau.http.*; @@ -1834,8 +1835,8 @@ public class RestClientTest { Bean b = rc .post("/echoBody", bean) .run() - .getBody().cache() - .assertValue("<object><f>1</f></object>") + .cacheBody() + .getBody().assertValue("<object><f>1</f></object>") .getBody().as(Bean.class); assertEqualObjects(b, bean); @@ -1851,15 +1852,15 @@ public class RestClientTest { rc .post("/echoBody", bean) .run() - .getBody().cache().assertValue("{f:1}"); + .getBody().assertValue("{f:1}"); Bean b = rc .post("/echoBody", bean) .accept("text/xml") .contentType("text/xml") .run() - .getBody().cache() - .assertValue("<object><f>1</f></object>") + .cacheBody() + .getBody().assertValue("<object><f>1</f></object>") .getBody().as(Bean.class); assertEqualObjects(b, bean); @@ -1868,7 +1869,8 @@ public class RestClientTest { .accept("text/json") .contentType("text/json") .run() - .getBody().cache().assertValue("{\"f\":1}") + .cacheBody() + .getBody().assertValue("{\"f\":1}") .getBody().as(Bean.class); assertEqualObjects(b, bean); } @@ -1884,7 +1886,8 @@ public class RestClientTest { Bean b = rc .post("/echoBody", bean) .run() - .getBody().cache().assertValue("<object><f>1</f></object>") + .cacheBody() + .getBody().assertValue("<object><f>1</f></object>") .getBody().as(Bean.class); assertEqualObjects(b, bean); @@ -1901,7 +1904,8 @@ public class RestClientTest { Bean b = rc .post("/echoBody", bean) .run() - .getBody().cache().assertValue("<object><f>1</f></object>") + .cacheBody() + .getBody().assertValue("<object><f>1</f></object>") .getBody().as(Bean.class); assertEqualObjects(b, bean); @@ -1919,14 +1923,15 @@ public class RestClientTest { rc .post("/echoBody", bean) .run() - .getBody().cache().assertValue("{f:1}"); + .getBody().assertValue("{f:1}"); Bean b = rc .post("/echoBody", bean) .accept("text/xml") .contentType("text/xml") .run() - .getBody().cache().assertValue("<object><f>1</f></object>") + .cacheBody() + .getBody().assertValue("<object><f>1</f></object>") .getBody().as(Bean.class); assertEqualObjects(b, bean); @@ -1935,7 +1940,8 @@ public class RestClientTest { .accept("text/json") .contentType("text/json") .run() - .getBody().cache().assertValue("{\"f\":1}") + .cacheBody() + .getBody().assertValue("{\"f\":1}") .getBody().as(Bean.class); assertEqualObjects(b, bean); } @@ -1951,14 +1957,15 @@ public class RestClientTest { rc .post("/echoBody", bean) .run() - .getBody().cache().assertValue("{f:1}"); + .getBody().assertValue("{f:1}"); Bean b = rc .post("/echoBody", bean) .accept("text/xml") .contentType("text/xml") .run() - .getBody().cache().assertValue("<object><f>1</f></object>") + .cacheBody() + .getBody().assertValue("<object><f>1</f></object>") .getBody().as(Bean.class); assertEqualObjects(b, bean); @@ -1967,7 +1974,8 @@ public class RestClientTest { .accept("text/json") .contentType("text/json") .run() - .getBody().cache().assertValue("{\"f\":1}") + .cacheBody() + .getBody().assertValue("{\"f\":1}") .getBody().as(Bean.class); assertEqualObjects(b, bean); } @@ -2117,7 +2125,7 @@ public class RestClientTest { .post("/echoBody", l1) .run(); } catch (RestCallException e) { - assertTrue(e.getCause().getCause().getMessage().startsWith("Recursion occurred")); + assertTrue(e.getCause(SerializeException.class).getMessage().startsWith("Recursion occurred")); } } @@ -2620,7 +2628,8 @@ public class RestClientTest { .post("/test", new O2(1)) .header("X", new O2(1)) .run() - .getBody().cache().assertValue("1") + .cacheBody() + .getBody().assertValue("1") .getHeader("X").assertValue("1") ; assertEquals(1, rr.getBody().as(O2.class).f); @@ -2654,7 +2663,8 @@ public class RestClientTest { .post("/test", new O9().init()) .header("X", new O9().init()) .run() - .getBody().cache().assertValue("{f1:1,f2:2}") + .cacheBody() + .getBody().assertValue("{f1:1,f2:2}") .getHeader("X").assertValue("f1=1,f2=2") ; assertEquals(2, rr.getBody().as(O9.class).f2); @@ -2703,7 +2713,8 @@ public class RestClientTest { .post("/test", new O10().init()) .header("X", new O10().init()) .run() - .getBody().cache().assertValue("{f1:1}") + .cacheBody() + .getBody().assertValue("{f1:1}") .getHeader("X").assertValue("f1=1") ; assertEquals(0, rr.getBody().as(O10.class).f2); @@ -2717,7 +2728,8 @@ public class RestClientTest { .post("/test", new O10().init()) .header("X", new O10().init()) .run() - .getBody().cache().assertValue("{f1:1}") + .cacheBody() + .getBody().assertValue("{f1:1}") .getHeader("X").assertValue("f1=1") ; assertEquals(0, rr.getBody().as(O10.class).f2); @@ -2731,7 +2743,8 @@ public class RestClientTest { .post("/test", new O10().init()) .header("X", new O10().init()) .run() - .getBody().cache().assertValue("{f1:1}") + .cacheBody() + .getBody().assertValue("{f1:1}") .getHeader("X").assertValue("f1=1") ; assertEquals(0, rr.getBody().as(O10.class).f2); @@ -2745,13 +2758,13 @@ public class RestClientTest { .post("/test", new O10().init()) .header("X", new O10().init()) .run() - .getBody().cache().assertValue("{f1:1}") + .cacheBody() + .getBody().assertValue("{f1:1}") .getHeader("X").assertValue("f1=1") ; assertEquals(0, rr.getBody().as(O10.class).f2); assertEquals(0, rr.getHeader("X").as(O10.class).f2); - rr = MockRestClient .create(O2R.class) .interfaces(O10I.class) @@ -2760,7 +2773,8 @@ public class RestClientTest { .post("/test", new O10().init()) .header("X", new O10().init()) .run() - .getBody().cache().assertValue("{f3:3}") + .cacheBody() + .getBody().assertValue("{f3:3}") .getHeader("X").assertValue("f3=3") ; assertEquals(3, rr.getBody().as(O10.class).f3); @@ -2805,7 +2819,8 @@ public class RestClientTest { .post("/test", new O18().init()) .header("X", new O18().init()) .run() - .getBody().cache().assertValue("{f1:1,f2:2}") + .cacheBody() + .getBody().assertValue("{f1:1,f2:2}") .getHeader("X").assertValue("f1=1,f2=2") ; assertEquals(2, rr.getBody().as(O18.class).f2); @@ -2834,7 +2849,7 @@ public class RestClientTest { .post("/test", new O21("1")) .header("X", new O21("1")) .run() - .getBody().cache().assertValue("{f1:'1'}") + .getBody().assertValue("{f1:'1'}") .getHeader("X").assertValue("f1=1") ; MockRestClient @@ -2845,7 +2860,7 @@ public class RestClientTest { .post("/test", new O21("1")) .header("X", new O21("1")) .run() - .getBody().cache().assertValue("'1'") + .getBody().assertValue("'1'") .getHeader("X").assertValue("1") ; } @@ -2859,7 +2874,7 @@ public class RestClientTest { .post("/test", new O21("1")) .header("X", new O21("1")) .run() - .getBody().cache().assertValue("{f1:'1'}") + .getBody().assertValue("{f1:'1'}") .getHeader("X").assertValue("f1=1") ; MockRestClient @@ -2870,7 +2885,7 @@ public class RestClientTest { .post("/test", new O21("1")) .header("X", new O21("1")) .run() - .getBody().cache().assertValue("'1'") + .getBody().assertValue("'1'") .getHeader("X").assertValue("1") ; } @@ -2909,7 +2924,7 @@ public class RestClientTest { .post("/test", new O25().init()) .header("X", new O25().init()) .run() - .getBody().cache().assertValue("{f1:1,f2:2}") + .getBody().assertValue("{f1:1,f2:2}") .getHeader("X").assertValue("f1=1,f2=2") ; MockRestClient @@ -2920,7 +2935,7 @@ public class RestClientTest { .post("/test", new O25().init()) .header("X", new O25().init()) .run() - .getBody().cache().assertValue("{f1:1}") + .getBody().assertValue("{f1:1}") .getHeader("X").assertValue("f1=1") ; } @@ -2935,7 +2950,7 @@ public class RestClientTest { .post("/test", new O25().init()) .header("X", new O25().init()) .run() - .getBody().cache().assertValue("{f2:2}") + .getBody().assertValue("{f2:2}") .getHeader("X").assertValue("f2=2") ; MockRestClient @@ -2946,7 +2961,7 @@ public class RestClientTest { .post("/test", new O25().init()) .header("X", new O25().init()) .run() - .getBody().cache().assertValue("{f2:2}") + .getBody().assertValue("{f2:2}") .getHeader("X").assertValue("f2=2") ; MockRestClient @@ -2957,7 +2972,7 @@ public class RestClientTest { .post("/test", new O25().init()) .header("X", new O25().init()) .run() - .getBody().cache().assertValue("{f2:2}") + .getBody().assertValue("{f2:2}") .getHeader("X").assertValue("f2=2") ; MockRestClient @@ -2968,7 +2983,7 @@ public class RestClientTest { .post("/test", new O25().init()) .header("X", new O25().init()) .run() - .getBody().cache().assertValue("{f2:2}") + .getBody().assertValue("{f2:2}") .getHeader("X").assertValue("f2=2") ; } @@ -2985,7 +3000,8 @@ public class RestClientTest { .post("/test", new O25().init()) .header("X", new O25().init()) .run() - .getBody().cache().assertValue("{f1:1,f2:2}") + .cacheBody() + .getBody().assertValue("{f1:1,f2:2}") .getHeader("X").assertValue("f1=1,f2=2") ; assertEquals("1/0", rr.getBody().as(O25.class).toString()); @@ -2999,7 +3015,8 @@ public class RestClientTest { .post("/test", new O25().init()) .header("X", new O25().init()) .run() - .getBody().cache().assertValue("{f1:1,f2:2}") + .cacheBody() + .getBody().assertValue("{f1:1,f2:2}") .getHeader("X").assertValue("f1=1,f2=2") ; assertEquals("1/0", rr.getBody().as(O25.class).toString()); @@ -3013,7 +3030,8 @@ public class RestClientTest { .post("/test", new O25().init()) .header("X", new O25().init()) .run() - .getBody().cache().assertValue("{f1:1,f2:2}") + .cacheBody() + .getBody().assertValue("{f1:1,f2:2}") .getHeader("X").assertValue("f1=1,f2=2") ; assertEquals("1/0", rr.getBody().as(O25.class).toString()); @@ -3032,7 +3050,8 @@ public class RestClientTest { .post("/test", new O25().init()) .header("X", new O25().init()) .run() - .getBody().cache().assertValue("{f1:1}") + .cacheBody() + .getBody().assertValue("{f1:1}") .getHeader("X").assertValue("f1=1") ; assertEquals("1/0", rr.getBody().as(O25.class).toString()); @@ -3046,7 +3065,8 @@ public class RestClientTest { .post("/test", new O25().init()) .header("X", new O25().init()) .run() - .getBody().cache().assertValue("{f1:1}") + .cacheBody() + .getBody().assertValue("{f1:1}") .getHeader("X").assertValue("f1=1") ; assertEquals("1/0", rr.getBody().as(O25.class).toString()); @@ -3060,7 +3080,8 @@ public class RestClientTest { .post("/test", new O25().init()) .header("X", new O25().init()) .run() - .getBody().cache().assertValue("{f1:1}") + .cacheBody() + .getBody().assertValue("{f1:1}") .getHeader("X").assertValue("f1=1") ; assertEquals("1/0", rr.getBody().as(O25.class).toString()); @@ -3077,7 +3098,7 @@ public class RestClientTest { .post("/test", new O25().init()) .header("X", new O25().init()) .run() - .getBody().cache().assertValue("{f2:2}") + .getBody().assertValue("{f2:2}") .getHeader("X").assertValue("f2=2") ; MockRestClient @@ -3088,7 +3109,7 @@ public class RestClientTest { .post("/test", new O25().init()) .header("X", new O25().init()) .run() - .getBody().cache().assertValue("{f2:2}") + .getBody().assertValue("{f2:2}") .getHeader("X").assertValue("f2=2") ; MockRestClient @@ -3099,7 +3120,7 @@ public class RestClientTest { .post("/test", new O25().init()) .header("X", new O25().init()) .run() - .getBody().cache().assertValue("{f2:2}") + .getBody().assertValue("{f2:2}") .getHeader("X").assertValue("f2=2") ; MockRestClient @@ -3110,7 +3131,7 @@ public class RestClientTest { .post("/test", new O25().init()) .header("X", new O25().init()) .run() - .getBody().cache().assertValue("{f2:2}") + .getBody().assertValue("{f2:2}") .getHeader("X").assertValue("f2=2") ; } @@ -3178,7 +3199,8 @@ public class RestClientTest { .build() .post("/echoBody", new O33a().init()) .run() - .getBody().cache().assertContains("{_type:'foo',foo:'1'}") + .cacheBody() + .getBody().assertContains("{_type:'foo',foo:'1'}") .getBody().as(Object.class); ; assertTrue(o instanceof O33a); @@ -3193,7 +3215,8 @@ public class RestClientTest { .build() .post("/echoBody", m) .run() - .getBody().cache().assertValue("{x:{_type:'foo',foo:'1'},y:{_type:'bar',foo:'2'}}") + .cacheBody() + .getBody().assertValue("{x:{_type:'foo',foo:'1'},y:{_type:'bar',foo:'2'}}") .getBody().as(OMap.class); ; assertTrue(m.get("x") instanceof O33a); @@ -3208,34 +3231,126 @@ public class RestClientTest { .build() .post("/echoBody", new O33c().init()) .run() - .getBody().cache().assertValue("{foo:{_type:'foo',foo:'1'}}") + .cacheBody() + .getBody().assertValue("{foo:{_type:'foo',foo:'1'}}") .getBody().as(O33c.class); ; assertTrue(o33c.foo instanceof O33a); } + public static class O34 { + private String foo; + public String getFoo() { + return foo; + } + public O34 init() { + foo = "foo"; + return this; + } + } + @Test + public void o034_beanContext_dontIgnorePropertiesWithoutSetters() throws Exception { + O34 x = MockRestClient + .create(A.class) + .simpleJson() + .build() + .post("/echoBody", new O34().init()) + .run() + .cacheBody() + .getBody().assertContains("{foo:'foo'}") + .getBody().as(O34.class); + ; + assertNull(x.foo); -// -// @Test -// public void o0_beanContext_() throws Exception { -// } -// @Override /* GENERATED - BeanContextBuilder */ -// public MockRestClient dontIgnorePropertiesWithoutSetters() { -// super.dontIgnorePropertiesWithoutSetters(); -// return this; -// } -// -// @Test -// public void o0_beanContext_() throws Exception { -// } -// @Override /* GENERATED - BeanContextBuilder */ -// public MockRestClient dontIgnoreTransientFields() { -// super.dontIgnoreTransientFields(); -// return this; -// } -// -// @Test + try { + MockRestClient + .create(A.class) + .simpleJson() + .dontIgnorePropertiesWithoutSetters() + .build() + .post("/echoBody", new O34().init()) + .run() + .cacheBody() + .getBody().assertContains("{foo:'foo'}") + .getBody().as(O34.class); + } catch (RestCallException e) { + assertTrue(e.getCause(BeanRuntimeException.class).getMessage().contains("Setter or public field not defined")); + } + } + + public static class O35 { + public String foo; + public transient String bar; + + public O35 init() { + foo = "1"; + bar = "2"; + return this; + } + } + + @Test + public void o035_beanContext_dontIgnoreTransientFields() throws Exception { + O35 x = MockRestClient + .create(A.class) + .simpleJson() + .build() + .post("/echoBody", new O35().init()) + .run() + .cacheBody() + .getBody().assertContains("{foo:'1'}") + .getBody().as(O35.class); + ; + assertNull(x.bar); + + x = MockRestClient + .create(A.class) + .simpleJson() + .dontIgnoreTransientFields() + .build() + .post("/echoBody", new O35().init()) + .run() + .cacheBody() + .getBody().assertContains("{bar:'2',foo:'1'}") + .getBody().as(O35.class); + assertEquals("2", x.bar); + } + + public static class O36 { + public String foo; + } + + @Test + public void o036_beanContext_dontIgnoreUnknownNullBeanProperties() throws Exception { + MockRestClient + .create(A.class) + .simpleJson() + .build() + .post("/echoBody", new StringReader("{foo:'1',bar:null}")) + .run() + .cacheBody() + .getBody().assertContains("{foo:'1',bar:null}") + .getBody().as(O36.class); + ; + + try { + MockRestClient + .create(A.class) + .simpleJson() + .dontIgnoreUnknownNullBeanProperties() + .build() + .post("/echoBody", new StringReader("{foo:'1',bar:null}")) + .run() + .cacheBody() + .getBody().assertContains("{foo:'1',bar:null}") + .getBody().as(O34.class); + } catch (RestCallException e) { + assertTrue(e.getCause(ParseException.class).getMessage().contains("Unknown property 'bar'")); + } + } + + // @Test // public void o0_beanContext_() throws Exception { // } // @Override /* GENERATED - BeanContextBuilder */ 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 fd264bd..fee442d 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 @@ -717,7 +717,7 @@ import org.apache.http.client.CookieStore; * </p> * * <p class='w900'> - * The response body can only be consumed once. However, the {@link RestResponseBody#cache()} method is provided + * The response body can only be consumed once. However, the {@link RestResponse#cacheBody()} and {@link RestResponseBody#cache()} methods are provided * to cache the response body in memory so that you can perform several operations against it. * * <h5 class='figure'>Examples:</h5> 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 25e7a42..c37bf77 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 @@ -2329,7 +2329,7 @@ public final class RestRequest extends BeanSession implements HttpUriRequest, Co } if (client.logRequests == DetailLevel.FULL) - response.getBody().cache(); + response.cacheBody(); for (RestCallInterceptor rci : interceptors) rci.onConnect(this, response); diff --git a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestResponse.java b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestResponse.java index 0d8444b..9a3e720 100644 --- a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestResponse.java +++ b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestResponse.java @@ -234,6 +234,21 @@ public final class RestResponse implements HttpResponse { return responseBody; } + /** + * Caches the response body so that it can be read as a stream multiple times. + * + * This is equivalent to calling the following: + * <p class='bcode w800'> + * getBody().cache(); + * </p> + * + * @return The body of the response. + */ + public RestResponse cacheBody() { + responseBody.cache(); + return this; + } + @SuppressWarnings("unchecked") <T> T as(ResponseBeanMeta rbm) throws RestCallException { try { diff --git a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestResponseBody.java b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestResponseBody.java index 62a31aa..32177e7 100644 --- a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestResponseBody.java +++ b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestResponseBody.java @@ -240,7 +240,7 @@ public class RestResponseBody implements HttpEntity { } if (isConsumed && ! entity.isRepeatable()) - throw new IllegalStateException("Method cannot be called. Response has already been consumed."); + throw new IllegalStateException("Method cannot be called. Response has already been consumed. Consider using the RestResponse.cacheBody() method."); HttpEntity e = response.asHttpResponse().getEntity(); InputStream is = e == null ? new ByteArrayInputStream(new byte[0]) : e.getContent(); @@ -523,7 +523,7 @@ public class RestResponseBody implements HttpEntity { * <li class='jc'>{@link StreamResource} - Returns access as an input stream wrapped in a stream resource. * </ul> * <li> - * If {@link #cache()} has been called, this method can be can be called multiple times and/or combined with + * If {@link #cache()} or {@link RestResponse#cacheBody()} has been called, this method can be can be called multiple times and/or combined with * other methods that retrieve the content of the response. Otherwise a {@link RestCallException} * with an inner {@link IllegalStateException} will be thrown. * <li> @@ -568,7 +568,7 @@ public class RestResponseBody implements HttpEntity { * * <ul class='notes'> * <li> - * If {@link #cache()} has been called, this method can be can be called multiple times and/or combined with + * If {@link #cache()} or {@link RestResponse#cacheBody()} has been called, this method can be can be called multiple times and/or combined with * other methods that retrieve the content of the response. Otherwise a {@link RestCallException} * with an inner {@link IllegalStateException} will be thrown. * <li> @@ -632,7 +632,7 @@ public class RestResponseBody implements HttpEntity { * <li class='jc'>{@link StreamResource} - Returns access as an input stream wrapped in a stream resource. * </ul> * <li> - * If {@link #cache()} has been called, this method can be can be called multiple times and/or combined with + * If {@link #cache()} or {@link RestResponse#cacheBody()} has been called, this method can be can be called multiple times and/or combined with * other methods that retrieve the content of the response. Otherwise a {@link RestCallException} * with an inner {@link IllegalStateException} will be thrown. * <li> @@ -670,7 +670,7 @@ public class RestResponseBody implements HttpEntity { * * <ul class='notes'> * <li> - * If {@link #cache()} has been called, this method can be can be called multiple times and/or combined with + * If {@link #cache()} or {@link RestResponse#cacheBody()} has been called, this method can be can be called multiple times and/or combined with * other methods that retrieve the content of the response. Otherwise a {@link RestCallException} * with an inner {@link IllegalStateException} will be thrown. * <li> @@ -724,7 +724,7 @@ public class RestResponseBody implements HttpEntity { * * <ul class='notes'> * <li> - * If {@link #cache()} has been called, this method can be can be called multiple times and/or combined with + * If {@link #cache()} or {@link RestResponse#cacheBody()} has been called, this method can be can be called multiple times and/or combined with * other methods that retrieve the content of the response. Otherwise a {@link RestCallException} * with an inner {@link IllegalStateException} will be thrown. * <li> @@ -849,7 +849,7 @@ public class RestResponseBody implements HttpEntity { * * <ul class='notes'> * <li> - * If {@link #cache()} has been called, this method can be can be called multiple times and/or combined with + * If {@link #cache()} or {@link RestResponse#cacheBody()} has been called, this method can be can be called multiple times and/or combined with * other methods that retrieve the content of the response. Otherwise a {@link RestCallException} * with an inner {@link IllegalStateException} will be thrown. * <li> @@ -878,7 +878,7 @@ public class RestResponseBody implements HttpEntity { * * <ul class='notes'> * <li> - * If {@link #cache()} has been called, this method can be can be called multiple times and/or combined with + * If {@link #cache()} or {@link RestResponse#cacheBody()} has been called, this method can be can be called multiple times and/or combined with * other methods that retrieve the content of the response. Otherwise a {@link RestCallException} * with an inner {@link IllegalStateException} will be thrown. * <li> @@ -909,7 +909,7 @@ public class RestResponseBody implements HttpEntity { * * <ul class='notes'> * <li> - * If {@link #cache()} has been called, this method can be can be called multiple times and/or combined with + * If {@link #cache()} or {@link RestResponse#cacheBody()} has been called, this method can be can be called multiple times and/or combined with * other methods that retrieve the content of the response. Otherwise a {@link RestCallException} * with an inner {@link IllegalStateException} will be thrown. * <li> @@ -935,7 +935,7 @@ public class RestResponseBody implements HttpEntity { * * <ul class='notes'> * <li> - * If {@link #cache()} has been called, this method can be can be called multiple times and/or combined with + * If {@link #cache()} or {@link RestResponse#cacheBody()} has been called, this method can be can be called multiple times and/or combined with * other methods that retrieve the content of the response. Otherwise a {@link RestCallException} * with an inner {@link IllegalStateException} will be thrown. * <li> @@ -968,7 +968,7 @@ public class RestResponseBody implements HttpEntity { * * <ul class='notes'> * <li> - * If {@link #cache()} has been called, this method can be can be called multiple times and/or combined with + * If {@link #cache()} or {@link RestResponse#cacheBody()} has been called, this method can be can be called multiple times and/or combined with * other methods that retrieve the content of the response. Otherwise a {@link RestCallException} * with an inner {@link IllegalStateException} will be thrown. * <li> @@ -996,7 +996,7 @@ public class RestResponseBody implements HttpEntity { * * <ul class='notes'> * <li> - * If {@link #cache()} has been called, this method can be can be called multiple times and/or combined with + * If {@link #cache()} or {@link RestResponse#cacheBody()} has been called, this method can be can be called multiple times and/or combined with * other methods that retrieve the content of the response. Otherwise a {@link RestCallException} * with an inner {@link IllegalStateException} will be thrown. * <li> @@ -1035,7 +1035,7 @@ public class RestResponseBody implements HttpEntity { * * <ul class='notes'> * <li> - * If {@link #cache()} has been called, this method can be can be called multiple times and/or combined with + * If {@link #cache()} or {@link RestResponse#cacheBody()} has been called, this method can be can be called multiple times and/or combined with * other methods that retrieve the content of the response. Otherwise a {@link RestCallException} * with an inner {@link IllegalStateException} will be thrown. * <li> @@ -1071,7 +1071,7 @@ public class RestResponseBody implements HttpEntity { * <li> * If no charset was found on the <code>Content-Type</code> response header, <js>"UTF-8"</js> is assumed. * <li> - * If {@link #cache()} has been called, this method can be can be called multiple times and/or combined with + * If {@link #cache()} or {@link RestResponse#cacheBody()} has been called, this method can be can be called multiple times and/or combined with * other methods that retrieve the content of the response. Otherwise a {@link RestCallException} * with an inner {@link IllegalStateException} will be thrown. * <li> @@ -1101,7 +1101,7 @@ public class RestResponseBody implements HttpEntity { * <li> * If no charset was found on the <code>Content-Type</code> response header, <js>"UTF-8"</js> is assumed. * <li> - * If {@link #cache()} has been called, this method can be can be called multiple times and/or combined with + * If {@link #cache()} or {@link RestResponse#cacheBody()} has been called, this method can be can be called multiple times and/or combined with * other methods that retrieve the content of the response. Otherwise a {@link RestCallException} * with an inner {@link IllegalStateException} will be thrown. * <li> @@ -1127,7 +1127,7 @@ public class RestResponseBody implements HttpEntity { * <li> * If no charset was found on the <code>Content-Type</code> response header, <js>"UTF-8"</js> is assumed. * <li> - * If {@link #cache()} has been called, this method can be can be called multiple times and/or combined with + * If {@link #cache()} or {@link RestResponse#cacheBody()} has been called, this method can be can be called multiple times and/or combined with * other methods that retrieve the content of the response. Otherwise a {@link RestCallException} * with an inner {@link IllegalStateException} will be thrown. * <li> @@ -1158,7 +1158,7 @@ public class RestResponseBody implements HttpEntity { * <li> * If no charset was found on the <code>Content-Type</code> response header, <js>"UTF-8"</js> is assumed. * <li> - * If {@link #cache()} has been called, this method can be can be called multiple times and/or combined with + * If {@link #cache()} or {@link RestResponse#cacheBody()} has been called, this method can be can be called multiple times and/or combined with * other methods that retrieve the content of the response. Otherwise a {@link RestCallException} * with an inner {@link IllegalStateException} will be thrown. * <li> @@ -1301,7 +1301,7 @@ public class RestResponseBody implements HttpEntity { * <li> * If no charset was found on the <code>Content-Type</code> response header, <js>"UTF-8"</js> is assumed. * <li> - * If {@link #cache()} has been called, this method can be can be called multiple times and/or combined with + * If {@link #cache()} or {@link RestResponse#cacheBody()} has been called, this method can be can be called multiple times and/or combined with * other methods that retrieve the content of the response. Otherwise a {@link RestCallException} * with an inner {@link IllegalStateException} will be thrown. * <li> @@ -1338,7 +1338,7 @@ public class RestResponseBody implements HttpEntity { * <li> * If no charset was found on the <code>Content-Type</code> response header, <js>"UTF-8"</js> is assumed. * <li> - * If {@link #cache()} has been called, this method can be can be called multiple times and/or combined with + * If {@link #cache()} or {@link RestResponse#cacheBody()} has been called, this method can be can be called multiple times and/or combined with * other methods that retrieve the content of the response. Otherwise a {@link RestCallException} * with an inner {@link IllegalStateException} will be thrown. * <li> @@ -1375,7 +1375,7 @@ public class RestResponseBody implements HttpEntity { * <li> * If no charset was found on the <code>Content-Type</code> response header, <js>"UTF-8"</js> is assumed. * <li> - * If {@link #cache()} has been called, this method can be can be called multiple times and/or combined with + * If {@link #cache()} or {@link RestResponse#cacheBody()} has been called, this method can be can be called multiple times and/or combined with * other methods that retrieve the content of the response. Otherwise a {@link RestCallException} * with an inner {@link IllegalStateException} will be thrown. * <li> @@ -1412,7 +1412,7 @@ public class RestResponseBody implements HttpEntity { * <li> * If no charset was found on the <code>Content-Type</code> response header, <js>"UTF-8"</js> is assumed. * <li> - * If {@link #cache()} has been called, this method can be can be called multiple times and/or combined with + * If {@link #cache()} or {@link RestResponse#cacheBody()} has been called, this method can be can be called multiple times and/or combined with * other methods that retrieve the content of the response. Otherwise a {@link RestCallException} * with an inner {@link IllegalStateException} will be thrown. * <li> @@ -1449,7 +1449,7 @@ public class RestResponseBody implements HttpEntity { * <li> * If no charset was found on the <code>Content-Type</code> response header, <js>"UTF-8"</js> is assumed. * <li> - * If {@link #cache()} has been called, this method can be can be called multiple times and/or combined with + * If {@link #cache()} or {@link RestResponse#cacheBody()} has been called, this method can be can be called multiple times and/or combined with * other methods that retrieve the content of the response. Otherwise a {@link RestCallException} * with an inner {@link IllegalStateException} will be thrown. * <li> @@ -1487,7 +1487,7 @@ public class RestResponseBody implements HttpEntity { * <li> * If no charset was found on the <code>Content-Type</code> response header, <js>"UTF-8"</js> is assumed. * <li> - * If {@link #cache()} has been called, this method can be can be called multiple times and/or combined with + * If {@link #cache()} or {@link RestResponse#cacheBody()} has been called, this method can be can be called multiple times and/or combined with * other methods that retrieve the content of the response. Otherwise a {@link RestCallException} * with an inner {@link IllegalStateException} will be thrown. * <li> @@ -1534,7 +1534,7 @@ public class RestResponseBody implements HttpEntity { * <li> * If no charset was found on the <code>Content-Type</code> response header, <js>"UTF-8"</js> is assumed. * <li> - * If {@link #cache()} has been called, this method can be can be called multiple times and/or combined with + * If {@link #cache()} or {@link RestResponse#cacheBody()} has been called, this method can be can be called multiple times and/or combined with * other methods that retrieve the content of the response. Otherwise a {@link RestCallException} * with an inner {@link IllegalStateException} will be thrown. * <li> @@ -1577,7 +1577,7 @@ public class RestResponseBody implements HttpEntity { * <li> * If no charset was found on the <code>Content-Type</code> response header, <js>"UTF-8"</js> is assumed. * <li> - * If {@link #cache()} has been called, this method can be can be called multiple times and/or combined with + * If {@link #cache()} or {@link RestResponse#cacheBody()} has been called, this method can be can be called multiple times and/or combined with * other methods that retrieve the content of the response. Otherwise a {@link RestCallException} * with an inner {@link IllegalStateException} will be thrown. * <li> @@ -1622,7 +1622,7 @@ public class RestResponseBody implements HttpEntity { * <li> * If no charset was found on the <code>Content-Type</code> response header, <js>"UTF-8"</js> is assumed. * <li> - * If {@link #cache()} has been called, this method can be can be called multiple times and/or combined with + * If {@link #cache()} or {@link RestResponse#cacheBody()} has been called, this method can be can be called multiple times and/or combined with * other methods that retrieve the content of the response. Otherwise a {@link RestCallException} * with an inner {@link IllegalStateException} will be thrown. * <li> @@ -1657,7 +1657,7 @@ public class RestResponseBody implements HttpEntity { * <li> * If no charset was found on the <code>Content-Type</code> response header, <js>"UTF-8"</js> is assumed. * <li> - * If {@link #cache()} has been called, this method can be can be called multiple times and/or combined with + * If {@link #cache()} or {@link RestResponse#cacheBody()} has been called, this method can be can be called multiple times and/or combined with * other methods that retrieve the content of the response. Otherwise a {@link RestCallException} * with an inner {@link IllegalStateException} will be thrown. * <li> @@ -1689,7 +1689,7 @@ public class RestResponseBody implements HttpEntity { * <li> * If no charset was found on the <code>Content-Type</code> response header, <js>"UTF-8"</js> is assumed. * <li> - * If {@link #cache()} has been called, this method can be can be called multiple times and/or combined with + * If {@link #cache()} or {@link RestResponse#cacheBody()} has been called, this method can be can be called multiple times and/or combined with * other methods that retrieve the content of the response. Otherwise a {@link RestCallException} * with an inner {@link IllegalStateException} will be thrown. * <li> @@ -1727,7 +1727,7 @@ public class RestResponseBody implements HttpEntity { * <li> * If no charset was found on the <code>Content-Type</code> response header, <js>"UTF-8"</js> is assumed. * <li> - * If {@link #cache()} has been called, this method can be can be called multiple times and/or combined with + * If {@link #cache()} or {@link RestResponse#cacheBody()} has been called, this method can be can be called multiple times and/or combined with * other methods that retrieve the content of the response. Otherwise a {@link RestCallException} * with an inner {@link IllegalStateException} will be thrown. * <li>