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 2e7ac7a  REST refactoring.
     new 3ba2ceb  Merge branch 'master' of 
https://gitbox.apache.org/repos/asf/juneau.git
2e7ac7a is described below

commit 2e7ac7a78d6313d3ccae2e90e1dc450051c2799f
Author: JamesBognar <[email protected]>
AuthorDate: Sat Mar 6 10:03:41 2021 -0500

    REST refactoring.
---
 .../java/org/apache/juneau/http/HttpEntities.java  |  60 +++----
 .../juneau/http/entity/BasicHttpEntity2.java       | 159 +++++++++++++++++
 .../apache/juneau/http/entity/ByteArrayEntity.java |  40 ++---
 .../org/apache/juneau/http/entity/FileEntity.java  |  66 +++----
 .../juneau/http/entity/HttpEntityBuilder.java      | 198 +++++++++++++++++++++
 .../juneau/http/entity/InputStreamEntity.java      |  62 +++----
 .../apache/juneau/http/entity/ReaderEntity.java    |  89 ++++-----
 .../apache/juneau/http/entity/StringEntity.java    | 101 ++++-------
 .../juneau/http/response/BasicHttpException.java   |   2 +-
 .../juneau/http/response/BasicHttpResponse.java    |   2 +-
 .../juneau/http/response/HttpExceptionBuilder.java |   2 +-
 .../juneau/http/response/HttpResponseBuilder.java  |   2 +-
 .../org/apache/juneau/rest/client/RestRequest.java |   6 +-
 .../rest/client/RestClient_BasicCalls_Test.java    |  12 +-
 .../juneau/rest/client/RestClient_Body_Test.java   |  16 +-
 15 files changed, 532 insertions(+), 285 deletions(-)

diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HttpEntities.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HttpEntities.java
index d3b27d2..3f80e18 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HttpEntities.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HttpEntities.java
@@ -25,71 +25,71 @@ import org.apache.juneau.serializer.*;
 public class HttpEntities {
 
        /**
-        * Creates a new {@link ByteArrayEntity} object.
+        * Creates a new {@link ByteArrayEntity} builder.
         *
         * <p>
         * Assumes no content type.
         *
         * @param content The entity content.  Can be <jk>null<jk>.
-        * @return A new {@link ByteArrayEntity} object.
+        * @return A new {@link ByteArrayEntity} builder.
         */
-       public static final ByteArrayEntity byteArrayEntity(byte[] content) {
+       public static final HttpEntityBuilder<ByteArrayEntity> 
byteArrayEntity(byte[] content) {
                return ByteArrayEntity.of(content);
        }
 
        /**
-        * Creates a new {@link ByteArrayEntity} object.
+        * Creates a new {@link ByteArrayEntity} builder.
         *
         * @param content The entity content.  Can be <jk>null<jk>.
         * @param contentType The entity content type, or <jk>null</jk> if not 
specified.
-        * @return A new {@link ByteArrayEntity} object.
+        * @return A new {@link ByteArrayEntity} builder.
         */
-       public static final ByteArrayEntity byteArrayEntity(byte[] content, 
ContentType contentType) {
+       public static final HttpEntityBuilder<ByteArrayEntity> 
byteArrayEntity(byte[] content, ContentType contentType) {
                return ByteArrayEntity.of(content, contentType);
        }
 
        /**
-        * Creates a new {@link FileEntity} object.
+        * Creates a new {@link FileEntity} builder.
         *
         * <p>
         * Assumes no content type.
         *
         * @param content The entity content.  Can be <jk>null<jk>.
-        * @return A new {@link FileEntity} object.
+        * @return A new {@link FileEntity} builder.
         */
-       public static final FileEntity fileEntity(File content) {
+       public static final HttpEntityBuilder<FileEntity> fileEntity(File 
content) {
                return FileEntity.of(content);
        }
 
        /**
-        * Creates a new {@link FileEntity} object.
+        * Creates a new {@link FileEntity} builder.
         *
         * @param content The entity content.  Can be <jk>null<jk>.
         * @param contentType The entity content type, or <jk>null</jk> if not 
specified.
-        * @return A new {@link FileEntity} object.
+        * @return A new {@link FileEntity} builder.
         */
-       public static final FileEntity fileEntity(File content, ContentType 
contentType) {
+       public static final HttpEntityBuilder<FileEntity> fileEntity(File 
content, ContentType contentType) {
                return FileEntity.of(content, contentType);
        }
 
        /**
-        * Creates a new {@link ReaderEntity} object.
+        * Creates a new {@link ReaderEntity} builder.
         *
         * @param content The entity content.  Can be <jk>null</jk>.
-        * @return A new {@link ReaderEntity} object.
+        * @return A new {@link ReaderEntity} builder.
         */
-       public static final ReaderEntity readerEntity(Reader content) {
+       public static final HttpEntityBuilder<ReaderEntity> readerEntity(Reader 
content) {
                return ReaderEntity.of(content);
        }
 
        /**
-        * Creates a new {@link ReaderEntity} object.
+        * Creates a new {@link ReaderEntity} builder.
         *
         * @param content The entity content.  Can be <jk>null</jk>.
         * @param contentType The entity content type, or <jk>null</jk> if not 
specified.
-        * @return A new {@link ReaderEntity} object.
+        * @return A new {@link ReaderEntity} builder.
         */
-       public static final ReaderEntity readerEntity(Reader content, 
ContentType contentType) {
+       public static final HttpEntityBuilder<ReaderEntity> readerEntity(Reader 
content, ContentType contentType) {
                return ReaderEntity.of(content, -1, contentType);
        }
 
@@ -124,48 +124,48 @@ public class HttpEntities {
        }
 
        /**
-        * Creates a new {@link InputStreamEntity} object.
+        * Creates a new {@link InputStreamEntity} builder.
         *
         * <p>
         * Assumes no content type.
         *
         * @param content The entity content.  Can be <jk>null<jk>.
-        * @return A new {@link InputStreamEntity} object.
+        * @return A new {@link InputStreamEntity} builder.
         */
-       public static final InputStreamEntity streamEntity(InputStream content) 
{
+       public static final HttpEntityBuilder<InputStreamEntity> 
streamEntity(InputStream content) {
                return InputStreamEntity.of(content);
        }
 
        /**
-        * Creates a new {@link InputStreamEntity} object.
+        * Creates a new {@link InputStreamEntity} builder.
         *
         * @param content The entity content.  Can be <jk>null<jk>.
         * @param contentType The entity content type, or <jk>null</jk> if not 
specified.
         * @param length The content length, or <c>-1</c> if not known.
-        * @return A new {@link InputStreamEntity} object.
+        * @return A new {@link InputStreamEntity} builder.
         */
-       public static final InputStreamEntity streamEntity(InputStream content, 
long length, ContentType contentType) {
+       public static final HttpEntityBuilder<InputStreamEntity> 
streamEntity(InputStream content, long length, ContentType contentType) {
                return InputStreamEntity.of(content, length, contentType);
        }
 
        /**
-        * Creates a new {@link StringEntity} object.
+        * Creates a new builder for a {@link StringEntity} builder.
         *
         * @param content The entity content.  Can be <jk>null</jk>.
-        * @return A new {@link StringEntity} object.
+        * @return A new {@link StringEntity} builder.
         */
-       public static final StringEntity stringEntity(String content) {
+       public static final HttpEntityBuilder<StringEntity> stringEntity(String 
content) {
                return StringEntity.of(content);
        }
 
        /**
-        * Creates a new {@link StringEntity} object.
+        * Creates a new builder for a {@link StringEntity} builder.
         *
         * @param content The entity content.  Can be <jk>null</jk>.
         * @param contentType The entity content type, or <jk>null</jk> if not 
specified.
-        * @return A new {@link StringEntity} object.
+        * @return A new {@link StringEntity} builder.
         */
-       public static final StringEntity stringEntity(String content, 
ContentType contentType) {
+       public static final HttpEntityBuilder<StringEntity> stringEntity(String 
content, ContentType contentType) {
                return StringEntity.of(content, contentType);
        }
 }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/BasicHttpEntity2.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/BasicHttpEntity2.java
new file mode 100644
index 0000000..7a32e10
--- /dev/null
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/BasicHttpEntity2.java
@@ -0,0 +1,159 @@
+// 
***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright 
ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not 
use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                
                                              *
+// *                                                                           
                                              *
+// *  http://www.apache.org/licenses/LICENSE-2.0                               
                                              *
+// *                                                                           
                                              *
+// * Unless required by applicable law or agreed to in writing, software 
distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the 
License.                                              *
+// 
***************************************************************************************************************************
+package org.apache.juneau.http.entity;
+
+import static org.apache.juneau.internal.IOUtils.*;
+
+import java.io.*;
+import java.nio.charset.*;
+
+import org.apache.http.*;
+import org.apache.juneau.annotation.*;
+import org.apache.juneau.assertions.*;
+import org.apache.juneau.http.header.*;
+
+/**
+ * A basic {@link org.apache.http.HttpEntity} implementation with additional 
features.
+ *
+ * Provides the following features:
+ * <ul class='spaced-list'>
+ *     <li>
+ *             Caching.
+ *     <li>
+ *             Fluent setters.
+ *     <li>
+ *             Fluent assertions.
+ * </ul>
+ */
+@BeanIgnore
+public abstract class BasicHttpEntity2 implements HttpEntity {
+
+       final boolean cached, chunked;
+       final Object content;
+       final ContentType contentType;
+       final ContentEncoding contentEncoding;
+       final Charset charset;
+       final long length;
+
+       /**
+        * Creates a builder for this class.
+        *
+        * @param implClass The subclass that the builder is going to create.
+        * @return A new builder bean.
+        */
+       public static <T extends BasicHttpEntity2> HttpEntityBuilder<T> 
create(Class<T> implClass) {
+               return new HttpEntityBuilder<>(implClass);
+       }
+
+       /**
+        * Constructor.
+        *
+        * @param builder The builder containing the arguments for this bean.
+        */
+       public BasicHttpEntity2(HttpEntityBuilder<?> builder) {
+               this.cached = builder.cached;
+               this.chunked = builder.chunked;
+               this.content = builder.content;
+               this.contentType = builder.contentType;
+               this.contentEncoding = builder.contentEncoding;
+               this.charset = builder.charset;
+               this.length = builder.contentLength;
+       }
+
+       /**
+        * Creates a builder for this class initialized with the contents of 
this bean.
+        *
+        * @param implClass The subclass that the builder is going to create.
+        * @return A new builder bean.
+        */
+       public <T extends BasicHttpEntity2> HttpEntityBuilder<T> 
builder(Class<T> implClass) {
+               return create(implClass).copyFrom(this);
+       }
+
+       /**
+        * Converts the contents of this entity as a byte array.
+        *
+        * @return The contents of this entity as a byte array.
+        * @throws IOException If a problem occurred while trying to read the 
byte array.
+        */
+       public String asString() throws IOException {
+               return read(getContent());
+       }
+
+       /**
+        * Converts the contents of this entity as a byte array.
+        *
+        * @return The contents of this entity as a byte array.
+        * @throws IOException If a problem occurred while trying to read the 
byte array.
+        */
+       public byte[] asBytes() throws IOException {
+               return readBytes(getContent());
+       }
+
+       /**
+        * Returns an assertion on the contents of this entity.
+        *
+        * @return A new fluent assertion.
+        * @throws IOException If a problem occurred while trying to read the 
byte array.
+        */
+       public FluentStringAssertion<BasicHttpEntity2> assertString() throws 
IOException {
+               return new FluentStringAssertion<>(asString(), this);
+       }
+
+       /**
+        * Returns an assertion on the contents of this entity.
+        *
+        * @return A new fluent assertion.
+        * @throws IOException If a problem occurred while trying to read the 
byte array.
+        */
+       public FluentByteArrayAssertion<BasicHttpEntity2> assertBytes() throws 
IOException {
+               return new FluentByteArrayAssertion<>(asBytes(), this);
+       }
+
+       @Override /* HttpEntity */
+       public long getContentLength() {
+               return length;
+       }
+
+       @Override
+       public boolean isRepeatable() {
+               return false;
+       }
+
+       @Override
+       public boolean isChunked() {
+               return chunked;
+       }
+
+       @Override
+       public Header getContentType() {
+               return contentType;
+       }
+
+       @Override
+       public Header getContentEncoding() {
+               return contentEncoding;
+       }
+
+       @Override
+       public boolean isStreaming() {
+               return false;
+       }
+
+       @Override
+       public void consumeContent() throws IOException {}
+
+       // <FluentSetters>
+
+       // </FluentSetters>
+}
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/ByteArrayEntity.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/ByteArrayEntity.java
index bea3c52..c8835e2 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/ByteArrayEntity.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/ByteArrayEntity.java
@@ -22,43 +22,42 @@ import org.apache.juneau.http.header.*;
 /**
  * A repeatable entity that obtains its content from a byte array.
  */
-public class ByteArrayEntity extends AbstractHttpEntity {
+public class ByteArrayEntity extends BasicHttpEntity2 {
 
        private final byte[] content;
 
        /**
-        * Creates a new {@link ByteArrayEntity} object.
+        * Creates a new {@link ByteArrayEntity} builder.
         *
         * <p>
         * Assumes no content type.
         *
         * @param content The entity content.  Can be <jk>null<jk>.
-        * @return A new {@link ByteArrayEntity} object.
+        * @return A new {@link ByteArrayEntity} builder.
         */
-       public static ByteArrayEntity of(byte[] content) {
-               return new ByteArrayEntity(content, null);
+       public static HttpEntityBuilder<ByteArrayEntity> of(byte[] content) {
+               return new 
HttpEntityBuilder<>(ByteArrayEntity.class).content(content);
        }
 
        /**
-        * Creates a new {@link ByteArrayEntity} object.
+        * Creates a new {@link ByteArrayEntity} builder.
         *
         * @param content The entity content.  Can be <jk>null<jk>.
         * @param contentType The entity content type, or <jk>null</jk> if not 
specified.
-        * @return A new {@link ByteArrayEntity} object.
+        * @return A new {@link ByteArrayEntity} builder.
         */
-       public static ByteArrayEntity of(byte[] content, ContentType 
contentType) {
-               return new ByteArrayEntity(content, contentType);
+       public static HttpEntityBuilder<ByteArrayEntity> of(byte[] content, 
ContentType contentType) {
+               return new 
HttpEntityBuilder<>(ByteArrayEntity.class).content(content).contentType(contentType);
        }
 
        /**
         * Constructor.
         *
-        * @param content The entity content.  Can be <jk>null</jk>.
-        * @param contentType The entity content type, or <jk>null</jk> if not 
specified.
+        * @param builder The entity builder.
         */
-       public ByteArrayEntity(byte[] content, ContentType contentType) {
-               this.content = content == null ? new byte[0] : content;
-               setContentType(contentType);
+       public ByteArrayEntity(HttpEntityBuilder<?> builder) {
+               super(builder);
+               this.content = builder.content == null ? new byte[0] : 
(byte[])builder.content;
        }
 
        @Override /* AbstractHttpEntity */
@@ -86,20 +85,9 @@ public class ByteArrayEntity extends AbstractHttpEntity {
                return new ByteArrayInputStream(content);
        }
 
-       /**
-        * Writes the contents of the byte array directly to the output stream.
-        *
-        * The content length determines how many bytes are written.
-        * If the length is unknown ({@code -1}), the stream will be completely 
consumed (to the end of the stream).
-        */
-       @Override
+       @Override /* HttpEntity */
        public void writeTo(OutputStream out) throws IOException {
                assertArgNotNull("out", out);
                out.write(content);
        }
-
-       @Override /* HttpEntity */
-       public boolean isStreaming() {
-               return false;
-       }
 }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/FileEntity.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/FileEntity.java
index d63a19b..355e126 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/FileEntity.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/FileEntity.java
@@ -16,7 +16,6 @@ import static org.apache.juneau.assertions.Assertions.*;
 import static org.apache.juneau.internal.IOUtils.*;
 
 import java.io.*;
-import java.util.concurrent.atomic.*;
 
 import org.apache.juneau.http.header.*;
 import org.apache.juneau.internal.*;
@@ -24,44 +23,45 @@ import org.apache.juneau.internal.*;
 /**
  * A repeatable entity that obtains its content from a {@link File}.
  */
-public class FileEntity extends AbstractHttpEntity {
+public class FileEntity extends BasicHttpEntity2 {
 
        private final File content;
-       private AtomicReference<byte[]> cache = new AtomicReference<>();
+       private final byte[] cache;
 
        /**
-        * Creates a new {@link FileEntity} object.
+        * Creates a new {@link FileEntity} builder.
         *
         * <p>
         * Assumes no content type.
         *
         * @param content The entity content.  Can be <jk>null<jk>.
-        * @return A new {@link FileEntity} object.
+        * @return A new {@link FileEntity} builder.
         */
-       public static FileEntity of(File content) {
-               return new FileEntity(content, null);
+       public static HttpEntityBuilder<FileEntity> of(File content) {
+               return new 
HttpEntityBuilder<>(FileEntity.class).content(content);
        }
 
        /**
-        * Creates a new {@link FileEntity} object.
+        * Creates a new {@link FileEntity} builder.
         *
         * @param content The entity content.  Can be <jk>null<jk>.
         * @param contentType The entity content type, or <jk>null</jk> if not 
specified.
-        * @return A new {@link FileEntity} object.
+        * @return A new {@link FileEntity} builder.
         */
-       public static FileEntity of(File content, ContentType contentType) {
-               return new FileEntity(content, contentType);
+       public static HttpEntityBuilder<FileEntity> of(File content, 
ContentType contentType) {
+               return new 
HttpEntityBuilder<>(FileEntity.class).content(content).contentType(contentType);
        }
 
        /**
         * Constructor.
         *
-        * @param content The entity content.  Can be <jk>null</jk>.
-        * @param contentType The entity content type, or <jk>null</jk> if not 
specified.
+        * @param builder The entity builder.
+        * @throws IOException If file could not be read.
         */
-       public FileEntity(File content, ContentType contentType) {
-               this.content = content;
-               setContentType(contentType);
+       public FileEntity(HttpEntityBuilder<?> builder) throws IOException {
+               super(builder);
+               this.content = (File)builder.content;
+               cache = builder.cached ? readBytes(this.content) : null;
        }
 
        @Override /* AbstractHttpEntity */
@@ -71,8 +71,7 @@ public class FileEntity extends AbstractHttpEntity {
 
        @Override /* AbstractHttpEntity */
        public byte[] asBytes() throws IOException {
-               cache();
-               return cache.get();
+               return cache == null ? readBytes(this.content) : cache;
        }
 
        @Override /* HttpEntity */
@@ -87,42 +86,19 @@ public class FileEntity extends AbstractHttpEntity {
 
        @Override /* HttpEntity */
        public InputStream getContent() throws IOException {
-               byte[] b = cache.get();
-               return b == null ? new FileInputStream(content) : new 
ByteArrayInputStream(b);
-       }
-
-       @Override /* AbstractHttpEntity */
-       public FileEntity cache() throws IOException {
-               byte[] b = cache.get();
-               if (b == null) {
-                       b = readBytes(content);
-                       cache.set(b);
-               }
-               return this;
+               return cache == null ? new FileInputStream(content) : new 
ByteArrayInputStream(cache);
        }
 
-       /**
-        * Writes bytes from the {@code InputStream} this entity was constructed
-        * with to an {@code OutputStream}.  The content length
-        * determines how many bytes are written.  If the length is unknown 
({@code -1}), the
-        * stream will be completely consumed (to the end of the stream).
-        */
-       @Override
+       @Override /* HttpEntity */
        public void writeTo(OutputStream out) throws IOException {
                assertArgNotNull("out", out);
 
-               byte[] b = cache.get();
-               if (b != null) {
-                       out.write(b);
+               if (cache != null) {
+                       out.write(cache);
                } else {
                        try (InputStream is = getContent()) {
                                IOUtils.pipe(is, out);
                        }
                }
        }
-
-       @Override /* HttpEntity */
-       public boolean isStreaming() {
-               return false;
-       }
 }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/HttpEntityBuilder.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/HttpEntityBuilder.java
new file mode 100644
index 0000000..c8b8438
--- /dev/null
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/HttpEntityBuilder.java
@@ -0,0 +1,198 @@
+// 
***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright 
ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not 
use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                
                                              *
+// *                                                                           
                                              *
+// *  http://www.apache.org/licenses/LICENSE-2.0                               
                                              *
+// *                                                                           
                                              *
+// * Unless required by applicable law or agreed to in writing, software 
distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the 
License.                                              *
+// 
***************************************************************************************************************************
+package org.apache.juneau.http.entity;
+
+import java.io.*;
+import java.nio.charset.*;
+
+import org.apache.http.*;
+import org.apache.juneau.http.header.*;
+import org.apache.juneau.internal.*;
+
+/**
+ * Builder for {@link HttpEntity} beans.
+ *
+ * @param <T> The bean type to create for this builder.
+ */
+@FluentSetters(returns="HttpEntityBuilder<T>")
+public class HttpEntityBuilder<T extends BasicHttpEntity2> {
+
+       boolean cached, chunked;
+       Object content;
+       ContentType contentType;
+       ContentEncoding contentEncoding;
+       Charset charset;
+       long contentLength = -1;
+
+       private final Class<? extends BasicHttpEntity2> implClass;
+
+       /**
+        * Constructor.
+        *
+        * @param implClass
+        *      The subclass of {@link HttpResponse} to create.
+        *      <br>This must contain a public constructor that takes in an 
{@link HttpEntityBuilder} object.
+        */
+       public HttpEntityBuilder(Class<T> implClass) {
+               this.implClass = implClass;
+       }
+
+       /**
+        * Instantiates the entity bean from the settings in this builder.
+        *
+        * @return A new {@link HttpEntity} bean.
+        */
+       @SuppressWarnings("unchecked")
+       public T build() {
+               try {
+                       return (T) 
implClass.getConstructor(HttpEntityBuilder.class).newInstance(this);
+               } catch (Exception e) {
+                       throw new RuntimeException(e);
+               }
+       }
+
+       /**
+        * Copies the values from the specified entity bean.
+        *
+        * @param value The exception to copy from.
+        * @return This object (for method chaining).
+        */
+       public HttpEntityBuilder<T> copyFrom(BasicHttpEntity2 value) {
+               this.cached = value.cached;
+               this.content = value.content;
+               this.contentType = value.contentType;
+               this.contentEncoding = value.contentEncoding;
+               this.charset = value.charset;
+               this.contentLength = value.length;
+               return this;
+       }
+
+       /**
+        * Sets the content on this entity bean.
+        *
+        * @param value The entity content, can be <jk>null</jk>.
+        * @return This object (for method chaining).
+        */
+       @FluentSetter
+       public HttpEntityBuilder<T> content(Object value) {
+               this.content = value;
+               return this;
+       }
+
+       /**
+        * Sets the content type on this entity bean.
+        *
+        * @param value The new <c>Content-Type</ header, or <jk>null</jk> to 
unset.
+        * @return This object (for method chaining).
+        */
+       @FluentSetter
+       public HttpEntityBuilder<T> contentType(String value) {
+               return contentType(ContentType.of(value));
+       }
+
+       /**
+        * Sets the content type on this entity bean.
+        *
+        * @param value The new <c>Content-Type</ header, or <jk>null</jk> to 
unset.
+        * @return This object (for method chaining).
+        */
+       @FluentSetter
+       public HttpEntityBuilder<T> contentType(ContentType value) {
+               contentType = value;
+               return this;
+       }
+
+       /**
+        * Sets the content length on this entity bean.
+        *
+        * @param value The new <c>Content-Length</c> header value, or 
<c>-1</c> to unset.
+        * @return This object (for method chaining).
+        */
+       @FluentSetter
+       public HttpEntityBuilder<T> contentLength(long value) {
+               contentLength = value;
+               return this;
+       }
+
+       /**
+        * Sets the content encoding header on this entity bean.
+        *
+        * @param value The new <c>Content-Encoding</ header, or <jk>null</jk> 
to unset.
+        * @return This object (for method chaining).
+        */
+       @FluentSetter
+       public HttpEntityBuilder<T> contentEncoding(String value) {
+               return contentEncoding(ContentEncoding.of(value));
+       }
+
+       /**
+        * Sets the content encoding header on this entity bean.
+        *
+        * @param value The new <c>Content-Encoding</ header, or <jk>null</jk> 
to unset.
+        * @return This object (for method chaining).
+        */
+       @FluentSetter
+       public HttpEntityBuilder<T> contentEncoding(ContentEncoding value) {
+               contentEncoding = value;
+               return this;
+       }
+
+       /**
+        * Sets the 'chunked' flag value to <jk>true</jk>.
+        *
+        * <ul class='notes'>
+        *      <li>If the {@link HttpEntity#getContentLength()} method returns 
a negative value, the HttpClient code will always
+        *              use chunked encoding.
+        * </ul>
+        *
+        * @return This object (for method chaining).
+        */
+       @FluentSetter
+       public HttpEntityBuilder<T> chunked() {
+               return chunked(true);
+       }
+
+       /**
+        * Sets the 'chunked' flag value.
+        *
+        * <ul class='notes'>
+        *      <li>If the {@link HttpEntity#getContentLength()} method returns 
a negative value, the HttpClient code will always
+        *              use chunked encoding.
+        * </ul>
+        *
+        * @param value The new value for this flag.
+        * @return This object (for method chaining).
+        */
+       @FluentSetter
+       public HttpEntityBuilder<T> chunked(boolean value) {
+               chunked = value;
+               return this;
+       }
+
+       /**
+        * Specifies that the contents of this resource should be cached into 
an internal byte array so that it can
+        * be read multiple times.
+        *
+        * @return This object (for method chaining).
+        * @throws IOException If entity could not be read into memory.
+        */
+       @FluentSetter
+       public HttpEntityBuilder<T> cached() throws IOException {
+               cached = true;
+               return this;
+       }
+
+       // <FluentSetters>
+
+       // </FluentSetters>
+}
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/InputStreamEntity.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/InputStreamEntity.java
index 8a56a18..6613daa 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/InputStreamEntity.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/InputStreamEntity.java
@@ -16,55 +16,54 @@ import static org.apache.juneau.assertions.Assertions.*;
 import static org.apache.juneau.internal.IOUtils.*;
 
 import java.io.*;
-import java.util.concurrent.atomic.*;
 
 import org.apache.juneau.http.header.*;
 
 /**
  * A streamed, non-repeatable entity that obtains its content from an {@link 
InputStream}.
  */
-public class InputStreamEntity extends AbstractHttpEntity {
+public class InputStreamEntity extends BasicHttpEntity2 {
 
        private final InputStream content;
        private final long length;
-       private final AtomicReference<byte[]> cache = new AtomicReference<>();
+       private final byte[] cache;
 
        /**
-        * Creates a new {@link InputStreamEntity} object.
+        * Creates a new {@link InputStreamEntity} builder.
         *
         * <p>
         * Assumes no content type.
         *
         * @param content The entity content.  Can be <jk>null<jk>.
-        * @return A new {@link InputStreamEntity} object.
+        * @return A new {@link InputStreamEntity} builder.
         */
-       public static InputStreamEntity of(InputStream content) {
-               return new InputStreamEntity(content, -1, null);
+       public static HttpEntityBuilder<InputStreamEntity> of(InputStream 
content) {
+               return new 
HttpEntityBuilder<>(InputStreamEntity.class).content(content);
        }
 
        /**
-        * Creates a new {@link InputStreamEntity} object.
+        * Creates a new {@link InputStreamEntity} builder.
         *
         * @param content The entity content.  Can be <jk>null<jk>.
         * @param contentType The entity content type, or <jk>null</jk> if not 
specified.
         * @param length The content length, or <c>-1</c> if not known.
-        * @return A new {@link InputStreamEntity} object.
+        * @return A new {@link InputStreamEntity} builder.
         */
-       public static InputStreamEntity of(InputStream content, long length, 
ContentType contentType) {
-               return new InputStreamEntity(content, length, contentType);
+       public static HttpEntityBuilder<InputStreamEntity> of(InputStream 
content, long length, ContentType contentType) {
+               return new 
HttpEntityBuilder<>(InputStreamEntity.class).content(content).contentLength(length).contentType(contentType);
        }
 
        /**
         * Constructor.
         *
-        * @param content The entity content.  Can be <jk>null</jk>.
-        * @param contentType The entity content type, or <jk>null</jk> if not 
specified.
-        * @param length The content length, or <c>-1</c> if not known.
+        * @param builder The entity builder.
+        * @throws IOException If stream could not be read.
         */
-       public InputStreamEntity(InputStream content, long length, ContentType 
contentType) {
-               this.content = content == null ? EMPTY_INPUT_STREAM : content;
-               this.length = length;
-               setContentType(contentType);
+       public InputStreamEntity(HttpEntityBuilder<?> builder) throws 
IOException {
+               super(builder);
+               this.content = builder.content == null ? EMPTY_INPUT_STREAM : 
(InputStream)builder.content;
+               this.cache = builder.cached ? readBytes(this.content) : null;
+               this.length = builder.contentLength == -1 && cache != null ? 
cache.length : builder.contentLength;
        }
 
        @Override /* AbstractHttpEntity */
@@ -74,13 +73,12 @@ public class InputStreamEntity extends AbstractHttpEntity {
 
        @Override /* AbstractHttpEntity */
        public byte[] asBytes() throws IOException {
-               cache();
-               return cache.get();
+               return cache == null ? readBytes(content) : cache;
        }
 
        @Override /* HttpEntity */
        public boolean isRepeatable() {
-               return cache.get() != null;
+               return cache != null;
        }
 
        @Override /* HttpEntity */
@@ -90,20 +88,7 @@ public class InputStreamEntity extends AbstractHttpEntity {
 
        @Override /* HttpEntity */
        public InputStream getContent() throws IOException {
-               byte[] b = cache.get();
-               return b == null ? content : new ByteArrayInputStream(b);
-       }
-
-       @Override /* AbstractHttpEntity */
-       public InputStreamEntity cache() throws IOException {
-               byte[] b = cache.get();
-               if (b == null) {
-                       try (InputStream is = getContent()) {
-                               b = readBytes(is, (int)length);
-                       }
-                       cache.set(b);
-               }
-               return this;
+               return cache == null ? content : new 
ByteArrayInputStream(cache);
        }
 
        /**
@@ -116,9 +101,8 @@ public class InputStreamEntity extends AbstractHttpEntity {
        public void writeTo(OutputStream out) throws IOException {
                assertArgNotNull("out", out);
 
-               byte[] b = cache.get();
-               if (b != null) {
-                       pipe(b, out, (int)length);
+               if (cache != null) {
+                       pipe(cache, out, (int)length);
                } else {
                        try (InputStream is = getContent()) {
                                pipe(is, out, length);
@@ -128,6 +112,6 @@ public class InputStreamEntity extends AbstractHttpEntity {
 
        @Override /* HttpEntity */
        public boolean isStreaming() {
-               return cache.get() == null;
+               return cache == null;
        }
 }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/ReaderEntity.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/ReaderEntity.java
index 0ac4b37..3db0482 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/ReaderEntity.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/ReaderEntity.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.internal.IOUtils.*;
 
 import java.io.*;
 import java.nio.charset.*;
-import java.util.concurrent.atomic.*;
 
 import org.apache.juneau.http.header.*;
 import org.apache.juneau.internal.*;
@@ -25,80 +24,65 @@ import org.apache.juneau.internal.*;
 /**
  * A streamed, non-repeatable entity that obtains its content from an {@link 
Reader}.
  */
-public class ReaderEntity extends AbstractHttpEntity {
+public class ReaderEntity extends BasicHttpEntity2 {
 
        private final Reader content;
        private final long length;
-       private Charset charset = UTF8;
-       private final AtomicReference<String> cache = new AtomicReference<>();
+       private final Charset charset;
+       private final byte[] cache;
 
        /**
-        * Creates a new {@link ReaderEntity} object.
+        * Creates a new {@link ReaderEntity} builder.
         *
         * <p>
         * Assumes no content type.
         *
         * @param content The entity content.  Can be <jk>null<jk>.
-        * @return A new {@link ReaderEntity} object.
+        * @return A new {@link ReaderEntity} builder.
         */
-       public static ReaderEntity of(Reader content) {
-               return new ReaderEntity(content, -1, null);
+       public static HttpEntityBuilder<ReaderEntity> of(Reader content) {
+               return new 
HttpEntityBuilder<>(ReaderEntity.class).content(content);
        }
 
        /**
-        * Creates a new {@link ReaderEntity} object.
+        * Creates a new {@link ReaderEntity} builder.
         *
-        * @param content The entity content.  Can be <jk>null<jk>.
+        * @param content The entity builder.  Can be <jk>null<jk>.
         * @param contentType The entity content type, or <jk>null</jk> if not 
specified.
         * @param length The content length, or <c>-1</c> if not known.
-        * @return A new {@link ReaderEntity} object.
+        * @return A new {@link ReaderEntity} builder.
         */
-       public static ReaderEntity of(Reader content, long length, ContentType 
contentType) {
-               return new ReaderEntity(content, length, contentType);
+       public static HttpEntityBuilder<ReaderEntity> of(Reader content, long 
length, ContentType contentType) {
+               return new 
HttpEntityBuilder<>(ReaderEntity.class).content(content).contentLength(length).contentType(contentType);
        }
 
        /**
         * Constructor.
         *
-        * @param content The entity content.  Can be <jk>null</jk>.
-        * @param contentType The entity content type, or <jk>null</jk> if not 
specified.
-        * @param length The content length, or <c>-1</c> if not known.
-        */
-       public ReaderEntity(Reader content, long length, ContentType 
contentType) {
-               this.content = content == null ? EMPTY_READER : content;
-               this.length = length;
-               setContentType(contentType);
-       }
-
-       /**
-        * Specifies the charset to use for the output.
-        *
-        * <p>
-        * The default is <js>"UTF-8"</js>.
-        *
-        * @param value The new charset, or <js>"UTF-8"</js> if <jk>null</jk>.
-        * @return This object (for method chaining).
+        * @param builder The entity builder.
+        * @throws IOException If reader could not be read.
         */
-       @FluentSetter
-       public ReaderEntity charset(Charset value) {
-               this.charset = value == null ? UTF8 : value;
-               return this;
+       public ReaderEntity(HttpEntityBuilder<?> builder) throws IOException {
+               super(builder);
+               this.content = builder.content == null ? EMPTY_READER : 
(Reader)builder.content;
+               this.charset = builder.charset == null ? UTF8 : builder.charset;
+               this.cache = builder.cached ? readBytes(this.content) : null;
+               this.length = builder.contentLength == -1 && cache != null ? 
cache.length : builder.contentLength;
        }
 
        @Override /* AbstractHttpEntity */
        public String asString() throws IOException {
-               cache();
-               return cache.get();
+               return cache == null ? read(content) : new String(cache, UTF8);
        }
 
        @Override /* AbstractHttpEntity */
        public byte[] asBytes() throws IOException {
-               return asString().getBytes(UTF8);
+               return cache == null ? asString().getBytes(UTF8) : cache;
        }
 
        @Override /* HttpEntity */
        public boolean isRepeatable() {
-               return cache.get() != null;
+               return cache != null;
        }
 
        @Override /* HttpEntity */
@@ -108,20 +92,7 @@ public class ReaderEntity extends AbstractHttpEntity {
 
        @Override /* HttpEntity */
        public InputStream getContent() throws IOException {
-               String s = cache.get();
-               return s == null ? new ReaderInputStream(content, charset) : 
new ReaderInputStream(new StringReader(s), charset);
-       }
-
-       @Override /* AbstractHttpEntity */
-       public ReaderEntity cache() throws IOException {
-               String s = cache.get();
-               if (s == null) {
-                       try (Reader r = content) {
-                               s = read(r);
-                       }
-                       cache.set(s);
-               }
-               return this;
+               return cache == null ? new ReaderInputStream(content, charset) 
: new ByteArrayInputStream(cache);
        }
 
        /**
@@ -134,18 +105,18 @@ public class ReaderEntity extends AbstractHttpEntity {
        public void writeTo(OutputStream out) throws IOException {
                assertArgNotNull("out", out);
 
-               OutputStreamWriter osw = new OutputStreamWriter(out, charset);
-               String s = cache.get();
-               if (s != null) {
-                       osw.write(s);
+               if (cache != null) {
+                       out.write(cache);
                } else {
+                       OutputStreamWriter osw = new OutputStreamWriter(out, 
charset);
                        pipe(content, osw);
+                       osw.flush();
                }
-               osw.flush();
+               out.flush();
        }
 
        @Override /* HttpEntity */
        public boolean isStreaming() {
-               return cache.get() == null;
+               return cache == null;
        }
 }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/StringEntity.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/StringEntity.java
index 9cf5e98..904fec9 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/StringEntity.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/entity/StringEntity.java
@@ -14,84 +14,58 @@ package org.apache.juneau.http.entity;
 
 import static org.apache.juneau.assertions.Assertions.*;
 import static org.apache.juneau.internal.IOUtils.*;
-import static org.apache.juneau.internal.StringUtils.*;
 
 import java.io.*;
 import java.nio.charset.Charset;
-import java.util.concurrent.atomic.*;
 
 import org.apache.juneau.http.header.*;
 import org.apache.juneau.internal.*;
 
 /**
  * A self contained, repeatable entity that obtains its content from a {@link 
String}.
- *
- * Similar to {@link org.apache.http.entity.StringEntity} but delays 
converting to an internal byte array until
- * actually used.
  */
-public class StringEntity extends AbstractHttpEntity {
+public class StringEntity extends BasicHttpEntity2 {
 
        private final String content;
-       private final AtomicReference<byte[]> cache = new AtomicReference<>();
-       private Charset charset = UTF8;
+       private final byte[] cache;
+       private final Charset charset;
 
        /**
-        * Creates a new {@link StringEntity} object.
+        * Creates a new {@link StringEntity} builder.
         *
         * @param content The entity content.  Can be <jk>null</jk>.
-        * @return A new {@link StringEntity} object.
+        * @return A new {@link StringEntity} builder.
         */
-       public static StringEntity of(String content) {
-               return new StringEntity(content, null);
+       public static HttpEntityBuilder<StringEntity> of(String content) {
+               return new 
HttpEntityBuilder<>(StringEntity.class).content(content);
        }
 
        /**
-        * Creates a new {@link StringEntity} object.
+        * Creates a new {@link StringEntity} builder.
         *
         * @param content The entity content.  Can be <jk>null</jk>.
         * @param contentType The entity content type, or <jk>null</jk> if not 
specified.
-        * @return A new {@link StringEntity} object.
+        * @return A new {@link StringEntity} builder.
         */
-       public static StringEntity of(String content, ContentType contentType) {
-               return new StringEntity(content, contentType);
+       public static HttpEntityBuilder<StringEntity> of(String content, 
ContentType contentType) {
+               return new 
HttpEntityBuilder<>(StringEntity.class).content(content).contentType(contentType);
        }
 
        /**
         * Constructor.
         *
-        * @param content The entity content. Can be <jk>null</jk>.
-        * @param contentType The entity content type, or <jk>null</jk> if not 
specified.
-        */
-       public StringEntity(String content, ContentType contentType) {
-               this.content = emptyIfNull(content);
-               setContentType(contentType);
-       }
-
-       /**
-        * Specifies the charset to use for the output.
-        *
-        * <p>
-        * The default is <js>"UTF-8"</js>.
-        *
-        * @param value The new charset, or <js>"UTF-8"</js> if <jk>null</jk>.
-        * @return This object (for method chaining).
+        * @param builder The entity builder.
         */
-       @FluentSetter
-       public StringEntity charset(Charset value) {
-               this.charset = value == null ? UTF8 : value;
-               return this;
+       public StringEntity(HttpEntityBuilder<?> builder) {
+               super(builder);
+               content = builder.content == null ? "" : 
(String)builder.content;
+               charset = builder.charset == null ? UTF8 : builder.charset;
+               cache = builder.cached ? this.content.getBytes(charset) : null;
        }
 
        @Override
        public byte[] asBytes() throws IOException {
-               cache();
-               return cache.get();
-       }
-
-       @Override /* AbstractHttpEntity */
-       public StringEntity cache() {
-               getBytes();
-               return this;
+               return cache == null ? content.getBytes() : cache;
        }
 
        @Override /* HttpEntity */
@@ -101,41 +75,38 @@ public class StringEntity extends AbstractHttpEntity {
 
        @Override /* HttpEntity */
        public long getContentLength() {
-               long len = super.getContentLength();
-               if (len == -1) {
-                       len = getBytes().length;
-                       contentLength(len);
-               }
-               return len;
+               if (cache != null)
+                       return cache.length;
+               long l = super.getContentLength();
+               if (l != -1)
+                       return l;
+               if (charset == UTF8)
+                       for (int i = 0; i < content.length(); i++)
+                               if (content.charAt(i) > 127)
+                                       return -1;
+               return content.length();
        }
 
        @Override /* HttpEntity */
        public InputStream getContent() throws IOException {
-               return new ByteArrayInputStream(getBytes());
+               return cache == null ? new ReaderInputStream(new 
StringReader(content), charset) : new ByteArrayInputStream(cache);
        }
 
        @Override /* HttpEntity */
        public void writeTo(OutputStream out) throws IOException {
                assertArgNotNull("out", out);
-               OutputStreamWriter osw = new OutputStreamWriter(out, charset);
-               osw.write(content);
-               osw.flush();
+               if (cache != null) {
+                       out.write(cache);
+               } else {
+                       OutputStreamWriter osw = new OutputStreamWriter(out, 
charset);
+                       osw.write(content);
+                       osw.flush();
+               }
        }
 
        @Override /* HttpEntity */
        public boolean isStreaming() {
                return false;
        }
-
-       private byte[] getBytes() {
-               byte[] b = cache.get();
-               if (b == null) {
-                       synchronized(cache) {
-                                b = content.getBytes(charset);
-                                cache.set(b);
-                       }
-               }
-               return b;
-       }
 }
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/response/BasicHttpException.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/response/BasicHttpException.java
index 9bdfb15..234b365 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/response/BasicHttpException.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/response/BasicHttpException.java
@@ -371,7 +371,7 @@ public class BasicHttpException extends 
BasicRuntimeException implements HttpRes
        public HttpEntity getEntity() {
                // Constructing a StringEntity is somewhat expensive, so don't 
create it unless it's needed.
                if (body == null)
-                       body = stringEntity(getMessage());
+                       body = stringEntity(getMessage()).build();
                return body;
        }
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/response/BasicHttpResponse.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/response/BasicHttpResponse.java
index 864210b..f2d0838 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/response/BasicHttpResponse.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/response/BasicHttpResponse.java
@@ -250,7 +250,7 @@ public class BasicHttpResponse implements HttpResponse {
        public HttpEntity getEntity() {
                // Constructing a StringEntity is somewhat expensive, so don't 
create it unless it's needed.
                if (body == null)
-                       body = stringEntity(getStatusLine().getReasonPhrase());
+                       body = 
stringEntity(getStatusLine().getReasonPhrase()).build();
                return body;
        }
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/response/HttpExceptionBuilder.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/response/HttpExceptionBuilder.java
index a907d5b..e6e928d 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/response/HttpExceptionBuilder.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/response/HttpExceptionBuilder.java
@@ -392,7 +392,7 @@ public class HttpExceptionBuilder<T extends 
BasicHttpException> extends BasicRun
         * @return This object (for method chaining).
         */
        public HttpExceptionBuilder<T> body(String value) {
-               body(stringEntity(value));
+               body(stringEntity(value).build());
                return this;
        }
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/response/HttpResponseBuilder.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/response/HttpResponseBuilder.java
index 055dedd..62765ea 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/response/HttpResponseBuilder.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/response/HttpResponseBuilder.java
@@ -424,7 +424,7 @@ public class HttpResponseBuilder<T extends 
BasicHttpResponse> {
         * @return This object (for method chaining).
         */
        public HttpResponseBuilder<T> body(String value) {
-               return body(stringEntity(value));
+               return body(stringEntity(value).build());
        }
 
        /**
diff --git 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestRequest.java
 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestRequest.java
index f057b4f..6a22569 100644
--- 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestRequest.java
+++ 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestRequest.java
@@ -2905,9 +2905,9 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
                                else if (input2 instanceof HttpEntity)
                                        entity = (HttpEntity)input2;
                                else if (input2 instanceof Reader)
-                                       entity = 
stringEntity(read((Reader)input2), getRequestContentType(TEXT_PLAIN));
+                                       entity = readerEntity((Reader)input2, 
getRequestContentType(TEXT_PLAIN)).build();
                                else if (input2 instanceof InputStream)
-                                       entity = 
streamEntity((InputStream)input2, -1, 
getRequestContentType(ContentType.APPLICATION_OCTET_STREAM));
+                                       entity = 
streamEntity((InputStream)input2, -1, 
getRequestContentType(ContentType.APPLICATION_OCTET_STREAM)).build();
                                else if (serializer != null)
                                        entity = SerializedEntity.of(input2, 
serializer).schema(requestBodySchema).contentType(contentType);
                                else {
@@ -2918,7 +2918,7 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
                                        }
                                        if (input2 == null)
                                                input2 = "";
-                                       entity = 
stringEntity(BeanContext.DEFAULT.getClassMetaForObject(input2).toString(input2),
 getRequestContentType(TEXT_PLAIN));
+                                       entity = 
stringEntity(BeanContext.DEFAULT.getClassMetaForObject(input2).toString(input2),
 getRequestContentType(TEXT_PLAIN)).build();
                                }
 
                                request2.setEntity(entity);
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_BasicCalls_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_BasicCalls_Test.java
index 435fb63..181acbd 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_BasicCalls_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_BasicCalls_Test.java
@@ -168,7 +168,7 @@ public class RestClient_BasicCalls_Test {
                        new ByteArrayInputStream("{f:1}".getBytes()),
                        BasicHttpResource.of("{f:1}"),
                        bean,
-                       stringEntity("{f:1}"),
+                       stringEntity("{f:1}").build(),
                        parts("f",1)
                );
                for (Object body : bodies) {
@@ -211,7 +211,7 @@ public class RestClient_BasicCalls_Test {
                        new ByteArrayInputStream("{f:1}".getBytes()),
                        BasicHttpResource.of("{f:1}"),
                        bean,
-                       stringEntity("{f:1}"),
+                       stringEntity("{f:1}").build(),
                        parts("f",1)
                );
                for (Object body : bodies) {
@@ -312,8 +312,8 @@ public class RestClient_BasicCalls_Test {
                        /*[ 0]*/ bean,
                        /*[ 1]*/ parts("f","1"),
                        /*[ 2]*/ new NameValuePair[]{part("f","1")},
-                       /*[ 3]*/ stringEntity("f=1", 
ContentType.APPLICATION_FORM_URLENCODED),
-                       /*[ 4]*/ stringEntity("f=1", null),
+                       /*[ 3]*/ stringEntity("f=1", 
ContentType.APPLICATION_FORM_URLENCODED).build(),
+                       /*[ 4]*/ stringEntity("f=1", null).build(),
                        /*[ 5]*/ part("f","1"),
                        /*[ 6]*/ BasicHttpResource.of("f=1"),
                        /*[ 7]*/ BasicHttpResource.of("f=1"),
@@ -351,7 +351,7 @@ public class RestClient_BasicCalls_Test {
                        new ByteArrayInputStream("{f:1}".getBytes()),
                        BasicHttpResource.of("{f:1}"),
                        bean,
-                       stringEntity("{f:1}"),
+                       stringEntity("{f:1}").build(),
                        parts("f",1)
                );
                RestClient x = client().build();
@@ -388,7 +388,7 @@ public class RestClient_BasicCalls_Test {
                        new ByteArrayInputStream("{f:1}".getBytes()),
                        BasicHttpResource.of("{f:1}"),
                        bean,
-                       stringEntity("{f:1}"),
+                       stringEntity("{f:1}").build(),
                        parts("f",1)
                );
                RestClient x = client().build();
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Body_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Body_Test.java
index 54dcedf..240bde0 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Body_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Body_Test.java
@@ -106,7 +106,7 @@ public class RestClient_Body_Test {
 
        @Test
        public void a02_StringEntity() throws Exception {
-               HttpEntity x1 = stringEntity("foo");
+               HttpEntity x1 = stringEntity("foo").build();
                client().build().post("/", x1).run()
                        .assertHeader("X-Content-Length").asInteger().is(3)
                        .assertHeader("X-Content-Encoding").doesNotExist()
@@ -114,7 +114,7 @@ public class RestClient_Body_Test {
                        .assertHeader("X-Transfer-Encoding").doesNotExist()
                ;
 
-               HttpEntity x2 = 
stringEntity("foo").contentType("text/plain").contentEncoding("identity");
+               HttpEntity x2 = 
stringEntity("foo").contentType("text/plain").contentEncoding("identity").build();
                client().build().post("/",x2).run()
                        .assertHeader("X-Content-Length").asInteger().is(3)
                        .assertHeader("X-Content-Encoding").is("identity")
@@ -122,7 +122,7 @@ public class RestClient_Body_Test {
                        .assertHeader("X-Transfer-Encoding").doesNotExist()
                ;
 
-               HttpEntity x3 = 
stringEntity("foo").contentType(contentType("text/plain")).contentEncoding(contentEncoding("identity")).chunked();
+               HttpEntity x3 = 
stringEntity("foo").contentType(contentType("text/plain")).contentEncoding(contentEncoding("identity")).chunked().build();
                client().build().post("/",x3).run()
                        .assertHeader("X-Content-Length").doesNotExist()  // 
Missing when chunked.
                        .assertHeader("X-Content-Encoding").is("identity")
@@ -130,7 +130,7 @@ public class RestClient_Body_Test {
                        .assertHeader("X-Transfer-Encoding").is("chunked")
                ;
 
-               HttpEntity x4 = stringEntity("foo", 
contentType("text/plain")).contentEncoding("identity");
+               HttpEntity x4 = stringEntity("foo", 
contentType("text/plain")).contentEncoding("identity").build();
                client().build().post("/",x4).run()
                        .assertHeader("X-Content-Length").asInteger().is(3)
                        .assertHeader("X-Content-Encoding").is("identity")
@@ -138,17 +138,17 @@ public class RestClient_Body_Test {
                        .assertHeader("X-Transfer-Encoding").doesNotExist()
                ;
 
-               HttpEntity x7 = readerEntity(new StringReader("foo"));
+               HttpEntity x7 = readerEntity(new StringReader("foo")).build();
                client().build().post("/",x7).run().assertBody().is("foo");
 
-               HttpEntity x8 = readerEntity(new StringReader("foo")).cache();
+               HttpEntity x8 = readerEntity(new 
StringReader("foo")).cached().build();
                client().build().post("/",x8).run().assertBody().is("foo");
                client().build().post("/",x8).run().assertBody().is("foo");
 
-               HttpEntity x9 = readerEntity(null);
+               HttpEntity x9 = readerEntity(null).build();
                client().build().post("/",x9).run().assertBody().isEmpty();
 
-               AbstractHttpEntity x12 = stringEntity("foo");
+               BasicHttpEntity2 x12 = stringEntity("foo").build();
                x12.assertString().is("foo");
                x12.assertBytes().asString().is("foo");
        }

Reply via email to