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 1a827ef  ignoreRecursions should not depend on detectRecursions.
1a827ef is described below

commit 1a827efdcf57a5661db2d350c3536435cbda60e3
Author: JamesBognar <[email protected]>
AuthorDate: Mon Apr 6 10:21:51 2020 -0400

    ignoreRecursions should not depend on detectRecursions.
---
 .../org/apache/juneau/BeanTraverseBuilder.java     | 115 ++++++++++++-
 .../org/apache/juneau/BeanTraverseContext.java     |  56 +++---
 .../apache/juneau/http/SerializedHttpEntity.java   |   3 +-
 juneau-doc/docs/ReleaseNotes/8.1.4.html            |   3 +
 .../juneau/rest/client2/RestClientBuilderTest.java | 191 +++++++++++++++------
 .../apache/juneau/rest/client2/RestRequest.java    |   2 +-
 6 files changed, 282 insertions(+), 88 deletions(-)

diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanTraverseBuilder.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanTraverseBuilder.java
index 6330c07..03d81f0 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanTraverseBuilder.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanTraverseBuilder.java
@@ -54,11 +54,35 @@ public class BeanTraverseBuilder extends BeanContextBuilder 
{
         * <p>
         * Specifies that recursions should be checked for during traversal.
         *
+        * <p>
+        * Recursions can occur when traversing models that aren't true trees 
but rather contain loops.
+        * <br>In general, unchecked recursions cause stack-overflow-errors.
+        * <br>These show up as {@link BeanRecursionException 
BeanRecursionException} with the message <js>"Depth too deep.  Stack overflow 
occurred."</js>.
+        *
         * <ul class='notes'>
         *      <li>
         *              Checking for recursion can cause a small performance 
penalty.
         * </ul>
         *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bcode w800'>
+        *      <jc>// Create a serializer that never adds _type to nodes.</jc>
+        *      WriterSerializer s = JsonSerializer
+        *              .<jsm>create</jsm>()
+        *              .detectRecursions(<jk>true</jk>)
+        *              .build();
+        *
+        *      <jc>// Create a POJO model with a recursive loop.</jc>
+        *      <jk>public class</jk> A {
+        *              <jk>public</jk> Object <jf>f</jf>;
+        *      }
+        *      A a = <jk>new</jk> A();
+        *      a.<jf>f</jf> = a;
+        *
+        *      <jc>// Throws a SerializeException</jc>
+        *      String json = s.serialize(a);
+        * </p>
+        *
         * <ul class='seealso'>
         *      <li class='jf'>{@link 
BeanTraverseContext#BEANTRAVERSE_detectRecursions}
         * </ul>
@@ -77,7 +101,36 @@ public class BeanTraverseBuilder extends BeanContextBuilder 
{
         * Configuration property:  Automatically detect POJO recursions.
         *
         * <p>
-        * Shortcut for calling <code>detectRecursions(<jk>true</jk>)</code>.
+        * Specifies that recursions should be checked for during traversal.
+        *
+        * <p>
+        * Recursions can occur when traversing models that aren't true trees 
but rather contain loops.
+        * <br>In general, unchecked recursions cause stack-overflow-errors.
+        * <br>These show up as {@link BeanRecursionException 
BeanRecursionException} with the message <js>"Depth too deep.  Stack overflow 
occurred."</js>.
+        *
+        * <ul class='notes'>
+        *      <li>
+        *              Checking for recursion can cause a small performance 
penalty.
+        * </ul>
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bcode w800'>
+        *      <jc>// Create a serializer that never adds _type to nodes.</jc>
+        *      WriterSerializer s = JsonSerializer
+        *              .<jsm>create</jsm>()
+        *              .detectRecursions()
+        *              .build();
+        *
+        *      <jc>// Create a POJO model with a recursive loop.</jc>
+        *      <jk>public class</jk> A {
+        *              <jk>public</jk> Object <jf>f</jf>;
+        *      }
+        *      A a = <jk>new</jk> A();
+        *      a.<jf>f</jf> = a;
+        *
+        *      <jc>// Throws a SerializeException</jc>
+        *      String json = s.serialize(a);
+        * </p>
         *
         * <ul class='seealso'>
         *      <li class='jf'>{@link 
BeanTraverseContext#BEANTRAVERSE_detectRecursions}
@@ -95,12 +148,33 @@ public class BeanTraverseBuilder extends 
BeanContextBuilder {
         *
         * <p>
         * If <jk>true</jk>, when we encounter the same object when traversing 
a tree, we set the value to <jk>null</jk>.
-        * Otherwise, an exception is thrown.
         *
-        * <ul class='notes'>
-        *      <li>
-        *              Checking for recursion can cause a small performance 
penalty.
-        * </ul>
+        * <p>
+        * For example, if a model contains the links A-&gt;B-&gt;C-&gt;A, then 
the JSON generated will look like
+        *      the following when <jsf>BEANTRAVERSE_ignoreRecursions</jsf> is 
<jk>true</jk>...
+        *
+        * <p class='bcode w800'>
+        *      {A:{B:{C:<jk>null</jk>}}}
+        * </p>
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bcode w800'>
+        *      <jc>// Create a serializer that never adds _type to nodes.</jc>
+        *      WriterSerializer s = JsonSerializer
+        *              .<jsm>create</jsm>()
+        *              .ignoreRecursions(<jk>true</jk>)
+        *              .build();
+        *
+        *      <jc>// Create a POJO model with a recursive loop.</jc>
+        *      <jk>public class</jk> A {
+        *              <jk>public</jk> Object <jf>f</jf>;
+        *      }
+        *      A a = <jk>new</jk> A();
+        *      a.<jf>f</jf> = a;
+        *
+        *      <jc>// Produces "{f:null}"</jc>
+        *      String json = s.serialize(a);
+        * </p>
         *
         * <ul class='seealso'>
         *      <li class='jf'>{@link 
BeanTraverseContext#BEANTRAVERSE_ignoreRecursions}
@@ -120,7 +194,34 @@ public class BeanTraverseBuilder extends 
BeanContextBuilder {
         * Configuration property:  Ignore recursion errors.
         *
         * <p>
-        * Shortcut for calling <code>ignoreRecursions(<jk>true</jk>)</code>.
+        * When enabled, when we encounter the same object when traversing a 
tree, we set the value to <jk>null</jk>.
+        *
+        * <p>
+        * For example, if a model contains the links A-&gt;B-&gt;C-&gt;A, then 
the JSON generated will look like
+        *      the following when <jsf>BEANTRAVERSE_ignoreRecursions</jsf> is 
<jk>true</jk>...
+        *
+        * <p class='bcode w800'>
+        *      {A:{B:{C:<jk>null</jk>}}}
+        * </p>
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bcode w800'>
+        *      <jc>// Create a serializer that never adds _type to nodes.</jc>
+        *      WriterSerializer s = JsonSerializer
+        *              .<jsm>create</jsm>()
+        *              .ignoreRecursions()
+        *              .build();
+        *
+        *      <jc>// Create a POJO model with a recursive loop.</jc>
+        *      <jk>public class</jk> A {
+        *              <jk>public</jk> Object <jf>f</jf>;
+        *      }
+        *      A a = <jk>new</jk> A();
+        *      a.<jf>f</jf> = a;
+        *
+        *      <jc>// Produces "{f:null}"</jc>
+        *      String json = s.serialize(a);
+        * </p>
         *
         * <ul class='seealso'>
         *      <li class='jf'>{@link 
BeanTraverseContext#BEANTRAVERSE_ignoreRecursions}
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanTraverseContext.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanTraverseContext.java
index ee5cb95..dcad339 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanTraverseContext.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanTraverseContext.java
@@ -15,7 +15,6 @@ package org.apache.juneau;
 
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.collections.*;
-import org.apache.juneau.parser.*;
 
 /**
  * Parent class for all classes that traverse POJOs.
@@ -63,18 +62,7 @@ public abstract class BeanTraverseContext extends 
BeanContext {
         * <p>
         * Recursions can occur when traversing models that aren't true trees 
but rather contain loops.
         * <br>In general, unchecked recursions cause stack-overflow-errors.
-        * <br>These show up as {@link ParseException ParseExceptions} with the 
message <js>"Depth too deep.  Stack overflow occurred."</js>.
-        *
-        * <p>
-        * The behavior when recursions are detected depends on the value for 
{@link #BEANTRAVERSE_ignoreRecursions}.
-        *
-        * <p>
-        * For example, if a model contains the links A-&gt;B-&gt;C-&gt;A, then 
the JSON generated will look like
-        *      the following when <jsf>BEANTRAVERSE_ignoreRecursions</jsf> is 
<jk>true</jk>...
-        *
-        * <p class='bcode w800'>
-        *      {A:{B:{C:<jk>null</jk>}}}
-        * </p>
+        * <br>These show up as {@link BeanRecursionException 
BeanRecursionException} with the message <js>"Depth too deep.  Stack overflow 
occurred."</js>.
         *
         * <ul class='notes'>
         *      <li>
@@ -86,15 +74,7 @@ public abstract class BeanTraverseContext extends 
BeanContext {
         *      <jc>// Create a serializer that never adds _type to nodes.</jc>
         *      WriterSerializer s = JsonSerializer
         *              .<jsm>create</jsm>()
-        *              .detectRecursions()
-        *              .ignoreRecursions()
-        *              .build();
-        *
-        *      <jc>// Same, but use property.</jc>
-        *      WriterSerializer s = JsonSerializer
-        *              .<jsm>create</jsm>()
         *              .set(<jsf>BEANTRAVERSE_detectRecursions</jsf>, 
<jk>true</jk>)
-        *              .set(<jsf>BEANTRAVERSE_ignoreRecursions</jsf>, 
<jk>true</jk>)
         *              .build();
         *
         *      <jc>// Create a POJO model with a recursive loop.</jc>
@@ -104,7 +84,7 @@ public abstract class BeanTraverseContext extends 
BeanContext {
         *      A a = <jk>new</jk> A();
         *      a.<jf>f</jf> = a;
         *
-        *      <jc>// Produces "{f:null}"</jc>
+        *      <jc>// Throws a SerializeException</jc>
         *      String json = s.serialize(a);
         * </p>
         */
@@ -135,12 +115,34 @@ public abstract class BeanTraverseContext extends 
BeanContext {
         *
         * <h5 class='section'>Description:</h5>
         * <p>
-        * Used in conjunction with {@link #BEANTRAVERSE_detectRecursions}.
-        * <br>Setting is ignored if <jsf>BEANTRAVERSE_detectRecursions</jsf> 
is <jk>false</jk>.
+        * If <jk>true</jk>, when we encounter the same object when traversing 
a tree, we set the value to <jk>null</jk>.
         *
         * <p>
-        * If <jk>true</jk>, when we encounter the same object when traversing 
a tree, we set the value to <jk>null</jk>.
-        * <br>Otherwise, a {@link BeanRecursionException} is thrown with the 
message <js>"Recursion occurred, stack=..."</js>.
+        * For example, if a model contains the links A-&gt;B-&gt;C-&gt;A, then 
the JSON generated will look like
+        *      the following when <jsf>BEANTRAVERSE_ignoreRecursions</jsf> is 
<jk>true</jk>...
+        *
+        * <p class='bcode w800'>
+        *      {A:{B:{C:<jk>null</jk>}}}
+        * </p>
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bcode w800'>
+        *      <jc>// Create a serializer that never adds _type to nodes.</jc>
+        *      WriterSerializer s = JsonSerializer
+        *              .<jsm>create</jsm>()
+        *              .set(<jsf>BEANTRAVERSE_ignoreRecursions</jsf>, 
<jk>true</jk>)
+        *              .build();
+        *
+        *      <jc>// Create a POJO model with a recursive loop.</jc>
+        *      <jk>public class</jk> A {
+        *              <jk>public</jk> Object <jf>f</jf>;
+        *      }
+        *      A a = <jk>new</jk> A();
+        *      a.<jf>f</jf> = a;
+        *
+        *      <jc>// Produces "{f:null}"</jc>
+        *      String json = s.serialize(a);
+        * </p>
         */
        public static final String BEANTRAVERSE_ignoreRecursions = PREFIX + 
".ignoreRecursions.b";
 
@@ -257,8 +259,8 @@ public abstract class BeanTraverseContext extends 
BeanContext {
 
                maxDepth = getIntegerProperty(BEANTRAVERSE_maxDepth, 100);
                initialDepth = getIntegerProperty(BEANTRAVERSE_initialDepth, 0);
-               detectRecursions = 
getBooleanProperty(BEANTRAVERSE_detectRecursions, false);
                ignoreRecursions = 
getBooleanProperty(BEANTRAVERSE_ignoreRecursions, false);
+               detectRecursions = 
getBooleanProperty(BEANTRAVERSE_detectRecursions, ignoreRecursions);
        }
 
        @Override /* Context */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/SerializedHttpEntity.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/SerializedHttpEntity.java
index 0026a12..b0bdefb 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/SerializedHttpEntity.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/SerializedHttpEntity.java
@@ -17,6 +17,7 @@ import static org.apache.juneau.internal.IOUtils.*;
 import java.io.*;
 
 import org.apache.http.entity.*;
+import org.apache.juneau.*;
 import org.apache.juneau.httppart.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.serializer.*;
@@ -69,7 +70,7 @@ public class SerializedHttpEntity extends BasicHttpEntity {
                                        }
                                }
                        } catch (SerializeException e) {
-                               throw new IOException(e);
+                               throw new BasicRuntimeException(e, 
"Serialization error on request body.");
                        }
                }
        }
diff --git a/juneau-doc/docs/ReleaseNotes/8.1.4.html 
b/juneau-doc/docs/ReleaseNotes/8.1.4.html
index 49a3475..80557d1 100644
--- a/juneau-doc/docs/ReleaseNotes/8.1.4.html
+++ b/juneau-doc/docs/ReleaseNotes/8.1.4.html
@@ -183,6 +183,9 @@
                        <li class='jm'>{@link 
oaj.http.annotation.FormData#multi()}
                </ul>
        <li>
+               {@link oaj.BeanContext#BEAN_ignoreRecursions} setting no longer 
requires {@link oaj.BeanContext#BEAN_detectRecursions} 
+               to be enabled.
+       <li>
                HTML-Schema support is being deprecated due to low-use and 
difficulty in maintaining.  It will be removed in 9.0.
 </ul>
 
diff --git 
a/juneau-rest/juneau-rest-client-utest/src/test/java/org/apache/juneau/rest/client2/RestClientBuilderTest.java
 
b/juneau-rest/juneau-rest-client-utest/src/test/java/org/apache/juneau/rest/client2/RestClientBuilderTest.java
index e5ccd22..72798fc 100644
--- 
a/juneau-rest/juneau-rest-client-utest/src/test/java/org/apache/juneau/rest/client2/RestClientBuilderTest.java
+++ 
b/juneau-rest/juneau-rest-client-utest/src/test/java/org/apache/juneau/rest/client2/RestClientBuilderTest.java
@@ -2233,58 +2233,145 @@ public class RestClientBuilderTest {
                assertEquals("{f:1}", b.toString());
        }
 
-//     @Test
-//     public void k21_restClient_serializerClass() throws Exception { fail(); 
}
-////   public RestClientBuilder serializer(Class<? extends Serializer> value) {
-//
-//     @Test
-//     public void k22_restClient_serializerObject() throws Exception { 
fail(); }
-////   public RestClientBuilder serializer(Serializer value) {
-//
-//     @Test
-//     public void k23_restClient_serializersClasses() throws Exception { 
fail(); }
-////   public RestClientBuilder serializers(Class<? extends 
Serializer>...value) {
-//
-//     @Test
-//     public void k24_restClient_serializersObjects() throws Exception { 
fail(); }
-////   public RestClientBuilder serializers(Serializer...value) {
-//
-//     
//-----------------------------------------------------------------------------------------------------------------
-//     // Serializer properties
-//     
//-----------------------------------------------------------------------------------------------------------------
-//
-//     @Test
-//     public void l01_serializer_addBeanTypesBoolean() throws Exception { 
fail(); }
-////   public RestClientBuilder addBeanTypes(boolean value) {
-//
-//     @Test
-//     public void l02_serializer_addBeanTypes() throws Exception { fail(); }
-////   public RestClientBuilder addBeanTypes() {
-//
-//     @Test
-//     public void l03_serializer_addRootTypeBoolean() throws Exception { 
fail(); }
-////   public RestClientBuilder addRootType(boolean value) {
-//
-//     @Test
-//     public void l04_serializer_addRootType() throws Exception { fail(); }
-////   public RestClientBuilder addRootType() {
-//
-//     @Test
-//     public void l05_serializer_detectRecursionsBoolean() throws Exception { 
fail(); }
-////   public RestClientBuilder detectRecursions(boolean value) {
-//
-//     @Test
-//     public void l06_serializer_detectRecursions() throws Exception { 
fail(); }
-////   public RestClientBuilder detectRecursions() {
-//
-//     @Test
-//     public void l07_serializer_ignoreRecursionsBoolean() throws Exception { 
fail(); }
-////   public RestClientBuilder ignoreRecursions(boolean value) {
-//
-//     @Test
-//     public void l08_serializer_ignoreRecursions() throws Exception { 
fail(); }
-////   public RestClientBuilder ignoreRecursions() {
-//
+       
//-----------------------------------------------------------------------------------------------------------------
+       // Serializer properties
+       
//-----------------------------------------------------------------------------------------------------------------
+
+       @Rest
+       public static class L extends BasicRest {
+               @RestMethod(path="/")
+               public Reader post(org.apache.juneau.rest.RestRequest req) 
throws IOException {
+                       return req.getBody().getReader();
+               }
+       }
+
+       public static class L1 {
+               public Object f1;
+
+               public static L1 create() {
+                       L1 l = new L1();
+                       l.f1 = L2.create();
+                       return l;
+               }
+       }
+
+       @org.apache.juneau.annotation.Bean(typeName="L")
+       public static class L2 {
+               public int f2;
+
+               public static L2 create() {
+                       L2 l = new L2();
+                       l.f2 = 1;
+                       return l;
+               }
+       }
+
+       @Test
+       public void l01a_serializer_addBeanTypes() throws Exception {
+               RestClient rc = MockRestClient
+                       .create(L.class)
+                       .simpleJson()
+                       .addBeanTypes(true)
+                       .build();
+               rc.post("", 
L1.create()).run().getBody().assertValue("{f1:{_type:'L',f2:1}}");
+
+               rc = MockRestClient
+                       .create(L.class)
+                       .simpleJson()
+                       .addBeanTypes(false)
+                       .build();
+               rc.post("", 
L1.create()).run().getBody().assertValue("{f1:{f2:1}}");
+
+               rc = MockRestClient
+                       .create(L.class)
+                       .simpleJson()
+                       .addBeanTypes()
+                       .build();
+               rc.post("", 
L1.create()).run().getBody().assertValue("{f1:{_type:'L',f2:1}}");
+       }
+
+       @Test
+       public void l03_serializer_addRootType() throws Exception {
+               RestClient rc = MockRestClient
+                       .create(L.class)
+                       .simpleJson()
+                       .addRootType(true)
+                       .build();
+               rc.post("", L2.create()).run().getBody().assertValue("{f2:1}");
+
+               rc = MockRestClient
+                       .create(L.class)
+                       .simpleJson()
+                       .addBeanTypes()
+                       .addRootType(false)
+                       .build();
+               rc.post("", L2.create()).run().getBody().assertValue("{f2:1}");
+
+               rc = MockRestClient
+                       .create(L.class)
+                       .simpleJson()
+                       .addBeanTypes()
+                       .addRootType(true)
+                       .build();
+               rc.post("", 
L2.create()).run().getBody().assertValue("{_type:'L',f2:1}");
+
+               rc = MockRestClient
+                       .create(L.class)
+                       .simpleJson()
+                       .addBeanTypes()
+                       .addRootType()
+                       .build();
+               rc.post("", 
L2.create()).run().getBody().assertValue("{_type:'L',f2:1}");
+       }
+
+       @Test
+       public void l05_serializer_detectRecursions() throws Exception {
+               L1 l1 = new L1();
+               l1.f1 = l1;
+
+               RestClient rc = MockRestClient
+                       .create(L.class)
+                       .simpleJson()
+                       .detectRecursions()
+                       .build();
+               try {
+                       rc.post("", l1).run();
+               } catch (RestCallException e) {
+                       
assertTrue(e.getCause().getCause().getMessage().startsWith("Recursion 
occurred"));
+               }
+
+               rc = MockRestClient
+                       .create(L.class)
+                       .simpleJson()
+                       .detectRecursions(true)
+                       .build();
+               try {
+                       rc.post("", l1).run();
+               } catch (RestCallException e) {
+                       
assertTrue(e.getCause().getCause().getMessage().startsWith("Recursion 
occurred"));
+               }
+       }
+
+       @Test
+       public void l07_serializer_ignoreRecursions() throws Exception {
+               L1 l1 = new L1();
+               l1.f1 = l1;
+
+               RestClient rc = MockRestClient
+                       .create(L.class)
+                       .simpleJson()
+                       .ignoreRecursions()
+                       .build();
+               rc.post("", l1).run().getBody().assertValue("{}");
+
+               rc = MockRestClient
+                       .create(L.class)
+                       .simpleJson()
+                       .ignoreRecursions(true)
+                       .build();
+               rc.post("", l1).run().getBody().assertValue("{}");
+       }
+
 //     @Test
 //     public void l09_serializer_initialDepth() throws Exception { fail(); }
 ////   public RestClientBuilder initialDepth(int value) {
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 4daf6c5..b13ae8a 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
@@ -2378,7 +2378,7 @@ public final class RestRequest extends BeanSession 
implements HttpUriRequest, Co
                } catch (Exception e) {
                        if (response != null)
                                response.close();
-                       throw e instanceof RestCallException ? 
(RestCallException)e : new RestCallException(e).setRestResponse(response);
+                       throw 
RestCallException.create(e).setRestResponse(response);
                }
 
                return this.response;

Reply via email to