You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2022/09/02 21:04:17 UTC

[juneau] branch master updated: Simplify HeaderList/PartList.

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 0bedfc7d5 Simplify HeaderList/PartList.
0bedfc7d5 is described below

commit 0bedfc7d53a3ea1ca682142e742e25b7e834c888
Author: JamesBognar <ja...@salesforce.com>
AuthorDate: Fri Sep 2 17:03:15 2022 -0400

    Simplify HeaderList/PartList.
---
 .../org/apache/juneau/rest/client/RestClient.java  |   44 +-
 .../org/apache/juneau/rest/client/RestRequest.java |  163 +-
 .../apache/juneau/rest/client/RestResponse.java    |   14 +-
 .../juneau/rest/client/remote/RemoteMeta.java      |   10 +-
 .../java/org/apache/juneau/http/HttpHeaders.java   |    4 +-
 .../java/org/apache/juneau/http/HttpParts.java     |    8 +-
 .../org/apache/juneau/http/header/HeaderList.java  | 1565 +++++++------------
 .../java/org/apache/juneau/http/part/PartList.java | 1566 ++++++--------------
 .../apache/juneau/http/resource/BasicResource.java |    2 +-
 .../juneau/http/resource/HttpResourceBuilder.java  |   28 +-
 .../juneau/http/response/BasicHttpException.java   |   49 +-
 .../juneau/http/response/BasicHttpResponse.java    |   51 +-
 .../juneau/http/response/HttpExceptionBuilder.java |   29 +-
 .../juneau/http/response/HttpResponseBuilder.java  |   33 +-
 .../apache/juneau/rest/mock/MockRestClient.java    |    2 +-
 .../java/org/apache/juneau/rest/RestContext.java   |   39 +-
 .../java/org/apache/juneau/rest/RestOpContext.java |   77 +-
 .../apache/juneau/http/header/HeaderList_Test.java |  123 +-
 .../org/apache/juneau/http/part/PartList_Test.java |  123 +-
 .../remote/Remote_FormDataAnnotation_Test.java     |    8 +-
 .../http/remote/Remote_PathAnnotation_Test.java    |    8 +-
 .../http/remote/Remote_QueryAnnotation_Test.java   |    8 +-
 .../org/apache/juneau/http/remote/Remote_Test.java |    4 +-
 .../org/apache/juneau/rest/Header_Accept_Test.java |    8 +-
 .../juneau/rest/Header_ContentType_Test.java       |    8 +-
 .../juneau/rest/annotation/FormData_Test.java      |    2 +-
 .../apache/juneau/rest/annotation/Query_Test.java  |    2 +-
 .../rest/client/RestClient_BasicCalls_Test.java    |   12 +-
 .../rest/client/RestClient_FormData_Test.java      |    2 +-
 29 files changed, 1337 insertions(+), 2655 deletions(-)

diff --git a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
index 1cf51cc0e..37fbd1ffe 100644
--- a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
+++ b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
@@ -195,7 +195,7 @@ import org.apache.juneau.xml.*;
  * 		<li class='jm'>{@link RestClient#head(Object) head(uri)}
  * 		<li class='jm'>{@link RestClient#options(Object) options(uri)}
  * 		<li class='jm'>{@link RestClient#formPost(Object,Object) formPost(uri,body)} / {@link RestClient#formPost(Object) formPost(uri)}
- * 		<li class='jm'>{@link RestClient#formPostPairs(Object,Object...) formPostPairs(uri,parameters...)}
+ * 		<li class='jm'>{@link RestClient#formPostPairs(Object,String...) formPostPairs(uri,parameters...)}
  * 		<li class='jm'>{@link RestClient#request(String,Object,Object) request(method,uri,body)}
  * 	</ul>
  * </ul>
@@ -1079,8 +1079,8 @@ public class RestClient extends BeanContextable implements HttpClient, Closeable
 		private HttpClientBuilder httpClientBuilder;
 		private CloseableHttpClient httpClient;
 
-		private HeaderList.Builder headerData;
-		private PartList.Builder queryData, formData, pathData;
+		private HeaderList headerData;
+		private PartList queryData, formData, pathData;
 		private BeanCreator<RestCallHandler> callHandler;
 		private SerializerSet.Builder serializers;
 		private ParserSet.Builder parsers;
@@ -2394,7 +2394,7 @@ public class RestClient extends BeanContextable implements HttpClient, Closeable
 		 *
 		 * @return The header list builder.
 		 */
-		public final HeaderList.Builder headers() {
+		public final HeaderList headers() {
 			if (headerData == null)
 				headerData = createHeaderData();
 			return headerData;
@@ -2412,7 +2412,7 @@ public class RestClient extends BeanContextable implements HttpClient, Closeable
 		 * @return The header list builder.
 		 * @see #headers()
 		 */
-		protected HeaderList.Builder createHeaderData() {
+		protected HeaderList createHeaderData() {
 			return HeaderList.create();
 		}
 
@@ -2693,7 +2693,7 @@ public class RestClient extends BeanContextable implements HttpClient, Closeable
 		 *
 		 * @return The query data list builder.
 		 */
-		public final PartList.Builder queryData() {
+		public final PartList queryData() {
 			if (queryData == null)
 				queryData = createQueryData();
 			return queryData;
@@ -2711,7 +2711,7 @@ public class RestClient extends BeanContextable implements HttpClient, Closeable
 		 * @return The query data list builder.
 		 * @see #queryData()
 		 */
-		protected PartList.Builder createQueryData() {
+		protected PartList createQueryData() {
 			return PartList.create();
 		}
 
@@ -2851,7 +2851,7 @@ public class RestClient extends BeanContextable implements HttpClient, Closeable
 		 *
 		 * @return The form data list builder.
 		 */
-		public final PartList.Builder formData() {
+		public final PartList formData() {
 			if (formData == null)
 				formData = createFormData();
 			return formData;
@@ -2869,7 +2869,7 @@ public class RestClient extends BeanContextable implements HttpClient, Closeable
 		 * @return The query data list builder.
 		 * @see #formData()
 		 */
-		protected PartList.Builder createFormData() {
+		protected PartList createFormData() {
 			return PartList.create();
 		}
 
@@ -3009,7 +3009,7 @@ public class RestClient extends BeanContextable implements HttpClient, Closeable
 		 *
 		 * @return The form data list builder.
 		 */
-		public final PartList.Builder pathData() {
+		public final PartList pathData() {
 			if (pathData == null)
 				pathData = createPathData();
 			return pathData;
@@ -3027,7 +3027,7 @@ public class RestClient extends BeanContextable implements HttpClient, Closeable
 		 * @return The query data list builder.
 		 * @see #pathData()
 		 */
-		protected PartList.Builder createPathData() {
+		protected PartList createPathData() {
 			return PartList.create();
 		}
 
@@ -6314,8 +6314,8 @@ public class RestClient extends BeanContextable implements HttpClient, Closeable
 	// Instance
 	//-------------------------------------------------------------------------------------------------------------------
 
-	final HeaderList.Builder headerData;
-	final PartList.Builder queryData, formData, pathData;
+	final HeaderList headerData;
+	final PartList queryData, formData, pathData;
 	final CloseableHttpClient httpClient;
 
 	private final HttpClientConnectionManager connectionManager;
@@ -6367,10 +6367,10 @@ public class RestClient extends BeanContextable implements HttpClient, Closeable
 			.addBean(RestClient.class, this);
 
 		httpClient = builder.getHttpClient();
-		headerData = builder.headers().build().copy();
-		queryData = builder.queryData().build().copy();
-		formData = builder.formData().build().copy();
-		pathData = builder.pathData().build().copy();
+		headerData = builder.headers().copy();
+		queryData = builder.queryData().copy();
+		formData = builder.formData().copy();
+		pathData = builder.pathData().copy();
 		callHandler = builder.callHandler().run();
 		skipEmptyHeaderData = builder.skipEmptyHeaderData;
 		skipEmptyQueryData = builder.skipEmptyQueryData;
@@ -6879,7 +6879,7 @@ public class RestClient extends BeanContextable implements HttpClient, Closeable
 	 * 	as a parsed object.
 	 * @throws RestCallException If any authentication errors occurred.
 	 */
-	public RestRequest formPostPairs(Object uri, Object...parameters) throws RestCallException {
+	public RestRequest formPostPairs(Object uri, String...parameters) throws RestCallException {
 		return formPost(uri, partList(parameters));
 	}
 
@@ -7758,7 +7758,7 @@ public class RestClient extends BeanContextable implements HttpClient, Closeable
 	 *
 	 * @return A new builder.
 	 */
-	public HeaderList.Builder createHeaderDataBuilder() {
+	public HeaderList createHeaderData() {
 		return headerData.copy();
 	}
 
@@ -7773,7 +7773,7 @@ public class RestClient extends BeanContextable implements HttpClient, Closeable
 	 *
 	 * @return A new builder.
 	 */
-	public PartList.Builder createQueryDataBuilder() {
+	public PartList createQueryData() {
 		return queryData.copy();
 	}
 
@@ -7788,7 +7788,7 @@ public class RestClient extends BeanContextable implements HttpClient, Closeable
 	 *
 	 * @return A new builder.
 	 */
-	public PartList.Builder createFormDataBuilder() {
+	public PartList createFormData() {
 		return formData.copy();
 	}
 
@@ -7803,7 +7803,7 @@ public class RestClient extends BeanContextable implements HttpClient, Closeable
 	 *
 	 * @return A new builder.
 	 */
-	public PartList.Builder createPathDataBuilder() {
+	public PartList createPathData() {
 		return pathData.copy();
 	}
 
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 692fe1f98..44c83ad12 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
@@ -89,9 +89,6 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 	private RestResponse response;                         // The response.
 	List<RestCallInterceptor> interceptors = list();   // Used for intercepting and altering requests.
 
-	private final HeaderList.Builder headerDataBuilder;
-	private final PartList.Builder queryDataBuilder, formDataBuilder, pathDataBuilder;
-
 	private HeaderList headerData;
 	private PartList queryData, formData, pathData;
 
@@ -126,10 +123,10 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 		this.errorCodes = client.errorCodes;
 		this.uriBuilder = new URIBuilder(request.getURI());
 		this.ignoreErrors = client.ignoreErrors;
-		this.headerDataBuilder = client.createHeaderDataBuilder();
-		this.queryDataBuilder = client.createQueryDataBuilder();
-		this.formDataBuilder = client.createFormDataBuilder();
-		this.pathDataBuilder = client.createPathDataBuilder();
+		this.headerData = client.createHeaderData();
+		this.queryData = client.createQueryData();
+		this.formData = client.createFormData();
+		this.pathData = client.createPathData();
 	}
 
 	/**
@@ -715,7 +712,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 	 */
 	@Override
 	public boolean isDebug() {
-		return getHeaderList().get("Debug", Boolean.class).orElse(false);
+		return headerData.get("Debug", Boolean.class).orElse(false);
 	}
 
 	/**
@@ -766,103 +763,39 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 	// Part builders
 	//------------------------------------------------------------------------------------------------------------------
 
-	/**
-	 * Returns the builder for the header data.
-	 *
-	 * <p>
-	 * Allows you to perform operations that aren't otherwise exposed on this API such
-	 * as Prepend/Replace/Default operations.
-	 *
-	 * @return The header data builder.
-	 */
-	public HeaderList.Builder headers() {
-		headerData = null;
-		return headerDataBuilder;
-	}
-
 	/**
 	 * Returns the header data for the request.
 	 *
 	 * @return An immutable list of headers to send on the request.
 	 */
-	public HeaderList getHeaderList() {
-		if (headerData == null)
-			headerData = headerDataBuilder.build();
+	public HeaderList getHeaders() {
 		return headerData;
 	}
 
-	/**
-	 * Returns the builder for the query data.
-	 *
-	 * <p>
-	 * Allows you to perform operations that aren't otherwise exposed on this API such
-	 * as Prepend/Replace/Default operations.
-	 *
-	 * @return The query data builder.
-	 */
-	public PartList.Builder queryData() {
-		queryData = null;
-		return queryDataBuilder;
-	}
-
 	/**
 	 * Returns the query data for the request.
 	 *
 	 * @return An immutable list of query data to send on the request.
 	 */
-	public PartList getQueryDataList() {
-		if (queryData == null)
-			queryData = queryDataBuilder.build();
+	public PartList getQueryData() {
 		return queryData;
 	}
 
-	/**
-	 * Returns the builder for the form data list.
-	 *
-	 * <p>
-	 * Allows you to perform operations that aren't otherwise exposed on this API such
-	 * as Prepend/Replace/Default operations.
-	 *
-	 * @return The form data builder.
-	 */
-	public PartList.Builder formData() {
-		formData = null;
-		return formDataBuilder;
-	}
-
 	/**
 	 * Returns the form data for the request.
 	 *
 	 * @return An immutable list of form data to send on the request.
 	 */
-	public PartList getFormDataList() {
-		if (formData == null)
-			formData = formDataBuilder.build();
+	public PartList getFormData() {
 		return formData;
 	}
 
-	/**
-	 * Returns the builder for the path data.
-	 *
-	 * <p>
-	 * Allows you to perform operations that aren't otherwise exposed on this API such
-	 * as Prepend/Replace/Default operations.
-	 *
-	 * @return The path data builder.
-	 */
-	public PartList.Builder pathData() {
-		pathData = null;
-		return pathDataBuilder;
-	}
-
 	/**
 	 * Returns the path data for the request.
 	 *
 	 * @return An immutable list of path data to send on the request.
 	 */
-	public PartList getPathDataList() {
-		if (pathData == null)
-			pathData = pathDataBuilder.build();
+	public PartList getPathData() {
 		return pathData;
 	}
 
@@ -914,7 +847,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 	 */
 	@FluentSetter
 	public RestRequest headers(Header...parts) {
-		headers().append(parts);
+		headerData.append(parts);
 		return this;
 	}
 
@@ -940,7 +873,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 	 */
 	@FluentSetter
 	public RestRequest queryData(NameValuePair...parts) {
-		queryData().append(parts);
+		queryData.append(parts);
 		return this;
 	}
 
@@ -966,7 +899,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 	 */
 	@FluentSetter
 	public RestRequest formData(NameValuePair...parts) {
-		formData().append(parts);
+		formData.append(parts);
 		return this;
 	}
 
@@ -992,7 +925,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 	 */
 	@FluentSetter
 	public RestRequest pathData(NameValuePair...parts) {
-		pathData().set(parts);
+		pathData.set(parts);
 		return this;
 	}
 
@@ -1017,7 +950,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 	 */
 	@FluentSetter
 	public RestRequest header(String name, Object value) {
-		headers().append(createHeader(name, value));
+		headerData.append(createHeader(name, value));
 		return this;
 	}
 
@@ -1042,7 +975,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 	 */
 	@FluentSetter
 	public RestRequest queryData(String name, Object value) {
-		queryData().append(createPart(QUERY, name, value));
+		queryData.append(createPart(QUERY, name, value));
 		return this;
 	}
 
@@ -1067,7 +1000,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 	 */
 	@FluentSetter
 	public RestRequest formData(String name, Object value) {
-		formData().append(createPart(FORMDATA, name, value));
+		formData.append(createPart(FORMDATA, name, value));
 		return this;
 	}
 
@@ -1092,7 +1025,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 	 */
 	@FluentSetter
 	public RestRequest pathData(String name, Object value) {
-		pathData().set(createPart(PATH, name, value));
+		pathData.set(createPart(PATH, name, value));
 		return this;
 	}
 
@@ -1115,7 +1048,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 	public RestRequest headerPairs(String...pairs) {
 		if (pairs.length % 2 != 0)
 			throw new RuntimeException("Odd number of parameters passed into headerPairs(String...)");
-		HeaderList.Builder b = headers();
+		HeaderList b = headerData;
 		for (int i = 0; i < pairs.length; i+=2)
 			b.append(pairs[i], pairs[i+1]);
 		return this;
@@ -1145,7 +1078,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 	public RestRequest queryDataPairs(String...pairs) throws RestCallException {
 		if (pairs.length % 2 != 0)
 			throw new RuntimeException("Odd number of parameters passed into queryDataPairs(String...)");
-		PartList.Builder b = queryData();
+		PartList b = queryData;
 		for (int i = 0; i < pairs.length; i+=2)
 			b.append(pairs[i], pairs[i+1]);
 		return this;
@@ -1175,7 +1108,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 	public RestRequest formDataPairs(String...pairs) throws RestCallException {
 		if (pairs.length % 2 != 0)
 			throw new RuntimeException("Odd number of parameters passed into formDataPairs(String...)");
-		PartList.Builder b = formData();
+		PartList b = formData;
 		for (int i = 0; i < pairs.length; i+=2)
 			b.append(pairs[i], pairs[i+1]);
 		return this;
@@ -1207,7 +1140,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 	public RestRequest pathDataPairs(String...pairs) {
 		if (pairs.length % 2 != 0)
 			throw new RuntimeException("Odd number of parameters passed into pathDataPairs(String...)");
-		PartList.Builder b = pathData();
+		PartList b = pathData;
 		for (int i = 0; i < pairs.length; i+=2)
 			b.set(pairs[i], pairs[i+1]);
 		return this;
@@ -1241,7 +1174,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 	public RestRequest headersBean(Object value) {
 		if (! isBean(value))
 			throw new RuntimeException("Object passed into headersBean(Object) is not a bean.");
-		HeaderList.Builder b = headers();
+		HeaderList b = headerData;
 		toBeanMap(value, PropertyNamerDUCS.INSTANCE).forEach((k,v) -> b.append(createHeader(k, v)));
 		return this;
 	}
@@ -1270,7 +1203,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 	public RestRequest queryDataBean(Object value) {
 		if (! isBean(value))
 			throw new RuntimeException("Object passed into queryDataBean(Object) is not a bean.");
-		PartList.Builder b = queryData();
+		PartList b = queryData;
 		toBeanMap(value).forEach((k,v) -> b.append(createPart(QUERY, k, v)));
 		return this;
 	}
@@ -1299,7 +1232,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 	public RestRequest formDataBean(Object value) {
 		if (! isBean(value))
 			throw new RuntimeException("Object passed into formDataBean(Object) is not a bean.");
-		PartList.Builder b = formData();
+		PartList b = formData;
 		toBeanMap(value).forEach((k,v) -> b.append(createPart(FORMDATA, k, v)));
 		return this;
 	}
@@ -1328,7 +1261,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 	public RestRequest pathDataBean(Object value) {
 		if (! isBean(value))
 			throw new RuntimeException("Object passed into pathDataBean(Object) is not a bean.");
-		PartList.Builder b = pathData();
+		PartList b = pathData;
 		toBeanMap(value).forEach((k,v) -> b.set(createPart(PATH, k, v)));
 		return this;
 	}
@@ -1588,7 +1521,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 		if (skipIfEmpty)
 			l.removeIf(x -> isEmpty(x.getValue()));
 
-		headers().append(l);
+		headerData.append(l);
 
 		return this;
 	}
@@ -1625,7 +1558,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 		if (skipIfEmpty)
 			l.removeIf(x -> isEmpty(x.getValue()));
 
-		queryData().append(l);
+		queryData.append(l);
 
 		return this;
 	}
@@ -1662,7 +1595,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 		if (skipIfEmpty)
 			l.removeIf(x -> isEmpty(x.getValue()));
 
-		formData().append(l);
+		formData.append(l);
 
 		return this;
 	}
@@ -1692,7 +1625,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 			throw new BasicRuntimeException("Invalid value type for path arg ''{0}'': {1}", name, className(value));
 		}
 
-		pathData().append(l);
+		pathData.append(l);
 
 		return this;
 	}
@@ -1918,11 +1851,11 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 
 		try {
 
-			getQueryDataList().stream().map(SimpleQuery::new).filter(SimplePart::isValid).forEach(
+			queryData.stream().map(SimpleQuery::new).filter(SimplePart::isValid).forEach(
 				x -> uriBuilder.addParameter(x.name, x.value)
 			);
 
-			getPathDataList().stream().map(SimplePath::new).forEach(x ->
+			pathData.stream().map(SimplePath::new).forEach(x ->
 				{
 					String path = uriBuilder.getPath();
 					String name = x.name, value = x.value;
@@ -1941,7 +1874,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 			request.setURI(uriBuilder.build());
 
 			// Pick the serializer if it hasn't been overridden.
-			HeaderList.Builder hl = headers();
+			HeaderList hl = headerData;
 			Optional<Header> h = hl.getLast("Content-Type");
 			String contentType = h.isPresent() ? h.get().getValue() : null;
 			Serializer serializer = this.serializer;
@@ -1959,7 +1892,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 			if (accept == null && parser != null)
 				hl.set(Accept.of( parser.getPrimaryMediaType()));
 
-			getHeaderList().stream().map(SimpleHeader::new).filter(SimplePart::isValid).forEach(x -> request.addHeader(x));
+			headerData.stream().map(SimpleHeader::new).filter(SimplePart::isValid).forEach(x -> request.addHeader(x));
 
 			if (request2 == null && content != NO_BODY)
 				throw new RestCallException(null, null, "Method does not support content entity.  Method={0}, URI={1}", getMethod(), getURI());
@@ -1970,7 +1903,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 				if (content != NO_BODY) {
 					input2 = content;
 				} else {
-					input2 = new UrlEncodedFormEntity(getFormDataList().stream().map(SimpleFormData::new).filter(SimplePart::isValid).collect(toList()));
+					input2 = new UrlEncodedFormEntity(formData.stream().map(SimpleFormData::new).filter(SimplePart::isValid).collect(toList()));
 				}
 
 				if (input2 instanceof Supplier)
@@ -2375,7 +2308,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 	 */
 	@Override /* HttpMessage */
 	public boolean containsHeader(String name) {
-		return getHeaderList().contains(name);
+		return headerData.contains(name);
 	}
 
 	/**
@@ -2389,7 +2322,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 	 */
 	@Override /* HttpMessage */
 	public Header[] getHeaders(String name) {
-		return getHeaderList().getAll(name);
+		return headerData.getAll(name);
 	}
 
 	/**
@@ -2404,7 +2337,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 	 */
 	@Override /* HttpMessage */
 	public Header getFirstHeader(String name) {
-		return getHeaderList().getFirst(name).orElse(null);
+		return headerData.getFirst(name).orElse(null);
 	}
 
 	/**
@@ -2419,7 +2352,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 	 */
 	@Override /* HttpMessage */
 	public Header getLastHeader(String name) {
-		return getHeaderList().getLast(name).orElse(null);
+		return headerData.getLast(name).orElse(null);
 	}
 
 	/**
@@ -2431,7 +2364,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 	 */
 	@Override /* HttpMessage */
 	public Header[] getAllHeaders() {
-		return getHeaderList().getAll();
+		return headerData.getAll();
 	}
 
 	/**
@@ -2447,7 +2380,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 	 */
 	@Override /* HttpMessage */
 	public void addHeader(Header header) {
-		headers().append(header);
+		headerData.append(header);
 	}
 
 	/**
@@ -2464,7 +2397,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 	 */
 	@Override /* HttpMessage */
 	public void addHeader(String name, String value) {
-		headers().append(stringHeader(name, value));
+		headerData.append(stringHeader(name, value));
 	}
 
 	/**
@@ -2476,7 +2409,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 	 */
 	@Override /* HttpMessage */
 	public void setHeader(Header header) {
-		headers().set(header);
+		headerData.set(header);
 	}
 
 	/**
@@ -2489,7 +2422,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 	 */
 	@Override /* HttpMessage */
 	public void setHeader(String name, String value) {
-		headers().set(stringHeader(name, value));
+		headerData.set(stringHeader(name, value));
 	}
 
 	/**
@@ -2499,7 +2432,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 	 */
 	@Override /* HttpMessage */
 	public void setHeaders(Header[] headers) {
-		headers().set(headers);
+		headerData.set(headers);
 	}
 
 	/**
@@ -2509,7 +2442,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 	 */
 	@Override /* HttpMessage */
 	public void removeHeader(Header header) {
-		headers().remove(header);
+		headerData.remove(header);
 	}
 
 	/**
@@ -2519,7 +2452,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 	 */
 	@Override /* HttpMessage */
 	public void removeHeaders(String name) {
-		headers().remove(name);
+		headerData.remove(name);
 	}
 
 	/**
@@ -2529,7 +2462,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 	 */
 	@Override /* HttpMessage */
 	public HeaderIterator headerIterator() {
-		return getHeaderList().headerIterator();
+		return headerData.headerIterator();
 	}
 
 	/**
@@ -2540,7 +2473,7 @@ public class RestRequest extends BeanSession implements HttpUriRequest, Configur
 	 */
 	@Override /* HttpMessage */
 	public HeaderIterator headerIterator(String name) {
-		return getHeaderList().headerIterator(name);
+		return headerData.headerIterator(name);
 	}
 
 	/**
diff --git a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestResponse.java b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestResponse.java
index ab81d57ad..e9e2dc61d 100644
--- a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestResponse.java
+++ b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestResponse.java
@@ -719,7 +719,7 @@ public class RestResponse implements HttpResponse {
 	 */
 	@Override /* HttpMessage */
 	public void addHeader(Header header) {
-		headers = headers.copy().append(header).build();
+		headers.append(header);
 	}
 
 	/**
@@ -732,7 +732,7 @@ public class RestResponse implements HttpResponse {
 	 */
 	@Override /* HttpMessage */
 	public void addHeader(String name, String value) {
-		headers = headers.copy().append(name, value).build();
+		headers.append(name, value);
 	}
 
 	/**
@@ -744,7 +744,7 @@ public class RestResponse implements HttpResponse {
 	 */
 	@Override /* HttpMessage */
 	public void setHeader(Header header) {
-		headers = headers.copy().set(header).build();
+		headers.set(header);
 	}
 
 	/**
@@ -757,7 +757,7 @@ public class RestResponse implements HttpResponse {
 	 */
 	@Override /* HttpMessage */
 	public void setHeader(String name, String value) {
-		headers = headers.copy().set(name, value).build();
+		headers.set(name, value);
 	}
 
 	/**
@@ -777,7 +777,7 @@ public class RestResponse implements HttpResponse {
 	 */
 	@Override /* HttpMessage */
 	public void removeHeader(Header header) {
-		headers = headers.copy().remove(header).build();
+		headers.remove(header);
 	}
 
 	/**
@@ -787,7 +787,7 @@ public class RestResponse implements HttpResponse {
 	 */
 	@Override /* HttpMessage */
 	public void removeHeaders(String name) {
-		headers = headers.copy().remove(name).build();
+		headers.remove(name);
 	}
 
 	/**
@@ -851,7 +851,7 @@ public class RestResponse implements HttpResponse {
 				sb.append("\n=== REQUEST ===\n");
 				sb.append(request.getMethod()).append(" ").append(request.getURI());
 				sb.append("\n---request headers---");
-				request.getHeaderList().forEach(x -> sb.append("\n\t").append(x));
+				request.getHeaders().forEach(x -> sb.append("\n\t").append(x));
 				if (request.hasHttpEntity()) {
 					sb.append("\n---request entity---");
 					HttpEntity e = request.getHttpEntity();
diff --git a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteMeta.java b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteMeta.java
index eedc2e97a..11aaeb351 100644
--- a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteMeta.java
+++ b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteMeta.java
@@ -55,20 +55,20 @@ public class RemoteMeta {
 		List<Remote> remotes = ci.getAnnotations(Remote.class);
 
 		String versionHeader = "Client-Version", clientVersion = null;
-		HeaderList.Builder headersBuilder = HeaderList.create().resolving();
+		HeaderList headers = HeaderList.create().resolving();
 
 		for (Remote r : remotes) {
 			if (isNotEmpty(r.path()))
 				path = trimSlashes(resolve(r.path()));
 			for (String h : r.headers())
-				headersBuilder.append(stringHeader(resolve(h)));
+				headers.append(stringHeader(resolve(h)));
 			if (isNotEmpty(r.version()))
 				clientVersion = resolve(r.version());
 			if (isNotEmpty(r.versionHeader()))
 				versionHeader = resolve(r.versionHeader());
 			if (isNotVoid(r.headerList())) {
 				try {
-					headersBuilder.append(r.headerList().newInstance().getAll());
+					headers.append(r.headerList().newInstance().getAll());
 				} catch (Exception e) {
 					throw new BasicRuntimeException(e, "Could not instantiate HeaderSupplier class");
 				}
@@ -76,7 +76,7 @@ public class RemoteMeta {
 		}
 
 		if (clientVersion != null)
-			headersBuilder.append(stringHeader(versionHeader, clientVersion));
+			headers.append(stringHeader(versionHeader, clientVersion));
 
 		Map<Method,RemoteOperationMeta> operations = map();
 		String path2 = path;
@@ -86,7 +86,7 @@ public class RemoteMeta {
 		);
 
 		this.operations = unmodifiable(operations);
-		this.headers = headersBuilder.build();
+		this.headers = headers;
 	}
 
 	/**
diff --git a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/HttpHeaders.java b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/HttpHeaders.java
index 515cd6689..c4a5f9345 100644
--- a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/HttpHeaders.java
+++ b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/HttpHeaders.java
@@ -2603,11 +2603,11 @@ public class HttpHeaders {
 	}
 
 	/**
-	 * Instantiates a new {@link org.apache.juneau.http.header.HeaderList.Builder}.
+	 * Instantiates a new {@link org.apache.juneau.http.header.HeaderList}.
 	 *
 	 * @return A new empty builder.
 	 */
-	public static final HeaderList.Builder headerList() {
+	public static final HeaderList headerList() {
 		return HeaderList.create();
 	}
 
diff --git a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/HttpParts.java b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/HttpParts.java
index 44c1e2989..b19070cbe 100644
--- a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/HttpParts.java
+++ b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/HttpParts.java
@@ -374,11 +374,11 @@ public class HttpParts {
 	}
 
 	/**
-	 * Instantiates a new {@link org.apache.juneau.http.part.PartList.Builder}.
+	 * Instantiates a new {@link org.apache.juneau.http.part.PartList}.
 	 *
-	 * @return A new empty builder.
+	 * @return A new part list.
 	 */
-	public static final PartList.Builder partList() {
+	public static final PartList partList() {
 		return PartList.create();
 	}
 
@@ -411,7 +411,7 @@ public class HttpParts {
 	 * @throws RuntimeException If odd number of parameters were specified.
 	 * @return A new instance.
 	 */
-	public static PartList partList(Object...pairs) {
+	public static PartList partList(String...pairs) {
 		return PartList.ofPairs(pairs);
 	}
 
diff --git a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/header/HeaderList.java b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/header/HeaderList.java
index 6bfc7db6b..5681252c9 100644
--- a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/header/HeaderList.java
+++ b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/header/HeaderList.java
@@ -23,23 +23,19 @@ import java.util.stream.*;
 
 import org.apache.http.*;
 import org.apache.http.util.*;
-import org.apache.juneau.*;
-import org.apache.juneau.collections.*;
-import org.apache.juneau.cp.*;
 import org.apache.juneau.http.HttpHeaders;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.svl.*;
 
 /**
- * An immutable list of HTTP headers.
+ * A simple list of HTTP headers with various convenience methods.
  *
  * <h5 class='figure'>Example</h5>
  * <p class='bjava'>
  * 	HeaderList <jv>headers</jv> = HeaderList
  * 		.<jsm>create</jsm>()
  * 		.append(Accept.<jsm>of</jsm>(<js>"text/xml"</js>))
- * 		.append(<js>"Content-Type"</js>, ()-&gt;<jsm>getDynamicContentTypeFromSomewhere</jsm>())
- * 		.build();
+ * 		.append(<js>"Content-Type"</js>, ()-&gt;<jsm>getDynamicContentTypeFromSomewhere</jsm>());
  * </p>
  *
  * <p>
@@ -49,15 +45,6 @@ import org.apache.juneau.svl.*;
  * </p>
  *
  * <p>
- * Header lists are immutable, but can be appended to using the {@link #copy()} method:
- * <p class='bjava'>
- * 	<jv>headers</jv> = <jv>headers</jv>
- * 		.copy()
- * 		.append(AcceptEncoding.<jsm>of</jsm>(<js>"identity"</js>))
- * 		.build();
- * </p>
- *
- * <p>
  * Static methods are provided on {@link HttpHeaders} to further simplify creation of header lists.
  * <p class='bjava'>
  * 	<jk>import static</jk> org.apache.juneau.http.HttpHeaders.*;
@@ -65,139 +52,31 @@ import org.apache.juneau.svl.*;
  * 	HeaderList <jv>headers</jv> = <jsm>headerList</jsm>(<jsm>accept</jsm>(<js>"text/xml"</js>), <jsm>contentType</jsm>(<js>"text/xml"</js>));
  * </p>
  *
- * <p>
- * The builder class supports setting default header values (i.e. add a header to the list if it isn't otherwise in the list).
- * Note that this is different from simply setting a value twice as using default values will not overwrite existing
- * headers.
- * <br>The following example notes the distinction:
- *
- * <p class='bjava'>
- * 	<jv>headers</jv> = HeaderList
- * 		.<jsm>create</jsm>()
- * 		.set(Accept.<jsf>TEXT_PLAIN</jsf>)
- * 		.set(Accept.<jsf>TEXT_XML</jsf>)
- * 		.build();
- * 	<jsm>assertObject</jsm>(<jv>headers</jv>).isString(<js>"[Accept: text/xml]"</js>);
- *
- * 	<jv>headers</jv> = HeaderList
- * 		.create()
- * 		.set(Accept.<jsf>TEXT_PLAIN</jsf>)
- * 		.setDefault(Accept.<jsf>TEXT_XML</jsf>)
- * 		.build();
- * 	<jsm>assertObject</jsm>(<jv>headers</jv>).isString(<js>"[Accept: text/plain]"</js>);
- * </p>
- *
- * <p>
- * Various methods are provided for iterating over the headers in this list to avoid array copies.
- * <ul class='javatree'>
- * 	<li class='jm'>{@link #forEach(Consumer)} / {@link #forEach(String,Consumer)} / {@link #forEach(Predicate,Consumer)} - Use consumers to process headers.
- * 	<li class='jm'>{@link #headerIterator()} / {@link #headerIterator(String)} - Use an {@link HeaderIterator} to process headers.
- * 	<li class='jm'>{@link #stream()} / {@link #stream(String)} - Use a stream.
- * </ul>
- * <p>
- * In general, try to use these over the {@link #getAll()}/{@link #getAll(String)} methods that require array copies.
- *
- * <p>
- * The {@link #get(String)} method is special in that it will collapse multiple headers with the same name into
- * a single comma-delimited list (see <a href='https://tools.ietf.org/html/rfc2616#section-4.2'>RFC 2616 Section 4.2</a> for rules).
- *
- * <p>
- * The {@link #get(Class)} and {@link #get(String, Class)} methods are provided for working with {@link org.apache.juneau.http.annotation.Header}-annotated
- * beans.
- *
- * <h5 class='figure'>Example</h5>
- * <p class='bjava'>
- * 	ContentType <jv>contentType</jv> = <jv>headers</jv>.get(ContentType.<jk>class</jk>);
- * </p>
- *
- * <p>
- * By default, header names are treated as case-insensitive.  This can be changed using the {@link HeaderList.Builder#caseSensitive()}
- * method.
- *
- * <p>
- * A {@link VarResolver} can be associated with this builder to create header values with embedded variables that
- * are resolved at runtime.
- *
- * <h5 class='figure'>Example</h5>
- * <p class='bjava'>
- * 	<jc>// Create a header list with dynamically-resolving values pulled from a system property.</jc>
- *
- * 	System.<jsm>setProperty</jsm>(<js>"foo"</js>, <js>"bar"</js>);
- *
- * 	HeaderList <jv>headers</jv> = HeaderList
- * 		.<jsm>create</jsm>()
- * 		.resolving()
- * 		.append(<js>"X1"</js>, <js>"$S{foo}"</js>)
- * 		.append(<js>"X2"</js>, ()-&gt;<js>"$S{foo}"</js>)
- * 		.build();
- *
- * 	<jsm>assertObject</jsm>(<jv>headers</jv>).isString(<js>"[X1: bar, X2: bar]"</js>);
- * </p>
- *
- * <p>
- * The {@link HeaderList} object can be extended to defined pre-packaged lists of headers which can be used in various
- * annotations throughout the framework.
- *
- * <h5 class='figure'>Example</h5>
- * <p class='bjava'>
- * 	<jc>// A predefined list of headers.</jc>
- * 	<jk>public class</jk> MyHeaderList <jk>extends</jk> HeaderList {
- * 		<jk>public</jk> MyHeaderList() {
- * 			<jk>super</jk>(Accept.<jsf>TEXT_XML</jsf>, ContentType.<jsf>TEXT_XML</jsf>);
- * 		}
- * 	}
- *
- * 	<jc>// Use it on a remote proxy to add headers on all requests.</jc>
- * 	<ja>@Remote</ja>(path=<js>"/petstore"</js>, headerList=MyHeaderList.<jk>class</jk>)
- * 	<jk>public interface</jk> PetStore {
- *
- * 		<ja>@RemotePost</ja>(<js>"/pets"</js>)
- * 		Pet addPet(
- * 			<ja>@Content</ja> CreatePet <jv>createPet</jv>,
- * 			<ja>@Header</ja>(<js>"E-Tag"</js>) UUID <jv>etag</jv>,
- * 			<ja>@Query</ja>(<js>"debug"</js>) <jk>boolean</jk> <jv>debug</jv>
- * 		);
- * 	}
- * </p>
- *
- * <ul class='notes'>
- * 	<li class='note'>This class is thread safe.
- * </ul>
- *
  * <ul class='seealso'>
  * 	<li class='link'>{@doc juneau-rest-common}
  * 	<li class='extlink'>{@source}
  * </ul>
  */
-public class HeaderList extends ControlledArrayList<Header>{
+public class HeaderList extends ArrayList<Header> {
+
+	private static final long serialVersionUID = 1L;
 
 	//-----------------------------------------------------------------------------------------------------------------
 	// Static
 	//-----------------------------------------------------------------------------------------------------------------
 
-	private static final long serialVersionUID = 1L;
-	private static final Header[] EMPTY_ARRAY = new Header[0];
-	private static final String[] EMPTY_STRING_ARRAY = new String[0];
-	private static final Predicate<Header> NOT_NULL = x -> x != null;
-
-	/** Represents no header supplier in annotations. */
+	/** Represents no header list in annotations. */
 	public static final class Void extends HeaderList {
-		Void() {
-			super(false);
-		}
 		private static final long serialVersionUID = 1L;
 	}
 
-	/** Predefined instance. */
-	public static final HeaderList EMPTY = new HeaderList(false);
-
 	/**
-	 * Instantiates a new builder for this bean.
+	 * Instantiates a new list.
 	 *
-	 * @return A new builder.
+	 * @return A new list.
 	 */
-	public static Builder create() {
-		return new Builder();
+	public static HeaderList create() {
+		return new HeaderList();
 	}
 
 	/**
@@ -210,7 +89,7 @@ public class HeaderList extends ControlledArrayList<Header>{
 	 * @return A new unmodifiable instance, never <jk>null</jk>.
 	 */
 	public static HeaderList of(List<Header> headers) {
-		return headers == null || headers.isEmpty() ? EMPTY : new HeaderList(true, headers);
+		return new HeaderList().append(headers);
 	}
 
 	/**
@@ -222,7 +101,7 @@ public class HeaderList extends ControlledArrayList<Header>{
 	 * @return A new unmodifiable instance, never <jk>null</jk>.
 	 */
 	public static HeaderList of(Header...headers) {
-		return headers == null || headers.length == 0 ? EMPTY : new HeaderList(true, headers);
+		return new HeaderList().append(headers);
 	}
 
 	/**
@@ -240,959 +119,523 @@ public class HeaderList extends ControlledArrayList<Header>{
 	 * @return A new instance.
 	 */
 	public static HeaderList ofPairs(String...pairs) {
-		if (pairs == null || pairs.length == 0)
-			return EMPTY;
+		HeaderList x = new HeaderList();
+		if (pairs == null)
+			pairs = new String[0];
 		if (pairs.length % 2 != 0)
 			throw new RuntimeException("Odd number of parameters passed into HeaderList.ofPairs()");
-		ArrayBuilder<Header> b = ArrayBuilder.of(Header.class).filter(NOT_NULL).size(pairs.length / 2);
 		for (int i = 0; i < pairs.length; i+=2)
-			b.add(BasicHeader.of(pairs[i], pairs[i+1]));
-		return new HeaderList(true, b.orElse(EMPTY_ARRAY));
+			x.add(BasicHeader.of(pairs[i], pairs[i+1]));
+		return x;
 	}
 
 	//-----------------------------------------------------------------------------------------------------------------
-	// Builder
+	// Instance
 	//-----------------------------------------------------------------------------------------------------------------
 
+	private VarResolver varResolver;
+	boolean caseSensitive = false;
+
 	/**
-	 * Builder class.
+	 * Constructor.
 	 */
-	@FluentSetters
-	public static class Builder extends BeanBuilder<HeaderList> {
-
-		final List<Header> entries;
-		List<Header> defaultEntries;
-		private VarResolver varResolver;
-		boolean caseSensitive = false, unmodifiable = false;
-
-		/**
-		 * Constructor.
-		 */
-		protected Builder() {
-			super(HeaderList.class, BeanStore.INSTANCE);
-			entries = list();
-		}
-
-		/**
-		 * Copy constructor.
-		 *
-		 * @param copyFrom The bean to copy.
-		 */
-		protected Builder(HeaderList copyFrom) {
-			super(copyFrom.getClass(), BeanStore.INSTANCE);
-			entries = copyOf(copyFrom);
-			caseSensitive = copyFrom.caseSensitive;
-			unmodifiable = false;
-		}
-
-		/**
-		 * Copy constructor.
-		 *
-		 * @param copyFrom The builder to copy.
-		 */
-		protected Builder(Builder copyFrom) {
-			super(copyFrom);
-			entries = copyOf(copyFrom.entries);
-			defaultEntries = copyOf(copyFrom.defaultEntries);
-			varResolver = copyFrom.varResolver;
-			caseSensitive = copyFrom.caseSensitive;
-			unmodifiable = copyFrom.unmodifiable;
-		}
-
-		@Override /* BeanBuilder */
-		protected HeaderList buildDefault() {
-			return entries.isEmpty() && defaultEntries == null ? EMPTY : new HeaderList(this);
-		}
-
-		/**
-		 * Makes a copy of this builder.
-		 *
-		 * @return A new copy of this builder.
-		 */
-		public Builder copy() {
-			return new Builder(this);
-		}
-
-		//-------------------------------------------------------------------------------------------------------------
-		// Properties
-		//-------------------------------------------------------------------------------------------------------------
-
-		/**
-		 * Allows header values to contain SVL variables.
-		 *
-		 * <p>
-		 * Resolves variables in header values when using the following methods:
-		 * <ul>
-		 * 	<li class='jm'>{@link #append(String, Object) append(String,Object)}
-		 * 	<li class='jm'>{@link #append(String, Supplier) append(String,Supplier&lt;?&gt;)}
-		 * 	<li class='jm'>{@link #prepend(String, Object) prepend(String,Object)}
-		 * 	<li class='jm'>{@link #prepend(String, Supplier) prepend(String,Supplier&lt;?&gt;)}
-		 * 	<li class='jm'>{@link #set(String, Object) set(String,Object)}
-		 * 	<li class='jm'>{@link #set(String, Supplier) set(String,Supplier&lt;?&gt;)}
-		 * 	<li class='jm'>{@link #setDefault(String, Object) set(String,Object)}
-		 * 	<li class='jm'>{@link #setDefault(String, Supplier) set(String,Supplier&lt;?&gt;)}
-		 * </ul>
-		 *
-		 * <p>
-		 * Uses {@link VarResolver#DEFAULT} to resolve variables.
-		 *
-		 * @return This object.
-		 */
-		public Builder resolving() {
-			return resolving(VarResolver.DEFAULT);
-		}
-
-		/**
-		 * Allows header values to contain SVL variables.
-		 *
-		 * <p>
-		 * Resolves variables in header values when using the following methods:
-		 * <ul>
-		 * 	<li class='jm'>{@link #append(String, Object) append(String,Object)}
-		 * 	<li class='jm'>{@link #append(String, Supplier) append(String,Supplier&lt;?&gt;)}
-		 * 	<li class='jm'>{@link #prepend(String, Object) prepend(String,Object)}
-		 * 	<li class='jm'>{@link #prepend(String, Supplier) prepend(String,Supplier&lt;?&gt;)}
-		 * 	<li class='jm'>{@link #set(String, Object) set(String,Object)}
-		 * 	<li class='jm'>{@link #set(String, Supplier) set(String,Supplier&lt;?&gt;)}
-		 * 	<li class='jm'>{@link #setDefault(String, Object) set(String,Object)}
-		 * 	<li class='jm'>{@link #setDefault(String, Supplier) set(String,Supplier&lt;?&gt;)}
-		 * </ul>
-		 *
-		 * @param varResolver The variable resolver to use for resolving variables.
-		 * @return This object.
-		 */
-		public Builder resolving(VarResolver varResolver) {
-			this.varResolver = varResolver;
-			return this;
-		}
+	public HeaderList() {
+	}
 
-		/**
-		 * Specifies that the headers in this builder should be treated as case-sensitive.
-		 *
-		 * <p>
-		 * The default behavior is case-insensitive.
-		 *
-		 * @return This object.
-		 */
-		public Builder caseSensitive() {
-			caseSensitive = true;
-			return this;
-		}
+	/**
+	 * Copy constructor.
+	 *
+	 * @param copyFrom The bean to copy.
+	 */
+	protected HeaderList(HeaderList copyFrom) {
+		super(copyFrom);
+		caseSensitive = copyFrom.caseSensitive;
+	}
 
-		/**
-		 * Specifies that the resulting list should be unmodifiable.
-		 *
-		 * <p>
-		 * The default behavior is modifiable.
-		 *
-		 * @return This object.
-		 */
-		public Builder unmodifiable() {
-			unmodifiable = true;
-			return this;
-		}
+	/**
+	 * Makes a copy of this list.
+	 *
+	 * @return A new copy of this list.
+	 */
+	public HeaderList copy() {
+		return new HeaderList(this);
+	}
 
-		/**
-		 * Removes any headers already in this builder.
-		 *
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder clear() {
-			entries.clear();
-			return this;
-		}
+	/**
+	 * Adds a collection of default headers.
+	 *
+	 * <p>
+	 * Default headers are set if they're not already in the list.
+	 *
+	 * @param headers The list of default headers.
+	 * @return This object.
+	 */
+	public HeaderList setDefault(List<Header> headers) {
+		if (headers != null)
+			headers.stream().filter(x -> x != null && ! contains(x.getName())).forEach(x -> set(x));
+		return this;
+	}
 
-		/**
-		 * Adds the specified header to the end of the headers in this builder.
-		 *
-		 * @param value The header to add.  <jk>null</jk> values are ignored.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder append(Header value) {
-			if (value != null)
-				entries.add(value);
-			return this;
-		}
+	/**
+	 * Replaces the first occurrence of the headers with the same name.
+	 *
+	 * @param name The header name.
+	 * @param value The header value.
+	 * @return This object.
+	 */
+	public HeaderList setDefault(String name, Object value) {
+		return setDefault(createPart(name, value));
+	}
 
-		/**
-		 * Appends the specified header to the end of this builder.
-		 *
-		 * <p>
-		 * The header is added as a {@link BasicHeader}.
-		 *
-		 * @param name The header name.
-		 * @param value The header value.
-		 * @return This object.
-		 */
-		public Builder append(String name, Object value) {
-			return append(createHeader(name, value));
-		}
+	/**
+	 * Replaces the first occurrence of the headers with the same name.
+	 *
+	 * @param name The header name.
+	 * @param value The header value.
+	 * @return This object.
+	 */
+	public HeaderList setDefault(String name, Supplier<?> value) {
+		return setDefault(createPart(name, value));
+	}
 
-		/**
-		 * Appends the specified header to the end of this builder using a value supplier.
-		 *
-		 * <p>
-		 * The header is added as a {@link BasicHeader}.
-		 *
-		 * <p>
-		 * Value is re-evaluated on each call to {@link BasicHeader#getValue()}.
-		 *
-		 * @param name The header name.
-		 * @param value The header value supplier.
-		 * @return This object.
-		 */
-		public Builder append(String name, Supplier<?> value) {
-			return append(createHeader(name, value));
-		}
+	/**
+	 * Makes a copy of this list of headers and adds a collection of default headers.
+	 *
+	 * <p>
+	 * Default headers are set if they're not already in the list.
+	 *
+	 * @param headers The list of default headers.
+	 * @return A new list, or the same list if the headers were empty.
+	 */
+	public HeaderList setDefault(Header...headers) {
+		if (headers != null)
+			setDefault(Arrays.asList(headers));
+		return this;
+	}
 
-		/**
-		 * Adds the specified headers to the end of the headers in this builder.
-		 *
-		 * @param values The headers to add.  <jk>null</jk> values are ignored.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder append(Header...values) {
-			if (values != null)
-				for (int i = 0; i < values.length; i++)
-					append(values[i]);
-			return this;
-		}
 
-		/**
-		 * Adds the specified headers to the end of the headers in this builder.
-		 *
-		 * @param values The headers to add.  <jk>null</jk> values are ignored.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder append(List<Header> values) {
-			if (values != null)
-				for (int i = 0, j = values.size(); i < j; i++) /* See HTTPCORE-361 */
-					append(values.get(i));
-			return this;
-		}
+	//-------------------------------------------------------------------------------------------------------------
+	// Properties
+	//-------------------------------------------------------------------------------------------------------------
 
-		/**
-		 * Adds the specified header to the beginning of the headers in this builder.
-		 *
-		 * @param value The header to add.  <jk>null</jk> values are ignored.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder prepend(Header value) {
-			if (value != null)
-				entries.add(0, value);
-			return this;
-		}
+	/**
+	 * Allows header values to contain SVL variables.
+	 *
+	 * <p>
+	 * Resolves variables in header values when using the following methods:
+	 * <ul>
+	 * 	<li class='jm'>{@link #append(String, Object) append(String,Object)}
+	 * 	<li class='jm'>{@link #append(String, Supplier) append(String,Supplier&lt;?&gt;)}
+	 * 	<li class='jm'>{@link #prepend(String, Object) prepend(String,Object)}
+	 * 	<li class='jm'>{@link #prepend(String, Supplier) prepend(String,Supplier&lt;?&gt;)}
+	 * 	<li class='jm'>{@link #set(String, Object) set(String,Object)}
+	 * 	<li class='jm'>{@link #set(String, Supplier) set(String,Supplier&lt;?&gt;)}
+	 * </ul>
+	 *
+	 * <p>
+	 * Uses {@link VarResolver#DEFAULT} to resolve variables.
+	 *
+	 * @return This object.
+	 */
+	public HeaderList resolving() {
+		return resolving(VarResolver.DEFAULT);
+	}
 
-		/**
-		 * Appends the specified header to the beginning of this builder.
-		 *
-		 * <p>
-		 * The header is added as a {@link BasicHeader}.
-		 *
-		 * @param name The header name.
-		 * @param value The header value.
-		 * @return This object.
-		 */
-		public Builder prepend(String name, Object value) {
-			return prepend(createHeader(name, value));
-		}
+	/**
+	 * Allows header values to contain SVL variables.
+	 *
+	 * <p>
+	 * Resolves variables in header values when using the following methods:
+	 * <ul>
+	 * 	<li class='jm'>{@link #append(String, Object) append(String,Object)}
+	 * 	<li class='jm'>{@link #append(String, Supplier) append(String,Supplier&lt;?&gt;)}
+	 * 	<li class='jm'>{@link #prepend(String, Object) prepend(String,Object)}
+	 * 	<li class='jm'>{@link #prepend(String, Supplier) prepend(String,Supplier&lt;?&gt;)}
+	 * 	<li class='jm'>{@link #set(String, Object) set(String,Object)}
+	 * 	<li class='jm'>{@link #set(String, Supplier) set(String,Supplier&lt;?&gt;)}
+	 * </ul>
+	 *
+	 * @param varResolver The variable resolver to use for resolving variables.
+	 * @return This object.
+	 */
+	public HeaderList resolving(VarResolver varResolver) {
+		this.varResolver = varResolver;
+		return this;
+	}
 
-		/**
-		 * Appends the specified header to the beginning of this builder using a value supplier.
-		 *
-		 * <p>
-		 * The header is added as a {@link BasicHeader}.
-		 *
-		 * <p>
-		 * Value is re-evaluated on each call to {@link BasicHeader#getValue()}.
-		 *
-		 * @param name The header name.
-		 * @param value The header value supplier.
-		 * @return This object.
-		 */
-		public Builder prepend(String name, Supplier<?> value) {
-			return prepend(createHeader(name, value));
-		}
+	/**
+	 * Specifies that the headers in this list should be treated as case-sensitive.
+	 *
+	 * <p>
+	 * The default behavior is case-insensitive.
+	 *
+	 * @param value The new value for this setting.
+	 * @return This object.
+	 */
+	public HeaderList caseSensitive(boolean value) {
+		caseSensitive = value;
+		return this;
+	}
 
-		/**
-		 * Adds the specified headers to the beginning of the headers in this builder.
-		 *
-		 * @param values The headers to add.  <jk>null</jk> values are ignored.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder prepend(Header...values) {
-			if (values != null)
-				prepend(alist(values));
-			return this;
-		}
+	/**
+	 * Adds the specified header to the end of the headers in this list.
+	 *
+	 * @param value The header to add.  <jk>null</jk> values are ignored.
+	 * @return This object.
+	 */
+	@FluentSetter
+	public HeaderList append(Header value) {
+		if (value != null)
+			add(value);
+		return this;
+	}
 
-		/**
-		 * Adds the specified headers to the beginning of the headers in this builder.
-		 *
-		 * @param values The headers to add.  <jk>null</jk> values are ignored.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder prepend(List<Header> values) {
-			if (values != null)
-				entries.addAll(0, values);
-			return this;
-		}
+	/**
+	 * Appends the specified header to the end of this list.
+	 *
+	 * <p>
+	 * The header is added as a {@link BasicHeader}.
+	 *
+	 * @param name The header name.
+	 * @param value The header value.
+	 * @return This object.
+	 */
+	public HeaderList append(String name, Object value) {
+		return append(createPart(name, value));
+	}
 
-		/**
-		 * Removes the specified header from this builder.
-		 *
-		 * @param value The header to remove.  <jk>null</jk> values are ignored.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder remove(Header value) {
-			if (value != null)
-				entries.remove(value);
-			return this;
-		}
+	/**
+	 * Appends the specified header to the end of this list using a value supplier.
+	 *
+	 * <p>
+	 * The header is added as a {@link BasicHeader}.
+	 *
+	 * <p>
+	 * Value is re-evaluated on each call to {@link BasicHeader#getValue()}.
+	 *
+	 * @param name The header name.
+	 * @param value The header value supplier.
+	 * @return This object.
+	 */
+	public HeaderList append(String name, Supplier<?> value) {
+		return append(createPart(name, value));
+	}
 
-		/**
-		 * Removes the specified headers from this builder.
-		 *
-		 * @param values The headers to remove.  <jk>null</jk> values are ignored.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder remove(Header...values) {
+	/**
+	 * Adds the specified headers to the end of the headers in this list.
+	 *
+	 * @param values The headers to add.  <jk>null</jk> values are ignored.
+	 * @return This object.
+	 */
+	@FluentSetter
+	public HeaderList append(Header...values) {
+		if (values != null)
 			for (int i = 0; i < values.length; i++)
-				remove(values[i]);
-			return this;
-		}
-
-		/**
-		 * Removes the specified headers from this builder.
-		 *
-		 * @param values The headers to remove.  <jk>null</jk> values are ignored.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder remove(List<Header> values) {
-			if (values != null)
-				values.forEach(x -> remove(x));
-			return this;
-		}
-
-		/**
-		 * Removes the header with the specified name from this builder.
-		 *
-		 * @param name The header name.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder remove(String name) {
-			for (int i = 0; i < entries.size(); i++) /* See HTTPCORE-361 */
-				if (eq(entries.get(i).getName(), name))
-					entries.remove(i--);
-			return this;
-		}
-
-		/**
-		 * Removes the header with the specified name from this builder.
-		 *
-		 * @param names The header name.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder remove(String...names) {
-			if (names != null)
-				for (int i = 0; i < names.length; i++)
-					remove(names[i]);
-			return this;
-		}
-
-		/**
-		 * Adds or replaces the header(s) with the same name.
-		 *
-		 * <p>
-		 * If no header with the same name is found the given header is added to the end of the list.
-		 *
-		 * @param value The headers to replace.  <jk>null</jk> values are ignored.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder set(Header value) {
-			if (value != null) {
-				boolean replaced = false;
-				for (int i = 0, j = entries.size(); i < j; i++) {
-					Header x = entries.get(i);
-					if (eq(x.getName(), value.getName())) {
-						if (replaced) {
-							entries.remove(i);
-							j--;
-						} else {
-							entries.set(i, value);
-							replaced = true;
-						}
-					}
-				}
-
-				if (! replaced)
-					entries.add(value);
-			}
-
-			return this;
-		}
+				if (values[i] != null)
+					append(values[i]);
+		return this;
+	}
 
-		/**
-		 * Adds or replaces the header(s) with the same name.
-		 *
-		 * <p>
-		 * If no header with the same name is found the given header is added to the end of the list.
-		 *
-		 * @param values The headers to replace.  <jk>null</jk> values are ignored.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder set(Header...values) {
-			if (values != null)
-				set(alist(values));
-			return this;
-		}
+	/**
+	 * Adds the specified headers to the end of the headers in this list.
+	 *
+	 * @param values The headers to add.  <jk>null</jk> values are ignored.
+	 * @return This object.
+	 */
+	@FluentSetter
+	public HeaderList append(List<Header> values) {
+		if (values != null)
+			values.forEach(x -> append(x));
+		return this;
+	}
 
-		/**
-		 * Replaces the first occurrence of the headers with the same name.
-		 *
-		 * @param name The header name.
-		 * @param value The header value.
-		 * @return This object.
-		 */
-		public Builder set(String name, Object value) {
-			return set(createHeader(name, value));
-		}
+	/**
+	 * Adds the specified header to the beginning of the headers in this list.
+	 *
+	 * @param value The header to add.  <jk>null</jk> values are ignored.
+	 * @return This object.
+	 */
+	@FluentSetter
+	public HeaderList prepend(Header value) {
+		if (value != null)
+			add(0, value);
+		return this;
+	}
 
-		/**
-		 * Replaces the first occurrence of the headers with the same name.
-		 *
-		 * @param name The header name.
-		 * @param value The header value.
-		 * @return This object.
-		 */
-		public Builder set(String name, Supplier<?> value) {
-			return set(createHeader(name, value));
-		}
+	/**
+	 * Appends the specified header to the beginning of this list.
+	 *
+	 * <p>
+	 * The header is added as a {@link BasicHeader}.
+	 *
+	 * @param name The header name.
+	 * @param value The header value.
+	 * @return This object.
+	 */
+	public HeaderList prepend(String name, Object value) {
+		return prepend(createPart(name, value));
+	}
 
-		/**
-		 * Replaces the first occurrence of the headers with the same name.
-		 *
-		 * <p>
-		 * If no header with the same name is found the given header is added to the end of the list.
-		 *
-		 * @param values The headers to replace.  <jk>null</jk> values are ignored.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder set(List<Header> values) {
-
-			if (values != null) {
-				for (int i1 = 0, j1 = values.size(); i1 < j1; i1++) {
-					Header h = values.get(i1);
-					if (h != null) {
-						for (int i2 = 0, j2 = entries.size(); i2 < j2; i2++) {
-							Header x = entries.get(i2);
-							if (eq(x.getName(), h.getName())) {
-								entries.remove(i2);
-								j2--;
-							}
-						}
-					}
-				}
+	/**
+	 * Appends the specified header to the beginning of this list using a value supplier.
+	 *
+	 * <p>
+	 * The header is added as a {@link BasicHeader}.
+	 *
+	 * <p>
+	 * Value is re-evaluated on each call to {@link BasicHeader#getValue()}.
+	 *
+	 * @param name The header name.
+	 * @param value The header value supplier.
+	 * @return This object.
+	 */
+	public HeaderList prepend(String name, Supplier<?> value) {
+		return prepend(createPart(name, value));
+	}
 
-				for (int i = 0, j = values.size(); i < j; i++) {
-					Header x = values.get(i);
-					if (x != null) {
-						entries.add(x);
-					}
-				}
-			}
+	/**
+	 * Adds the specified headers to the beginning of the headers in this list.
+	 *
+	 * @param values The headers to add.  <jk>null</jk> values are ignored.
+	 * @return This object.
+	 */
+	@FluentSetter
+	public HeaderList prepend(Header...values) {
+		if (values != null)
+			prepend(alist(values));
+		return this;
+	}
 
-			return this;
-		}
+	/**
+	 * Adds the specified headers to the beginning of the headers in this list.
+	 *
+	 * @param values The headers to add.  <jk>null</jk> values are ignored.
+	 * @return This object.
+	 */
+	@FluentSetter
+	public HeaderList prepend(List<Header> values) {
+		if (values != null)
+			addAll(0, values);
+		return this;
+	}
 
-		/**
-		 * Sets a default value for a header.
-		 *
-		 * <p>
-		 * If no header with the same name is found, the given header is added to the end of the list.
-		 *
-		 * @param value The default header to set.  <jk>null</jk> values are ignored.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder setDefault(Header value) {
-			if (value != null) {
-				boolean replaced = false;
-				if (defaultEntries == null)
-					defaultEntries = list();
-				for (int i = 0, j = defaultEntries.size(); i < j; i++) {
-					Header x = defaultEntries.get(i);
-					if (eq(x.getName(), value.getName())) {
-						if (replaced) {
-							defaultEntries.remove(i);
-							j--;
-						} else {
-							defaultEntries.set(i, value);
-							replaced = true;
-						}
-					}
-				}
+	/**
+	 * Removes the specified header from this list.
+	 *
+	 * @param value The header to remove.  <jk>null</jk> values are ignored.
+	 * @return This object.
+	 */
+	@FluentSetter
+	public HeaderList remove(Header value) {
+		if (value != null)
+			removeIf(x -> eq(x.getName(), value.getName()) && eq(x.getValue(), value.getValue()));
+		return this;
+	}
 
-				if (! replaced)
-					defaultEntries.add(value);
-			}
+	/**
+	 * Removes the specified headers from this list.
+	 *
+	 * @param values The headers to remove.  <jk>null</jk> values are ignored.
+	 * @return This object.
+	 */
+	@FluentSetter
+	public HeaderList remove(Header...values) {
+		for (int i = 0; i < values.length; i++)
+			remove(values[i]);
+		return this;
+	}
 
-			return this;
-		}
+	/**
+	 * Removes the specified headers from this list.
+	 *
+	 * @param values The headers to remove.  <jk>null</jk> values are ignored.
+	 * @return This object.
+	 */
+	@FluentSetter
+	public HeaderList remove(List<Header> values) {
+		if (values != null)
+			values.forEach(x -> remove(x));
+		return this;
+	}
 
-		/**
-		 * Sets default values for one or more headers.
-		 *
-		 * <p>
-		 * If no header with the same name is found the given header is added to the end of the list.
-		 *
-		 * @param values The default headers to set.  <jk>null</jk> values are ignored.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder setDefault(Header...values) {
-			if (values != null)
-				setDefault(alist(values));
-			return this;
-		}
+	/**
+	 * Removes the header with the specified name from this list.
+	 *
+	 * @param name The header name.
+	 * @return This object.
+	 */
+	@FluentSetter
+	public HeaderList remove(String name) {
+		removeIf(x -> eq(x.getName(), name));
+		return this;
+	}
 
-		/**
-		 * Sets a default value for a header.
-		 *
-		 * @param name The header name.
-		 * @param value The header value.
-		 * @return This object.
-		 */
-		public Builder setDefault(String name, Object value) {
-			return setDefault(createHeader(name, value));
-		}
+	/**
+	 * Removes the header with the specified name from this list.
+	 *
+	 * @param names The header name.
+	 * @return This object.
+	 */
+	@FluentSetter
+	public HeaderList remove(String...names) {
+		if (names != null)
+			for (int i = 0; i < names.length; i++)
+				remove(names[i]);
+		return this;
+	}
 
-		/**
-		 * Sets a default value for a header.
-		 *
-		 * @param name The header name.
-		 * @param value The header value.
-		 * @return This object.
-		 */
-		public Builder setDefault(String name, Supplier<?> value) {
-			return setDefault(createHeader(name, value));
-		}
+	/**
+	 * Removes all headers from this list.
+	 *
+	 * @return This object.
+	 */
+	public HeaderList removeAll() {
+		clear();
+		return this;
+	}
 
-		/**
-		 * Sets default values for one or more headers.
-		 *
-		 * <p>
-		 * If no header with the same name is found the given header is added to the end of the list.
-		 *
-		 * @param values The default headers to set.  <jk>null</jk> values are ignored.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder setDefault(List<Header> values) {
-
-			if (values != null) {
-				if (defaultEntries == null)
-					defaultEntries = list();
-				for (int i1 = 0, j1 = values.size(); i1 < j1; i1++) {
-					Header h = values.get(i1);
-					if (h != null) {
-						for (int i2 = 0, j2 = defaultEntries.size(); i2 < j2; i2++) {
-							Header x = defaultEntries.get(i2);
-							if (eq(x.getName(), h.getName())) {
-								defaultEntries.remove(i2);
-								j2--;
-							}
-						}
+	/**
+	 * Adds or replaces the header(s) with the same name.
+	 *
+	 * <p>
+	 * If no header with the same name is found the given header is added to the end of the list.
+	 *
+	 * @param value The headers to replace.  <jk>null</jk> values are ignored.
+	 * @return This object.
+	 */
+	@FluentSetter
+	public HeaderList set(Header value) {
+		if (value != null) {
+			boolean replaced = false;
+			for (int i = 0, j = size(); i < j; i++) {
+				Header x = get(i);
+				if (eq(x.getName(), value.getName())) {
+					if (replaced) {
+						remove(i);
+						j--;
+					} else {
+						set(i, value);
+						replaced = true;
 					}
 				}
-				values.forEach(x -> {
-					if (x != null)
-						defaultEntries.add(x);
-				});
-			}
-
-			return this;
-		}
-
-		/**
-		 * Adds the specify header to this list.
-		 *
-		 * @param flag
-		 * 	What to do with the header.
-		 * 	<br>Possible values:
-		 * 	<ul>
-		 * 		<li>{@link ListOperation#APPEND APPEND} - Calls {@link #append(Header)}.
-		 * 		<li>{@link ListOperation#PREPEND PREEND} - Calls {@link #prepend(Header)}.
-		 * 		<li>{@link ListOperation#SET REPLACE} - Calls {@link #set(Header)}.
-		 * 		<li>{@link ListOperation#DEFAULT DEFAULT} - Calls {@link #setDefault(Header)}.
-		 * 	</ul>
-		 * @param value The header to add.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder add(ListOperation flag, Header value) {
-			if (flag == ListOperation.APPEND)
-				return append(value);
-			if (flag == ListOperation.PREPEND)
-				return prepend(value);
-			if (flag == ListOperation.SET)
-				return set(value);
-			if (flag == ListOperation.DEFAULT)
-				return setDefault(value);
-			throw new BasicRuntimeException("Invalid value specified for flag parameter on add(flag,value) method: {0}", flag);
-		}
-
-		/**
-		 * Adds the specified headers to this list.
-		 *
-		 * @param flag
-		 * 	What to do with the header.
-		 * 	<br>Possible values:
-		 * 	<ul>
-		 * 		<li>{@link ListOperation#APPEND APPEND} - Calls {@link #append(Header[])}.
-		 * 		<li>{@link ListOperation#PREPEND PREEND} - Calls {@link #prepend(Header[])}.
-		 * 		<li>{@link ListOperation#SET REPLACE} - Calls {@link #set(Header[])}.
-		 * 		<li>{@link ListOperation#DEFAULT DEFAULT} - Calls {@link #setDefault(Header[])}.
-		 * 	</ul>
-		 * @param values The headers to add.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder add(ListOperation flag, Header...values) {
-			if (flag == ListOperation.APPEND)
-				return append(values);
-			if (flag == ListOperation.PREPEND)
-				return prepend(values);
-			if (flag == ListOperation.SET)
-				return set(values);
-			if (flag == ListOperation.DEFAULT)
-				return setDefault(values);
-			throw new BasicRuntimeException("Invalid value specified for flag parameter on add(flag,values) method: {0}", flag);
-		}
-
-		/**
-		 * Adds the specified header to this list.
-		 *
-		 * @param flag
-		 * 	What to do with the header.
-		 * 	<br>Possible values:
-		 * 	<ul>
-		 * 		<li>{@link ListOperation#APPEND APPEND} - Calls {@link #append(String,Object)}.
-		 * 		<li>{@link ListOperation#PREPEND PREEND} - Calls {@link #prepend(String,Object)}.
-		 * 		<li>{@link ListOperation#SET REPLACE} - Calls {@link #set(String,Object)}.
-		 * 		<li>{@link ListOperation#DEFAULT DEFAULT} - Calls {@link #setDefault(String,Object)}.
-		 * 	</ul>
-		 * @param name The header name.
-		 * @param value The header value.
-		 * @return This object.
-		 */
-		public Builder add(ListOperation flag, String name, Object value) {
-			if (flag == ListOperation.APPEND)
-				return append(name, value);
-			if (flag == ListOperation.PREPEND)
-				return prepend(name, value);
-			if (flag == ListOperation.SET)
-				return set(name, value);
-			if (flag == ListOperation.DEFAULT)
-				return setDefault(name, value);
-			throw new BasicRuntimeException("Invalid value specified for flag parameter on add(flag,name,value) method: {0}", flag);
-		}
-
-		/**
-		 * Adds the specified header to this list.
-		 *
-		 * @param flag
-		 * 	What to do with the header.
-		 * 	<br>Possible values:
-		 * 	<ul>
-		 * 		<li>{@link ListOperation#APPEND APPEND} - Calls {@link #append(String,Supplier)}.
-		 * 		<li>{@link ListOperation#PREPEND PREEND} - Calls {@link #prepend(String,Supplier)}.
-		 * 		<li>{@link ListOperation#SET REPLACE} - Calls {@link #set(String,Supplier)}.
-		 * 		<li>{@link ListOperation#DEFAULT DEFAULT} - Calls {@link #setDefault(String,Supplier)}.
-		 * 	</ul>
-		 * @param name The header name.
-		 * @param value The header value supplier.
-		 * @return This object.
-		 */
-		public Builder add(ListOperation flag, String name, Supplier<?> value) {
-			if (flag == ListOperation.APPEND)
-				return append(name, value);
-			if (flag == ListOperation.PREPEND)
-				return prepend(name, value);
-			if (flag == ListOperation.SET)
-				return set(name, value);
-			if (flag == ListOperation.DEFAULT)
-				return setDefault(name, value);
-			throw new BasicRuntimeException("Invalid value specified for flag parameter on add(flag,name,value) method: {0}", flag);
-		}
-
-		/**
-		 * Adds the specified headers to this list.
-		 *
-		 * @param flag
-		 * 	What to do with the header.
-		 * 	<br>Possible values:
-		 * 	<ul>
-		 * 		<li>{@link ListOperation#APPEND APPEND} - Calls {@link #append(String,Supplier)}.
-		 * 		<li>{@link ListOperation#PREPEND PREEND} - Calls {@link #prepend(String,Supplier)}.
-		 * 		<li>{@link ListOperation#SET REPLACE} - Calls {@link #set(String,Supplier)}.
-		 * 		<li>{@link ListOperation#DEFAULT DEFAULT} - Calls {@link #setDefault(String,Supplier)}.
-		 * 	</ul>
-		 * @param values The headers to add.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder add(ListOperation flag, List<Header> values) {
-			if (flag == ListOperation.APPEND)
-				return append(values);
-			if (flag == ListOperation.PREPEND)
-				return prepend(values);
-			if (flag == ListOperation.SET)
-				return set(values);
-			if (flag == ListOperation.DEFAULT)
-				return setDefault(values);
-			throw new BasicRuntimeException("Invalid value specified for flag parameter on add(flag,values) method: {0}", flag);
-		}
-
-		/**
-		 * Performs an action on all headers in this list.
-		 *
-		 * <p>
-		 * This is the preferred method for iterating over parts as it does not involve
-		 * creation or copy of lists/arrays.
-		 *
-		 * @param action An action to perform on each element.
-		 * @return This object.
-		 */
-		public Builder forEach(Consumer<Header> action) {
-			for (int i = 0, j = entries.size(); i < j; i++)
-				action.accept(entries.get(i));
-			return this;
-		}
-
-		/**
-		 * Performs an action on all headers with the specified name in this list.
-		 *
-		 * <p>
-		 * This is the preferred method for iterating over parts as it does not involve
-		 * creation or copy of lists/arrays.
-		 *
-		 * @param name The part name.
-		 * @param action An action to perform on each element.
-		 * @return This object.
-		 */
-		public Builder forEach(String name, Consumer<Header> action) {
-			for (int i = 0, j = entries.size(); i < j; i++) {
-				Header x = entries.get(i);
-				if (eq(name, x.getName()))
-					action.accept(x);
-			}
-			return this;
-		}
-
-		private boolean isResolving() {
-			return varResolver != null;
-		}
-
-		private Supplier<Object> resolver(Object input) {
-			return ()->varResolver.resolve(stringify(unwrap(input)));
-		}
-
-		private Object unwrap(Object o) {
-			while (o instanceof Supplier)
-				o = ((Supplier<?>)o).get();
-			return o;
-		}
-
-		/**
-		 * Creates a new header out of the specified name/value pair.
-		 *
-		 * @param name The header name.
-		 * @param value The header value.
-		 * @return A new header.
-		 */
-		protected Header createHeader(String name, Object value) {
-			if (value instanceof Supplier<?>) {
-				Supplier<?> value2 = (Supplier<?>)value;
-				return isResolving() ? new BasicHeader(name, resolver(value2)) : new BasicHeader(name, value2);
-			}
-			return isResolving() ? new BasicHeader(name, resolver(value)) : new BasicHeader(name, value);
-		}
-
-		private boolean eq(String s1, String s2) {
-			return caseSensitive ? StringUtils.eq(s1, s2) : StringUtils.eqic(s1, s2);
-		}
-
-		/**
-		 * Gets the first header with the given name.
-		 *
-		 * <p>
-		 * Header name comparison is case insensitive.
-		 *
-		 * @param name The header name.
-		 * @return The first matching header, or {@link Optional#empty()} if not found.
-		 */
-		public Optional<Header> getFirst(String name) {
-			for (int i = 0; i < entries.size(); i++) {
-				Header x = entries.get(i);
-				if (eq(x.getName(), name))
-					return optional(x);
-			}
-			if (defaultEntries != null) {
-				for (int i = 0; i < defaultEntries.size(); i++) {
-					Header x = defaultEntries.get(i);
-					if (eq(x.getName(), name))
-						return optional(x);
-				}
 			}
-			return empty();
-		}
 
-		/**
-		 * Gets the last header with the given name.
-		 *
-		 * <p>
-		 * Header name comparison is case insensitive.
-		 *
-		 * @param name The header name.
-		 * @return The last matching header, or {@link Optional#empty()} if not found.
-		 */
-		public Optional<Header> getLast(String name) {
-			for (int i = entries.size() - 1; i >= 0; i--) {
-				Header x = entries.get(i);
-				if (eq(x.getName(), name))
-					return optional(x);
-			}
-			if (defaultEntries != null) {
-				for (int i = defaultEntries.size() - 1; i >= 0; i--) {
-					Header x = defaultEntries.get(i);
-					if (eq(x.getName(), name))
-						return optional(x);
-				}
-			}
-			return empty();
-		}
-
-		// <FluentSetters>
-
-		@Override /* GENERATED - org.apache.juneau.BeanBuilder */
-		public Builder impl(Object value) {
-			super.impl(value);
-			return this;
+			if (! replaced)
+				add(value);
 		}
 
-		@Override /* GENERATED - org.apache.juneau.BeanBuilder */
-		public Builder type(Class<?> value) {
-			super.type(value);
-			return this;
-		}
-
-		// </FluentSetters>
-
-		//-------------------------------------------------------------------------------------------------------------
-		// Other methods
-		//-------------------------------------------------------------------------------------------------------------
-
-		@Override /* Object */
-		public String toString() {
-			return "[" + join(entries, ", ") + "]";
-		}
+		return this;
 	}
 
-	//-----------------------------------------------------------------------------------------------------------------
-	// Instance
-	//-----------------------------------------------------------------------------------------------------------------
-
-	final boolean caseSensitive;
-
 	/**
-	 * Constructor.
+	 * Adds or replaces the header(s) with the same name.
+	 *
+	 * <p>
+	 * If no header with the same name is found the given header is added to the end of the list.
 	 *
-	 * @param builder The builder containing the settings for this bean.
+	 * @param values The headers to replace.  <jk>null</jk> values are ignored.
+	 * @return This object.
 	 */
-	public HeaderList(Builder builder) {
-		super(! builder.unmodifiable, builder.entries);
-
-		if (builder.defaultEntries != null) {
-			for (int i1 = 0, j1 = builder.defaultEntries.size(); i1 < j1; i1++) {
-				Header x = builder.defaultEntries.get(i1);
-				boolean exists = false;
-				for (int i2 = 0, j2 = builder.entries.size(); i2 < j2 && ! exists; i2++)
-					exists = eq(builder.entries.get(i2).getName(), x.getName());
-				if (! exists)
-					overrideAdd(x);
-			}
-		}
-		this.caseSensitive = builder.caseSensitive;
+	@FluentSetter
+	public HeaderList set(Header...values) {
+		if (values != null)
+			set(alist(values));
+		return this;
 	}
 
 	/**
-	 * Constructor.
+	 * Replaces the first occurrence of the headers with the same name.
 	 *
-	 * @param modifiable Whether this list should be modifiable.
-	 * @param headers
-	 * 	The headers to add to the list.
-	 * 	<br>Can be <jk>null</jk>.
-	 * 	<br><jk>null</jk> entries are ignored.
+	 * @param name The header name.
+	 * @param value The header value.
+	 * @return This object.
 	 */
-	public HeaderList(boolean modifiable, List<Header> headers) {
-		super(modifiable, headers);
-		caseSensitive = false;
+	public HeaderList set(String name, Object value) {
+		return set(createPart(name, value));
 	}
 
 	/**
-	 * Constructor.
+	 * Replaces the first occurrence of the headers with the same name.
 	 *
-	 * @param modifiable Whether this list should be modifiable.
-	 * @param headers
-	 * 	The headers to add to the list.
-	 * 	<br><jk>null</jk> entries are ignored.
+	 * @param name The header name.
+	 * @param value The header value.
+	 * @return This object.
 	 */
-	public HeaderList(boolean modifiable, Header...headers) {
-		super(modifiable, Arrays.asList(headers));
-		caseSensitive = false;
+	public HeaderList set(String name, Supplier<?> value) {
+		return set(createPart(name, value));
 	}
 
 	/**
-	 * Default constructor.
+	 * Replaces the first occurrence of the headers with the same name.
+	 *
+	 * <p>
+	 * If no header with the same name is found the given header is added to the end of the list.
 	 *
-	 * @param modifiable Whether this list should be modifiable.
+	 * @param values The headers to replace.  <jk>null</jk> values are ignored.
+	 * @return This object.
 	 */
-	public HeaderList(boolean modifiable) {
-		super(modifiable);
-		caseSensitive = false;
+	@FluentSetter
+	public HeaderList set(List<Header> values) {
+
+		if (values != null) {
+			for (int i1 = 0, j1 = values.size(); i1 < j1; i1++) {
+				Header h = values.get(i1);
+				if (h != null) {
+					for (int i2 = 0, j2 = size(); i2 < j2; i2++) {
+						Header x = get(i2);
+						if (eq(x.getName(), h.getName())) {
+							remove(i2);
+							j2--;
+						}
+					}
+				}
+			}
+
+			for (int i = 0, j = values.size(); i < j; i++) {
+				Header x = values.get(i);
+				if (x != null) {
+					add(x);
+				}
+			}
+		}
+
+		return this;
 	}
 
 	/**
-	 * Default constructor.
+	 * Gets the first header with the given name.
+	 *
+	 * <p>
+	 * Header name comparison is case insensitive.
+	 *
+	 * @param name The header name.
+	 * @return The first matching header, or {@link Optional#empty()} if not found.
 	 */
-	public HeaderList() {
-		super(true);
-		caseSensitive = false;
+	public Optional<Header> getFirst(String name) {
+		for (int i = 0; i < size(); i++) {
+			Header x = get(i);
+			if (eq(x.getName(), name))
+				return optional(x);
+		}
+		return empty();
 	}
 
 	/**
-	 * Returns a builder initialized with the contents of this bean.
+	 * Gets the last header with the given name.
+	 *
+	 * <p>
+	 * Header name comparison is case insensitive.
 	 *
-	 * @return A new builder object.
+	 * @param name The header name.
+	 * @return The last matching header, or {@link Optional#empty()} if not found.
 	 */
-	public Builder copy() {
-		return new Builder(this);
+	public Optional<Header> getLast(String name) {
+		for (int i = size() - 1; i >= 0; i--) {
+			Header x = get(i);
+			if (eq(x.getName(), name))
+				return optional(x);
+		}
+		return empty();
 	}
 
 	/**
@@ -1321,21 +764,20 @@ public class HeaderList extends ControlledArrayList<Header>{
 	}
 
 	/**
-	 * Gets all of the headers contained within this list.
+	 * Gets all of the headers.
 	 *
 	 * <p>
 	 * The returned array maintains the relative order in which the headers were added.
-	 * Headers with null values are ignored.
 	 * Each call creates a new array not backed by this list.
 	 *
 	 * <p>
 	 * As a general rule, it's more efficient to use the other methods with consumers to
 	 * get headers.
 	 *
-	 * @return An array of all the headers in this list, never <jk>null</jk>.
+	 * @return An array containing all headers, never <jk>null</jk>.
 	 */
 	public Header[] getAll() {
-		return size() == 0 ? EMPTY_ARRAY : toArray(new Header[size()]);
+		return stream().toArray(Header[]::new);
 	}
 
 	/**
@@ -1356,47 +798,7 @@ public class HeaderList extends ControlledArrayList<Header>{
 	 * @return An array containing all matching headers, never <jk>null</jk>.
 	 */
 	public Header[] getAll(String name) {
-		ArrayBuilder<Header> b = ArrayBuilder.of(Header.class).filter(NOT_NULL);
-		for (Header x : this)
-			if (eq(x.getName(), name))
-				b.add(x);
-		return b.orElse(EMPTY_ARRAY);
-	}
-
-	/**
-	 * Gets the first header with the given name.
-	 *
-	 * <p>
-	 * Header name comparison is case insensitive.
-	 *
-	 * @param name The header name.
-	 * @return The first matching header, or <jk>null</jk> if not found.
-	 */
-	public Optional<Header> getFirst(String name) {
-		for (int i = 0; i < size(); i++) {
-			Header x = get(i);
-			if (eq(x.getName(), name))
-				return optional(x);
-		}
-		return empty();
-	}
-
-	/**
-	 * Gets the last header with the given name.
-	 *
-	 * <p>
-	 * Header name comparison is case insensitive.
-	 *
-	 * @param name The header name.
-	 * @return The last matching header, or <jk>null</jk> if not found.
-	 */
-	public Optional<Header> getLast(String name) {
-		for (int i = size() - 1; i >= 0; i--) {
-			Header x = get(i);
-			if (eq(x.getName(), name))
-				return optional(x);
-		}
-		return empty();
+		return stream().filter(x -> eq(x.getName(), name)).toArray(Header[]::new);
 	}
 
 	/**
@@ -1428,9 +830,7 @@ public class HeaderList extends ControlledArrayList<Header>{
 	 * @return An array containing all values.  Never <jk>null</jk>.
 	 */
 	public String[] getValues(String name) {
-		ArrayBuilder<String> b = ArrayBuilder.of(String.class).size(1);
-		forEach(name, x -> b.add(x.getValue()));
-		return b.orElse(EMPTY_STRING_ARRAY);
+		return stream().filter(x -> eq(x.getName(), name)).map(x -> x.getValue()).toArray(String[]::new);
 	}
 
 	/**
@@ -1443,11 +843,7 @@ public class HeaderList extends ControlledArrayList<Header>{
 	 * @return <jk>true</jk> if at least one header with the name is present.
 	 */
 	public boolean contains(String name) {
-		for (Header x : this) {
-			if (eq(x.getName(), name))
-				return true;
-		}
-		return false;
+		return stream().anyMatch(x -> eq(x.getName(), name));
 	}
 
 	/**
@@ -1456,7 +852,7 @@ public class HeaderList extends ControlledArrayList<Header>{
 	 * @return A new iterator over this list of headers.
 	 */
 	public HeaderIterator headerIterator() {
-		return new BasicHeaderIterator(getAll(), null, caseSensitive);
+		return new BasicHeaderIterator(toArray(new Header[0]), null, caseSensitive);
 	}
 
 	/**
@@ -1514,12 +910,43 @@ public class HeaderList extends ControlledArrayList<Header>{
 		return stream().filter(x->eq(name, x.getName()));
 	}
 
+	//-------------------------------------------------------------------------------------------------------------
+	// Other methods
+	//-------------------------------------------------------------------------------------------------------------
+
+	/**
+	 * Creates a new header out of the specified name/value pair.
+	 *
+	 * @param name The header name.
+	 * @param value The header value.
+	 * @return A new header.
+	 */
+	private Header createPart(String name, Object value) {
+		boolean isResolving = varResolver != null;
+
+		if (value instanceof Supplier<?>) {
+			Supplier<?> value2 = (Supplier<?>)value;
+			return isResolving ? new BasicHeader(name, resolver(value2)) : new BasicHeader(name, value2);
+		}
+		return isResolving ? new BasicHeader(name, resolver(value)) : new BasicHeader(name, value);
+	}
+
+	private Supplier<Object> resolver(Object input) {
+		return ()->varResolver.resolve(stringify(unwrap(input)));
+	}
+
+	private Object unwrap(Object o) {
+		while (o instanceof Supplier)
+			o = ((Supplier<?>)o).get();
+		return o;
+	}
+
 	private boolean eq(String s1, String s2) {
-		return StringUtils.eq(!caseSensitive, s1, s2);
+		return caseSensitive ? StringUtils.eq(s1, s2) : StringUtils.eqic(s1, s2);
 	}
 
 	@Override /* Object */
 	public String toString() {
-		return super.toString();
+		return "[" + join(this, ", ") + "]";
 	}
-}
+}
\ No newline at end of file
diff --git a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/PartList.java b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/PartList.java
index 6bb00b919..d65ae4652 100644
--- a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/PartList.java
+++ b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/PartList.java
@@ -23,169 +23,46 @@ import java.util.stream.*;
 
 import org.apache.http.*;
 import org.apache.http.util.*;
-import org.apache.juneau.*;
-import org.apache.juneau.collections.*;
-import org.apache.juneau.http.HttpParts;
 import org.apache.juneau.http.annotation.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.svl.*;
 
 /**
- * An immutable list of HTTP parts (form-data, query-parameters, path-parameters).
+ * An simple list of HTTP parts (form-data, query-parameters, path-parameters).
  *
  * <h5 class='figure'>Example</h5>
  * <p class='bjava'>
  * 	PartList <jv>parts</jv> = PartList
  * 		.<jsm>create</jsm>()
  * 		.append(MyPart.<jsm>of</jsm>(<js>"foo"</js>))
- * 		.append(<js>"Bar"</js>, ()-&gt;<jsm>getDynamicValueFromSomewhere</jsm>())
- * 		.build();
+ * 		.append(<js>"Bar"</js>, ()-&gt;<jsm>getDynamicValueFromSomewhere</jsm>());
  * </p>
  *
- * <p>
- * Convenience creators are provided for creating lists with minimal code:
- * <p class='bjava'>
- * 	PartList <jv>parts</jv> = PartList.<jsm>of</jsm>(BasicIntegerPart.<jsm>of</jsm>(<js>"foo"</js>, 1));
- * </p>
- *
- * <p>
- * Part lists are immutable, but can be appended to using the {@link #copy()} method:
- * <p class='bjava'>
- * 	<jv>parts</jv> = <jv>parts</jv>
- * 		.copy()
- * 		.append(BasicIntegerPart.<jsm>of</jsm>(<js>"foo"</js>, 1))
- * 		.build();
- * </p>
- *
- * <p>
- * Static methods are provided on {@link HttpParts} to further simplify creation of part lists.
- * <p class='bjava'>
- * 	<jk>import static</jk> org.apache.juneau.http.HttpParts.*;
- *
- * 	PartList <jv>parts</jv> = <jsm>partList</jsm>(<jsm>integerPart</jsm>(<js>"foo"</js>, 1), <jsm>booleanPart</jsm>(<js>"bar"</js>, <jk>false</jk>));
- * </p>
- *
- * <p>
- * The builder class supports setting default part values (i.e. add a part to the list if it isn't otherwise in the list).
- * Note that this is different from simply setting a value twice as using default values will not overwrite existing
- * parts.
- * <br>The following example notes the distinction:
- *
- * <p class='bjava'>
- * 	<jv>parts</jv> = PartList
- * 		.<jsm>create</jsm>()
- * 		.set(<js>"Foo"</js>, <js>"bar"</js>)
- * 		.set(<js>"Foo"</js>, <js>"baz"</js>)
- * 		.build();
- * 	<jsm>assertObject</jsm>(<jv>parts</jv>).isString(<js>"foo=baz"</js>);
- *
- * 	<jv>parts</jv> = PartList
- * 		.create()
- * 		.set(<js>"Foo"</js>, <js>"bar"</js>)
- * 		.setDefault(<js>"Foo"</js>, <js>"baz"</js>)
- * 		.build();
- * 	<jsm>assertObject</jsm>(<jv>parts</jv>).isString(<js>"foo=bar"</js>);
- * </p>
- *
- * <p>
- * Various methods are provided for iterating over the parts in this list to avoid array copies.
- * <ul class='javatree'>
- * 	<li class='jm'>{@link #forEach(Consumer)} / {@link #forEach(String,Consumer)} / {@link #forEach(Predicate,Consumer)} - Use consumers to process parts.
- * 	<li class='jm'>{@link #partIterator()} / {@link #partIterator(String)} - Use an {@link PartIterator} to process parts.
- * 	<li class='jm'>{@link #stream()} / {@link #stream(String)} - Use a stream.
- * </ul>
- * <p>
- * In general, try to use these over the {@link #getAll()}/{@link #getAll(String)} methods that require array copies.
- *
- * <p>
- * Similar to the way multiple headers can be collapsed into a single value, the {@link #get(String)} method is special in that it will collapse multiple
- * parts with the same name into a single comma-delimited list.
- *
- * <p>
- * The {@link #get(Class)} and {@link #get(String, Class)} methods are provided for working with {@link FormData}/{@link Query}/{@link Path}-annotated
- * beans.
- *
- * <h5 class='figure'>Example</h5>
- * <p class='bjava'>
- * 	MyQueryBean <jv>foo</jv> = <jv>parts</jv>.get(MyQueryBean.<jk>class</jk>);
- * </p>
- *
- * <p>
- * By default, part names are treated as case-sensitive.  This can be changed using the {@link PartList.Builder#caseInsensitive()}
- * method.
- *
- * <p>
- * A {@link VarResolver} can be associated with this builder to create part values with embedded variables that
- * are resolved at runtime.
- *
- * <h5 class='figure'>Example</h5>
- * <p class='bjava'>
- * 	<jc>// Create a part list with dynamically-resolving values pulled from a system property.</jc>
- *
- * 	System.<jsm>setProperty</jsm>(<js>"foo"</js>, <js>"bar"</js>);
- *
- * 	PartList <jv>parts</jv> = PartList
- * 		.<jsm>create</jsm>()
- * 		.resolving()
- * 		.append(<js>"X1"</js>, <js>"$S{foo}"</js>)
- * 		.append(<js>"X2"</js>, ()-&gt;<js>"$S{foo}"</js>)
- * 		.build();
- *
- * 	<jsm>assertObject</jsm>(<jv>parts</jv>).isString(<js>"X1=bar&amp;X2=bar"</js>);
- * </p>
- *
- * <p>
- * The {@link PartList} object can be extended to defined pre-packaged lists of parts which can be used in various
- * annotations throughout the framework.
- *
- * <h5 class='figure'>Example</h5>
- * <p class='bjava'>
- * 	<jc>// A predefined list of parts.</jc>
- * 	<jk>public class</jk> MyPartList <jk>extends</jk> PartList {
- * 		<jk>public</jk> MyPartList() {
- * 			<jk>super</jk>(BasicIntegerPart.<jsm>of</jsm>(<js>"foo"</js>,1), BasicBooleanPart.<jsm>of</jsm>(<js>"bar"</js>,<jk>false</jk>));
- * 		}
- * 	}
- * </p>
- *
- * <ul class='notes'>
- * 	<li class='note'>This class is thread safe.
- * </ul>
- *
  * <ul class='seealso'>
  * 	<li class='link'>{@doc juneau-rest-common}
  * 	<li class='extlink'>{@source}
  * </ul>
  */
-public class PartList extends ControlledArrayList<NameValuePair> {
+public class PartList extends ArrayList<NameValuePair> {
+
+	private static final long serialVersionUID = 1L;
 
 	//-----------------------------------------------------------------------------------------------------------------
 	// Static
 	//-----------------------------------------------------------------------------------------------------------------
 
-	private static final long serialVersionUID = 1L;
-	private static final NameValuePair[] EMPTY_ARRAY = new NameValuePair[0];
-	private static final String[] EMPTY_STRING_ARRAY = new String[0];
-	private static final Predicate<NameValuePair> NOT_NULL = x -> x != null;
-
-	/** Represents no part supplier in annotations. */
+	/** Represents no part list in annotations. */
 	public static final class Void extends PartList {
-		Void() {
-			super(false);
-		}
 		private static final long serialVersionUID = 1L;
 	}
 
-	/** Predefined instance. */
-	public static final PartList EMPTY = new PartList(false);
-
 	/**
-	 * Instantiates a new builder for this bean.
+	 * Instantiates a new part list.
 	 *
-	 * @return A new builder.
+	 * @return A new part list.
 	 */
-	public static Builder create() {
-		return new Builder();
+	public static PartList create() {
+		return new PartList();
 	}
 
 	/**
@@ -198,7 +75,7 @@ public class PartList extends ControlledArrayList<NameValuePair> {
 	 * @return A new unmodifiable instance, never <jk>null</jk>.
 	 */
 	public static PartList of(List<NameValuePair> parts) {
-		return parts == null || parts.isEmpty() ? EMPTY : new PartList(true, parts);
+		return new PartList().append(parts);
 	}
 
 	/**
@@ -210,7 +87,7 @@ public class PartList extends ControlledArrayList<NameValuePair> {
 	 * @return A new unmodifiable instance, never <jk>null</jk>.
 	 */
 	public static PartList of(NameValuePair...parts) {
-		return parts == null || parts.length == 0 ? EMPTY : new PartList(true, parts);
+		return new PartList().append(parts);
 	}
 
 	/**
@@ -227,954 +104,513 @@ public class PartList extends ControlledArrayList<NameValuePair> {
 	 * @throws RuntimeException If odd number of parameters were specified.
 	 * @return A new instance.
 	 */
-	public static PartList ofPairs(Object...pairs) {
-		if (pairs == null || pairs.length == 0)
-			return EMPTY;
+	public static PartList ofPairs(String...pairs) {
+		PartList x = new PartList();
+		if (pairs == null)
+			pairs = new String[0];
 		if (pairs.length % 2 != 0)
 			throw new RuntimeException("Odd number of parameters passed into PartList.ofPairs()");
-		ArrayBuilder<NameValuePair> b = ArrayBuilder.of(NameValuePair.class).filter(NOT_NULL).size(pairs.length / 2);
 		for (int i = 0; i < pairs.length; i+=2)
-			b.add(BasicPart.of(stringify(pairs[i]), pairs[i+1]));
-		return new PartList(true, b.orElse(EMPTY_ARRAY));
+			x.add(BasicPart.of(pairs[i], pairs[i+1]));
+		return x;
 	}
 
 	//-----------------------------------------------------------------------------------------------------------------
-	// Builder
+	// Instance
 	//-----------------------------------------------------------------------------------------------------------------
 
+	private VarResolver varResolver;
+	boolean caseInsensitive = false;
+
 	/**
-	 * Builder class.
+	 * Constructor.
 	 */
-	@FluentSetters
-	public static class Builder extends BeanBuilder<PartList> {
-
-		final List<NameValuePair> entries;
-		List<NameValuePair> defaultEntries;
-		private VarResolver varResolver;
-		boolean caseInsensitive = false, unmodifiable = false;
-
-		/**
-		 * Constructor.
-		 */
-		protected Builder() {
-			super(PartList.class);
-			entries = list();
-		}
-
-		/**
-		 * Copy constructor.
-		 *
-		 * @param copyFrom The bean to copy.
-		 */
-		protected Builder(PartList copyFrom) {
-			super(copyFrom.getClass());
-			entries = copyOf(copyFrom);
-			caseInsensitive = copyFrom.caseInsensitive;
-			unmodifiable = false;
-		}
-
-		/**
-		 * Copy constructor.
-		 *
-		 * @param copyFrom The builder to copy.
-		 */
-		protected Builder(Builder copyFrom) {
-			super(copyFrom);
-			entries = copyOf(copyFrom.entries);
-			defaultEntries = copyOf(copyFrom.defaultEntries);
-			varResolver = copyFrom.varResolver;
-			caseInsensitive = copyFrom.caseInsensitive;
-			unmodifiable = copyFrom.unmodifiable;
-		}
-
-		@Override /* BeanBuilder */
-		protected PartList buildDefault() {
-			return entries.isEmpty() && defaultEntries == null ? EMPTY : new PartList(this);
-		}
-
-		/**
-		 * Makes a copy of this builder.
-		 *
-		 * @return A new copy of this builder.
-		 */
-		public Builder copy() {
-			return new Builder(this);
-		}
-
-		//-------------------------------------------------------------------------------------------------------------
-		// Properties
-		//-------------------------------------------------------------------------------------------------------------
-
-		/**
-		 * Allows part values to contain SVL variables.
-		 *
-		 * <p>
-		 * Resolves variables in part values when using the following methods:
-		 * <ul>
-		 * 	<li class='jm'>{@link #append(String, Object) append(String,Object)}
-		 * 	<li class='jm'>{@link #append(String, Supplier) append(String,Supplier&lt;?&gt;)}
-		 * 	<li class='jm'>{@link #prepend(String, Object) prepend(String,Object)}
-		 * 	<li class='jm'>{@link #prepend(String, Supplier) prepend(String,Supplier&lt;?&gt;)}
-		 * 	<li class='jm'>{@link #set(String, Object) set(String,Object)}
-		 * 	<li class='jm'>{@link #set(String, Supplier) set(String,Supplier&lt;?&gt;)}
-		 * 	<li class='jm'>{@link #setDefault(String, Object) set(String,Object)}
-		 * 	<li class='jm'>{@link #setDefault(String, Supplier) set(String,Supplier&lt;?&gt;)}
-		 * </ul>
-		 *
-		 * <p>
-		 * Uses {@link VarResolver#DEFAULT} to resolve variables.
-		 *
-		 * @return This object.
-		 */
-		public Builder resolving() {
-			return resolving(VarResolver.DEFAULT);
-		}
-
-		/**
-		 * Allows part values to contain SVL variables.
-		 *
-		 * <p>
-		 * Resolves variables in part values when using the following methods:
-		 * <ul>
-		 * 	<li class='jm'>{@link #append(String, Object) append(String,Object)}
-		 * 	<li class='jm'>{@link #append(String, Supplier) append(String,Supplier&lt;?&gt;)}
-		 * 	<li class='jm'>{@link #prepend(String, Object) prepend(String,Object)}
-		 * 	<li class='jm'>{@link #prepend(String, Supplier) prepend(String,Supplier&lt;?&gt;)}
-		 * 	<li class='jm'>{@link #set(String, Object) set(String,Object)}
-		 * 	<li class='jm'>{@link #set(String, Supplier) set(String,Supplier&lt;?&gt;)}
-		 * 	<li class='jm'>{@link #setDefault(String, Object) set(String,Object)}
-		 * 	<li class='jm'>{@link #setDefault(String, Supplier) set(String,Supplier&lt;?&gt;)}
-		 * </ul>
-		 *
-		 * @param varResolver The variable resolver to use for resolving variables.
-		 * @return This object.
-		 */
-		public Builder resolving(VarResolver varResolver) {
-			this.varResolver = varResolver;
-			return this;
-		}
+	public PartList() {
+	}
 
-		/**
-		 * Specifies that the part in this builder should be treated as case-insensitive.
-		 *
-		 * <p>
-		 * The default behavior is case-sensitive.
-		 *
-		 * @return This object.
-		 */
-		public Builder caseInsensitive() {
-			caseInsensitive = true;
-			return this;
-		}
+	/**
+	 * Copy constructor.
+	 *
+	 * @param copyFrom The bean to copy.
+	 */
+	protected PartList(PartList copyFrom) {
+		super(copyFrom);
+		caseInsensitive = copyFrom.caseInsensitive;
+	}
 
-		/**
-		 * Specifies that the resulting list should be unmodifiable.
-		 *
-		 * <p>
-		 * The default behavior is modifiable.
-		 *
-		 * @return This object.
-		 */
-		public Builder unmodifiable() {
-			unmodifiable = true;
-			return this;
-		}
+	/**
+	 * Makes a copy of this list.
+	 *
+	 * @return A new copy of this list.
+	 */
+	public PartList copy() {
+		return new PartList(this);
+	}
 
-		/**
-		 * Removes any parts already in this builder.
-		 *
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder clear() {
-			entries.clear();
-			return this;
-		}
+	/**
+	 * Adds a collection of default parts.
+	 *
+	 * <p>
+	 * Default parts are set if they're not already in the list.
+	 *
+	 * @param parts The list of default parts.
+	 * @return This object.
+	 */
+	public PartList setDefault(List<NameValuePair> parts) {
+		if (parts != null)
+			parts.stream().filter(x -> x != null && ! contains(x.getName())).forEach(x -> set(x));
+		return this;
+	}
 
-		/**
-		 * Adds the specified part to the end of the parts in this builder.
-		 *
-		 * @param value The parts to add.  <jk>null</jk> values are ignored.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder append(NameValuePair value) {
-			if (value != null)
-				entries.add(value);
-			return this;
-		}
+	/**
+	 * Makes a copy of this list of parts and adds a collection of default parts.
+	 *
+	 * <p>
+	 * Default parts are set if they're not already in the list.
+	 *
+	 * @param parts The list of default parts.
+	 * @return A new list, or the same list if the parts were empty.
+	 */
+	public PartList setDefault(NameValuePair...parts) {
+		if (parts != null)
+			setDefault(Arrays.asList(parts));
+		return this;
+	}
 
-		/**
-		 * Appends the specified parts to the end of this builder.
-		 *
-		 * <p>
-		 * The parts is added as a {@link BasicPart}.
-		 *
-		 * @param name The part name.
-		 * @param value The part value.
-		 * @return This object.
-		 */
-		public Builder append(String name, Object value) {
-			return append(createPart(name, value));
-		}
+	/**
+	 * Replaces the first occurrence of the part with the same name.
+	 *
+	 * @param name The header name.
+	 * @param value The header value.
+	 * @return This object.
+	 */
+	public PartList setDefault(String name, Object value) {
+		return setDefault(createPart(name, value));
+	}
 
-		/**
-		 * Appends the specified part to the end of this builder using a value supplier.
-		 *
-		 * <p>
-		 * The part is added as a {@link BasicPart}.
-		 *
-		 * <p>
-		 * Value is re-evaluated on each call to {@link BasicPart#getValue()}.
-		 *
-		 * @param name The part name.
-		 * @param value The part value supplier.
-		 * @return This object.
-		 */
-		public Builder append(String name, Supplier<?> value) {
-			return append(createPart(name, value));
-		}
+	/**
+	 * Replaces the first occurrence of the headers with the same name.
+	 *
+	 * @param name The header name.
+	 * @param value The header value.
+	 * @return This object.
+	 */
+	public PartList setDefault(String name, Supplier<?> value) {
+		return setDefault(createPart(name, value));
+	}
 
-		/**
-		 * Adds the specified parts to the end of the parts in this builder.
-		 *
-		 * @param values The parts to add.  <jk>null</jk> values are ignored.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder append(NameValuePair...values) {
-			if (values != null)
-				for (int i = 0; i < values.length; i++)
-					append(values[i]);
-			return this;
-		}
 
-		/**
-		 * Adds the specified parts to the end of the parts in this builder.
-		 *
-		 * @param values The parts to add.  <jk>null</jk> values are ignored.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder append(List<? extends NameValuePair> values) {
-			if (values != null)
-				values.forEach(x -> append(x));
-			return this;
-		}
+	//-------------------------------------------------------------------------------------------------------------
+	// Properties
+	//-------------------------------------------------------------------------------------------------------------
 
-		/**
-		 * Adds the specified part to the beginning of the parts in this builder.
-		 *
-		 * @param value The part to add.  <jk>null</jk> values are ignored.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder prepend(NameValuePair value) {
-			if (value != null)
-				entries.add(0, value);
-			return this;
-		}
+	/**
+	 * Allows part values to contain SVL variables.
+	 *
+	 * <p>
+	 * Resolves variables in part values when using the following methods:
+	 * <ul>
+	 * 	<li class='jm'>{@link #append(String, Object) append(String,Object)}
+	 * 	<li class='jm'>{@link #append(String, Supplier) append(String,Supplier&lt;?&gt;)}
+	 * 	<li class='jm'>{@link #prepend(String, Object) prepend(String,Object)}
+	 * 	<li class='jm'>{@link #prepend(String, Supplier) prepend(String,Supplier&lt;?&gt;)}
+	 * 	<li class='jm'>{@link #set(String, Object) set(String,Object)}
+	 * 	<li class='jm'>{@link #set(String, Supplier) set(String,Supplier&lt;?&gt;)}
+	 * </ul>
+	 *
+	 * <p>
+	 * Uses {@link VarResolver#DEFAULT} to resolve variables.
+	 *
+	 * @return This object.
+	 */
+	public PartList resolving() {
+		return resolving(VarResolver.DEFAULT);
+	}
 
-		/**
-		 * Appends the specified part to the beginning of this builder.
-		 *
-		 * <p>
-		 * The part is added as a {@link BasicPart}.
-		 *
-		 * @param name The part name.
-		 * @param value The part value.
-		 * @return This object.
-		 */
-		public Builder prepend(String name, Object value) {
-			return prepend(createPart(name, value));
-		}
+	/**
+	 * Allows part values to contain SVL variables.
+	 *
+	 * <p>
+	 * Resolves variables in part values when using the following methods:
+	 * <ul>
+	 * 	<li class='jm'>{@link #append(String, Object) append(String,Object)}
+	 * 	<li class='jm'>{@link #append(String, Supplier) append(String,Supplier&lt;?&gt;)}
+	 * 	<li class='jm'>{@link #prepend(String, Object) prepend(String,Object)}
+	 * 	<li class='jm'>{@link #prepend(String, Supplier) prepend(String,Supplier&lt;?&gt;)}
+	 * 	<li class='jm'>{@link #set(String, Object) set(String,Object)}
+	 * 	<li class='jm'>{@link #set(String, Supplier) set(String,Supplier&lt;?&gt;)}
+	 * </ul>
+	 *
+	 * @param varResolver The variable resolver to use for resolving variables.
+	 * @return This object.
+	 */
+	public PartList resolving(VarResolver varResolver) {
+		this.varResolver = varResolver;
+		return this;
+	}
 
-		/**
-		 * Appends the specified part to the beginning of this builder using a value supplier.
-		 *
-		 * <p>
-		 * The part is added as a {@link BasicPart}.
-		 *
-		 * <p>
-		 * Value is re-evaluated on each call to {@link BasicPart#getValue()}.
-		 *
-		 * @param name The part name.
-		 * @param value The part value supplier.
-		 * @return This object.
-		 */
-		public Builder prepend(String name, Supplier<?> value) {
-			return prepend(createPart(name, value));
-		}
+	/**
+	 * Specifies that the parts in this list should be treated as case-sensitive.
+	 *
+	 * <p>
+	 * The default behavior is case-sensitive.
+	 *
+	 * @param value The new value for this setting.
+	 * @return This object.
+	 */
+	public PartList caseInsensitive(boolean value) {
+		caseInsensitive = value;
+		return this;
+	}
 
-		/**
-		 * Adds the specified parts to the beginning of the parts in this builder.
-		 *
-		 * @param values The parts to add.  <jk>null</jk> values are ignored.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder prepend(NameValuePair...values) {
-			if (values != null)
-				prepend(alist(values));
-			return this;
-		}
+	/**
+	 * Adds the specified part to the end of the parts in this list.
+	 *
+	 * @param value The part to add.  <jk>null</jk> values are ignored.
+	 * @return This object.
+	 */
+	@FluentSetter
+	public PartList append(NameValuePair value) {
+		if (value != null)
+			add(value);
+		return this;
+	}
 
-		/**
-		 * Adds the specified parts to the beginning of the parts in this builder.
-		 *
-		 * @param values The parts to add.  <jk>null</jk> values are ignored.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder prepend(List<? extends NameValuePair> values) {
-			if (values != null)
-				entries.addAll(0, values);
-			return this;
-		}
+	/**
+	 * Appends the specified part to the end of this list.
+	 *
+	 * <p>
+	 * The part is added as a {@link BasicPart}.
+	 *
+	 * @param name The part name.
+	 * @param value The part value.
+	 * @return This object.
+	 */
+	public PartList append(String name, Object value) {
+		return append(createPart(name, value));
+	}
 
-		/**
-		 * Removes the specified part from this builder.
-		 *
-		 * @param value The part to remove.  <jk>null</jk> values are ignored.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder remove(NameValuePair value) {
-			if (value != null)
-				entries.remove(value);
-			return this;
-		}
+	/**
+	 * Appends the specified part to the end of this list using a value supplier.
+	 *
+	 * <p>
+	 * The part is added as a {@link BasicPart}.
+	 *
+	 * <p>
+	 * Value is re-evaluated on each call to {@link BasicPart#getValue()}.
+	 *
+	 * @param name The part name.
+	 * @param value The part value supplier.
+	 * @return This object.
+	 */
+	public PartList append(String name, Supplier<?> value) {
+		return append(createPart(name, value));
+	}
 
-		/**
-		 * Removes the specified parts from this builder.
-		 *
-		 * @param values The parts to remove.  <jk>null</jk> values are ignored.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder remove(NameValuePair...values) {
+	/**
+	 * Adds the specified parts to the end of the parts in this list.
+	 *
+	 * @param values The parts to add.  <jk>null</jk> values are ignored.
+	 * @return This object.
+	 */
+	@FluentSetter
+	public PartList append(NameValuePair...values) {
+		if (values != null)
 			for (int i = 0; i < values.length; i++)
-				remove(values[i]);
-			return this;
-		}
-
-		/**
-		 * Removes the specified parts from this builder.
-		 *
-		 * @param values The parts to remove.  <jk>null</jk> values are ignored.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder remove(List<? extends NameValuePair> values) {
-			if (values != null)
-				values.forEach(x -> remove(x));
-			return this;
-		}
-
-		/**
-		 * Removes the part with the specified name from this builder.
-		 *
-		 * @param name The part name.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder remove(String name) {
-			for (int i = 0; i < entries.size(); i++) /* See HTTPCORE-361 */
-				if (eq(entries.get(i).getName(), name))
-					entries.remove(i--);
-			return this;
-		}
-
-		/**
-		 * Removes the part with the specified name from this builder.
-		 *
-		 * @param names The part name.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder remove(String...names) {
-			if (names != null)
-				for (int i = 0; i < names.length; i++)
-					remove(names[i]);
-			return this;
-		}
-
-		/**
-		 * Adds or replaces the part(s) with the same name.
-		 *
-		 * <p>
-		 * If no part with the same name is found the given part is added to the end of the list.
-		 *
-		 * @param value The parts to replace.  <jk>null</jk> values are ignored.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder set(NameValuePair value) {
-			if (value != null) {
-				boolean replaced = false;
-				for (int i = 0, j = entries.size(); i < j; i++) {
-					NameValuePair x = entries.get(i);
-					if (eq(x.getName(), value.getName())) {
-						if (replaced) {
-							entries.remove(i);
-							j--;
-						} else {
-							entries.set(i, value);
-							replaced = true;
-						}
-					}
-				}
-
-				if (! replaced)
-					entries.add(value);
-			}
-
-			return this;
-		}
-
-		/**
-		 * Adds or replaces the part(s) with the same name.
-		 *
-		 * <p>
-		 * If no part with the same name is found the given part is added to the end of the list.
-		 *
-		 * @param values The parts to replace.  <jk>null</jk> values are ignored.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder set(NameValuePair...values) {
-			if (values != null)
-				set(alist(values));
-			return this;
-		}
+				append(values[i]);
+		return this;
+	}
 
-		/**
-		 * Adds or replaces the part with the specified name.
-		 *
-		 * @param name The part name.
-		 * @param value The part value.
-		 * @return This object.
-		 */
-		public Builder set(String name, Object value) {
-			return set(createPart(name, value));
-		}
+	/**
+	 * Adds the specified parts to the end of the parts in this list.
+	 *
+	 * @param values The parts to add.  <jk>null</jk> values are ignored.
+	 * @return This object.
+	 */
+	@FluentSetter
+	public PartList append(List<NameValuePair> values) {
+		if (values != null)
+			values.forEach(x -> append(x));
+		return this;
+	}
 
-		/**
-		 * Adds or replaces the part with the specified name.
-		 *
-		 * @param name The part name.
-		 * @param value The part value.
-		 * @return This object.
-		 */
-		public Builder set(String name, Supplier<?> value) {
-			return set(createPart(name, value));
-		}
+	/**
+	 * Adds the specified part to the beginning of the parts in this list.
+	 *
+	 * @param value The part to add.  <jk>null</jk> values are ignored.
+	 * @return This object.
+	 */
+	@FluentSetter
+	public PartList prepend(NameValuePair value) {
+		if (value != null)
+			add(0, value);
+		return this;
+	}
 
-		/**
-		 * Adds or replaces the parts with the specified names.
-		 *
-		 * <p>
-		 * If no part with the same name is found the given part is added to the end of the list.
-		 *
-		 * @param values The parts to replace.  <jk>null</jk> values are ignored.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder set(List<? extends NameValuePair> values) {
-
-			if (values != null) {
-				for (int i1 = 0, j1 = values.size(); i1 < j1; i1++) {
-					NameValuePair p = values.get(i1);
-					if (p != null) {
-						for (int i2 = 0, j2 = entries.size(); i2 < j2; i2++) {
-							NameValuePair x = entries.get(i2);
-							if (eq(x.getName(), p.getName())) {
-								entries.remove(i2);
-								j2--;
-							}
-						}
-					}
-				}
+	/**
+	 * Appends the specified part to the beginning of this list.
+	 *
+	 * <p>
+	 * The part is added as a {@link BasicPart}.
+	 *
+	 * @param name The part name.
+	 * @param value The part value.
+	 * @return This object.
+	 */
+	public PartList prepend(String name, Object value) {
+		return prepend(createPart(name, value));
+	}
 
-				for (int i = 0, j = values.size(); i < j; i++) {
-					NameValuePair x = values.get(i);
-					if (x != null) {
-						entries.add(x);
-					}
-				}
-			}
+	/**
+	 * Appends the specified part to the beginning of this list using a value supplier.
+	 *
+	 * <p>
+	 * The part is added as a {@link BasicPart}.
+	 *
+	 * <p>
+	 * Value is re-evaluated on each call to {@link BasicPart#getValue()}.
+	 *
+	 * @param name The part name.
+	 * @param value The part value supplier.
+	 * @return This object.
+	 */
+	public PartList prepend(String name, Supplier<?> value) {
+		return prepend(createPart(name, value));
+	}
 
-			return this;
-		}
+	/**
+	 * Adds the specified parts to the beginning of the parts in this list.
+	 *
+	 * @param values The parts to add.  <jk>null</jk> values are ignored.
+	 * @return This object.
+	 */
+	@FluentSetter
+	public PartList prepend(NameValuePair...values) {
+		if (values != null)
+			prepend(alist(values));
+		return this;
+	}
 
-		/**
-		 * Sets a default value for a part.
-		 *
-		 * <p>
-		 * If no part with the same name is found, the given part is added to the end of the list.
-		 *
-		 * @param value The default part to set.  <jk>null</jk> values are ignored.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder setDefault(NameValuePair value) {
-			if (value != null) {
-				boolean replaced = false;
-				if (defaultEntries == null)
-					defaultEntries = list();
-				for (int i = 0, j = defaultEntries.size(); i < j; i++) {
-					NameValuePair x = defaultEntries.get(i);
-					if (eq(x.getName(), value.getName())) {
-						if (replaced) {
-							defaultEntries.remove(i);
-							j--;
-						} else {
-							defaultEntries.set(i, value);
-							replaced = true;
-						}
-					}
-				}
+	/**
+	 * Adds the specified parts to the beginning of the parts in this list.
+	 *
+	 * @param values The parts to add.  <jk>null</jk> values are ignored.
+	 * @return This object.
+	 */
+	@FluentSetter
+	public PartList prepend(List<NameValuePair> values) {
+		if (values != null)
+			addAll(0, values);
+		return this;
+	}
 
-				if (! replaced)
-					defaultEntries.add(value);
-			}
+	/**
+	 * Removes the specified part from this list.
+	 *
+	 * @param value The part to remove.  <jk>null</jk> values are ignored.
+	 * @return This object.
+	 */
+	@FluentSetter
+	public PartList remove(NameValuePair value) {
+		if (value != null)
+			removeIf(x -> eq(x.getName(), value.getName()) && eq(x.getValue(), value.getValue()));
+		return this;
+	}
 
-			return this;
-		}
+	/**
+	 * Removes the specified parts from this list.
+	 *
+	 * @param values The parts to remove.  <jk>null</jk> values are ignored.
+	 * @return This object.
+	 */
+	@FluentSetter
+	public PartList remove(NameValuePair...values) {
+		for (int i = 0; i < values.length; i++)
+			remove(values[i]);
+		return this;
+	}
 
-		/**
-		 * Sets default values for one or more parts.
-		 *
-		 * <p>
-		 * If no part with the same name is found the given part is added to the end of the list.
-		 *
-		 * @param values The default parts to set.  <jk>null</jk> values are ignored.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder setDefault(NameValuePair...values) {
-			if (values != null)
-				setDefault(alist(values));
-			return this;
-		}
+	/**
+	 * Removes the specified parts from this list.
+	 *
+	 * @param values The parts to remove.  <jk>null</jk> values are ignored.
+	 * @return This object.
+	 */
+	@FluentSetter
+	public PartList remove(List<NameValuePair> values) {
+		if (values != null)
+			values.forEach(x -> remove(x));
+		return this;
+	}
 
-		/**
-		 * Sets a default value for a part.
-		 *
-		 * @param name The part name.
-		 * @param value The part value.
-		 * @return This object.
-		 */
-		public Builder setDefault(String name, Object value) {
-			return setDefault(createPart(name, value));
-		}
+	/**
+	 * Removes the part with the specified name from this list.
+	 *
+	 * @param name The part name.
+	 * @return This object.
+	 */
+	@FluentSetter
+	public PartList remove(String name) {
+		removeIf(x -> eq(x.getName(), name));
+		return this;
+	}
 
-		/**
-		 * Sets a default value for a part.
-		 *
-		 * @param name The part name.
-		 * @param value The part value.
-		 * @return This object.
-		 */
-		public Builder setDefault(String name, Supplier<?> value) {
-			return setDefault(createPart(name, value));
-		}
+	/**
+	 * Removes the part with the specified name from this list.
+	 *
+	 * @param names The part name.
+	 * @return This object.
+	 */
+	@FluentSetter
+	public PartList remove(String...names) {
+		if (names != null)
+			for (int i = 0; i < names.length; i++)
+				remove(names[i]);
+		return this;
+	}
 
-		/**
-		 * Sets default values for one or more parts.
-		 *
-		 * <p>
-		 * If no part with the same name is found the given part is added to the end of the list.
-		 *
-		 * @param values The default parts to set.  <jk>null</jk> values are ignored.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder setDefault(List<? extends NameValuePair> values) {
-
-			if (values != null) {
-				if (defaultEntries == null)
-					defaultEntries = list();
-				for (int i1 = 0, j1 = values.size(); i1 < j1; i1++) {
-					NameValuePair p = values.get(i1);
-					if (p != null) {
-						for (int i2 = 0, j2 = defaultEntries.size(); i2 < j2; i2++) {
-							NameValuePair x = defaultEntries.get(i2);
-							if (eq(x.getName(), p.getName())) {
-								defaultEntries.remove(i2);
-								j2--;
-							}
-						}
+	/**
+	 * Adds or replaces the part(s) with the same name.
+	 *
+	 * <p>
+	 * If no part with the same name is found the given part is added to the end of the list.
+	 *
+	 * @param value The part to replace.  <jk>null</jk> values are ignored.
+	 * @return This object.
+	 */
+	@FluentSetter
+	public PartList set(NameValuePair value) {
+		if (value != null) {
+			boolean replaced = false;
+			for (int i = 0, j = size(); i < j; i++) {
+				NameValuePair x = get(i);
+				if (eq(x.getName(), value.getName())) {
+					if (replaced) {
+						remove(i);
+						j--;
+					} else {
+						set(i, value);
+						replaced = true;
 					}
 				}
-
-				values.forEach(x -> {
-					if (x != null)
-						defaultEntries.add(x);
-				});
-			}
-
-			return this;
-		}
-
-		/**
-		 * Adds the specify part to this list.
-		 *
-		 * @param flag
-		 * 	What to do with the part.
-		 * 	<br>Possible values:
-		 * 	<ul>
-		 * 		<li>{@link ListOperation#APPEND APPEND} - Calls {@link #append(NameValuePair)}.
-		 * 		<li>{@link ListOperation#PREPEND PREEND} - Calls {@link #prepend(NameValuePair)}.
-		 * 		<li>{@link ListOperation#SET REPLACE} - Calls {@link #set(NameValuePair)}.
-		 * 		<li>{@link ListOperation#DEFAULT DEFAULT} - Calls {@link #setDefault(NameValuePair)}.
-		 * 	</ul>
-		 * @param value The part to add.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder add(ListOperation flag, NameValuePair value) {
-			if (flag == ListOperation.APPEND)
-				return append(value);
-			if (flag == ListOperation.PREPEND)
-				return prepend(value);
-			if (flag == ListOperation.SET)
-				return set(value);
-			if (flag == ListOperation.DEFAULT)
-				return setDefault(value);
-			throw new BasicRuntimeException("Invalid value specified for flag parameter on add(flag,value) method: {0}", flag);
-		}
-
-		/**
-		 * Adds the specified parts to this list.
-		 *
-		 * @param flag
-		 * 	What to do with the part.
-		 * 	<br>Possible values:
-		 * 	<ul>
-		 * 		<li>{@link ListOperation#APPEND APPEND} - Calls {@link #append(NameValuePair[])}.
-		 * 		<li>{@link ListOperation#PREPEND PREEND} - Calls {@link #prepend(NameValuePair[])}.
-		 * 		<li>{@link ListOperation#SET REPLACE} - Calls {@link #set(NameValuePair[])}.
-		 * 		<li>{@link ListOperation#DEFAULT DEFAULT} - Calls {@link #setDefault(NameValuePair[])}.
-		 * 	</ul>
-		 * @param values The parts to add.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder add(ListOperation flag, NameValuePair...values) {
-			if (flag == ListOperation.APPEND)
-				return append(values);
-			if (flag == ListOperation.PREPEND)
-				return prepend(values);
-			if (flag == ListOperation.SET)
-				return set(values);
-			if (flag == ListOperation.DEFAULT)
-				return setDefault(values);
-			throw new BasicRuntimeException("Invalid value specified for flag parameter on add(flag,values) method: {0}", flag);
-		}
-
-		/**
-		 * Adds the specified part to this list.
-		 *
-		 * @param flag
-		 * 	What to do with the part.
-		 * 	<br>Possible values:
-		 * 	<ul>
-		 * 		<li>{@link ListOperation#APPEND APPEND} - Calls {@link #append(String,Object)}.
-		 * 		<li>{@link ListOperation#PREPEND PREEND} - Calls {@link #prepend(String,Object)}.
-		 * 		<li>{@link ListOperation#SET REPLACE} - Calls {@link #set(String,Object)}.
-		 * 		<li>{@link ListOperation#DEFAULT DEFAULT} - Calls {@link #setDefault(String,Object)}.
-		 * 	</ul>
-		 * @param name The part name.
-		 * @param value The part value.
-		 * @return This object.
-		 */
-		public Builder add(ListOperation flag, String name, Object value) {
-			if (flag == ListOperation.APPEND)
-				return append(name, value);
-			if (flag == ListOperation.PREPEND)
-				return prepend(name, value);
-			if (flag == ListOperation.SET)
-				return set(name, value);
-			if (flag == ListOperation.DEFAULT)
-				return setDefault(name, value);
-			throw new BasicRuntimeException("Invalid value specified for flag parameter on add(flag,name,value) method: {0}", flag);
-		}
-
-		/**
-		 * Adds the specified part to this list.
-		 *
-		 * @param flag
-		 * 	What to do with the part.
-		 * 	<br>Possible values:
-		 * 	<ul>
-		 * 		<li>{@link ListOperation#APPEND APPEND} - Calls {@link #append(String,Supplier)}.
-		 * 		<li>{@link ListOperation#PREPEND PREEND} - Calls {@link #prepend(String,Supplier)}.
-		 * 		<li>{@link ListOperation#SET REPLACE} - Calls {@link #set(String,Supplier)}.
-		 * 		<li>{@link ListOperation#DEFAULT DEFAULT} - Calls {@link #setDefault(String,Supplier)}.
-		 * 	</ul>
-		 * @param name The part name.
-		 * @param value The part value supplier.
-		 * @return This object.
-		 */
-		public Builder add(ListOperation flag, String name, Supplier<?> value) {
-			if (flag == ListOperation.APPEND)
-				return append(name, value);
-			if (flag == ListOperation.PREPEND)
-				return prepend(name, value);
-			if (flag == ListOperation.SET)
-				return set(name, value);
-			if (flag == ListOperation.DEFAULT)
-				return setDefault(name, value);
-			throw new BasicRuntimeException("Invalid value specified for flag parameter on add(flag,name,value) method: {0}", flag);
-		}
-
-		/**
-		 * Adds the specified parts to this list.
-		 *
-		 * @param flag
-		 * 	What to do with the part.
-		 * 	<br>Possible values:
-		 * 	<ul>
-		 * 		<li>{@link ListOperation#APPEND APPEND} - Calls {@link #append(String,Supplier)}.
-		 * 		<li>{@link ListOperation#PREPEND PREEND} - Calls {@link #prepend(String,Supplier)}.
-		 * 		<li>{@link ListOperation#SET REPLACE} - Calls {@link #set(String,Supplier)}.
-		 * 		<li>{@link ListOperation#DEFAULT DEFAULT} - Calls {@link #setDefault(String,Supplier)}.
-		 * 	</ul>
-		 * @param values The parts to add.
-		 * @return This object.
-		 */
-		@FluentSetter
-		public Builder add(ListOperation flag, List<NameValuePair> values) {
-			if (flag == ListOperation.APPEND)
-				return append(values);
-			if (flag == ListOperation.PREPEND)
-				return prepend(values);
-			if (flag == ListOperation.SET)
-				return set(values);
-			if (flag == ListOperation.DEFAULT)
-				return setDefault(values);
-			throw new BasicRuntimeException("Invalid value specified for flag parameter on add(flag,values) method: {0}", flag);
-		}
-
-		/**
-		 * Performs an action on all the parts in this list.
-		 *
-		 * <p>
-		 * This is the preferred method for iterating over parts as it does not involve
-		 * creation or copy of lists/arrays.
-		 *
-		 * @param action An action to perform on each element.
-		 * @return This object.
-		 */
-		public Builder forEach(Consumer<NameValuePair> action) {
-			for (int i = 0, j = entries.size(); i < j; i++)
-				action.accept(entries.get(i));
-			return this;
-		}
-
-		/**
-		 * Performs an action on the parts with the specified name in this list.
-		 *
-		 * <p>
-		 * This is the preferred method for iterating over parts as it does not involve
-		 * creation or copy of lists/arrays.
-		 *
-		 * @param name The part name.
-		 * @param action An action to perform on each element.
-		 * @return This object.
-		 */
-		public Builder forEach(String name, Consumer<NameValuePair> action) {
-			for (int i = 0, j = entries.size(); i < j; i++) {
-				NameValuePair x = entries.get(i);
-				if (eq(name, x.getName()))
-					action.accept(x);
-			}
-			return this;
-		}
-
-		private boolean isResolving() {
-			return varResolver != null;
-		}
-
-		private Supplier<Object> resolver(Object input) {
-			return ()->varResolver.resolve(stringify(unwrap(input)));
-		}
-
-		private Object unwrap(Object o) {
-			while (o instanceof Supplier)
-				o = ((Supplier<?>)o).get();
-			return o;
-		}
-
-		/**
-		 * Creates a new part out of the specified name/value pair.
-		 *
-		 * @param name The part name.
-		 * @param value The part value.
-		 * @return A new header.
-		 */
-		public NameValuePair createPart(String name, Object value) {
-			if (value instanceof Supplier<?>) {
-				Supplier<?> value2 = (Supplier<?>)value;
-				return isResolving() ? new BasicPart(name, resolver(value2)) : new BasicPart(name, value2);
-			}
-			return isResolving() ? new BasicPart(name, resolver(value)) : new BasicPart(name, value);
-		}
-
-		private boolean eq(String s1, String s2) {
-			return caseInsensitive ? StringUtils.eq(s1, s2) : StringUtils.eqic(s1, s2);
-		}
-
-		/**
-		 * Gets the first part with the given name.
-		 *
-		 * @param name The part name.
-		 * @return The first matching part, or {@link Optional#empty()} if not found.
-		 */
-		public Optional<NameValuePair> getFirst(String name) {
-			for (int i = 0; i < entries.size(); i++) {
-				NameValuePair x = entries.get(i);
-				if (eq(x.getName(), name))
-					return optional(x);
-			}
-			if (defaultEntries != null) {
-				for (int i = 0; i < defaultEntries.size(); i ++) {
-					NameValuePair x = defaultEntries.get(i);
-					if (eq(x.getName(), name))
-						return optional(x);
-				}
-			}
-			return empty();
-		}
-
-		/**
-		 * Gets the last part with the given name.
-		 *
-		 * @param name The part name.
-		 * @return The last matching part, or {@link Optional#empty()} if not found.
-		 */
-		public Optional<NameValuePair> getLast(String name) {
-			for (int i = entries.size() - 1; i >= 0; i--) {
-				NameValuePair x = entries.get(i);
-				if (eq(x.getName(), name))
-					return optional(x);
-			}
-			if (defaultEntries != null) {
-				for (int i = defaultEntries.size() - 1; i >= 0; i--) {
-					NameValuePair x = defaultEntries.get(i);
-					if (eq(x.getName(), name))
-						return optional(x);
-				}
 			}
-			return empty();
-		}
-
-		// <FluentSetters>
 
-		@Override /* GENERATED - org.apache.juneau.BeanBuilder */
-		public Builder impl(Object value) {
-			super.impl(value);
-			return this;
+			if (! replaced)
+				add(value);
 		}
 
-		@Override /* GENERATED - org.apache.juneau.BeanBuilder */
-		public Builder type(Class<?> value) {
-			super.type(value);
-			return this;
-		}
-
-		// </FluentSetters>
-
-		//-------------------------------------------------------------------------------------------------------------
-		// Other methods
-		//-------------------------------------------------------------------------------------------------------------
-
-		@Override /* Object */
-		public String toString() {
-			return "[" + join(entries, ", ") + "]";
-		}
+		return this;
 	}
 
-	//-----------------------------------------------------------------------------------------------------------------
-	// Instance
-	//-----------------------------------------------------------------------------------------------------------------
-
-	final boolean caseInsensitive;
-
 	/**
-	 * Constructor.
+	 * Adds or replaces the part(s) with the same name.
+	 *
+	 * <p>
+	 * If no part with the same name is found the given part is added to the end of the list.
 	 *
-	 * @param builder The builder containing the settings for this bean.
+	 * @param values The part to replace.  <jk>null</jk> values are ignored.
+	 * @return This object.
 	 */
-	public PartList(Builder builder) {
-		super(! builder.unmodifiable, builder.entries);
-
-		if (builder.defaultEntries != null) {
-			for (int i1 = 0, j1 = builder.defaultEntries.size(); i1 < j1; i1++) {
-				NameValuePair x = builder.defaultEntries.get(i1);
-				boolean exists = false;
-				for (int i2 = 0, j2 = builder.entries.size(); i2 < j2 && ! exists; i2++)
-					exists = eq(builder.entries.get(i2).getName(), x.getName());
-				if (! exists)
-					overrideAdd(x);
-			}
-		}
-		this.caseInsensitive = builder.caseInsensitive;
+	@FluentSetter
+	public PartList set(NameValuePair...values) {
+		if (values != null)
+			set(alist(values));
+		return this;
 	}
 
 	/**
-	 * Constructor.
+	 * Replaces the first occurrence of the parts with the same name.
 	 *
-	 * @param modifiable Whether this list should be modifiable.
-	 * @param parts
-	 * 	The parts to add to the list.
-	 * 	<br>Can be <jk>null</jk>.
-	 * 	<br><jk>null</jk> entries are ignored.
+	 * @param name The part name.
+	 * @param value The part value.
+	 * @return This object.
 	 */
-	public PartList(boolean modifiable, List<NameValuePair> parts) {
-		super(modifiable, parts);
-		caseInsensitive = false;
+	public PartList set(String name, Object value) {
+		return set(createPart(name, value));
 	}
 
 	/**
-	 * Constructor.
+	 * Replaces the first occurrence of the parts with the same name.
 	 *
-	 * @param modifiable Whether this list should be modifiable.
-	 * @param parts
-	 * 	The parts to add to the list.
-	 * 	<br><jk>null</jk> entries are ignored.
+	 * @param name The part name.
+	 * @param value The part value.
+	 * @return This object.
 	 */
-	public PartList(boolean modifiable, NameValuePair...parts) {
-		super(modifiable, Arrays.asList(parts));
-		caseInsensitive = false;
+	public PartList set(String name, Supplier<?> value) {
+		return set(createPart(name, value));
 	}
 
 	/**
-	 * Default constructor.
+	 * Replaces the first occurrence of the parts with the same name.
 	 *
-	 * @param modifiable Whether this list should be modifiable.
+	 * <p>
+	 * If no part with the same name is found the given part is added to the end of the list.
+	 *
+	 * @param values The parts to replace.  <jk>null</jk> values are ignored.
+	 * @return This object.
 	 */
-	public PartList(boolean modifiable) {
-		super(modifiable);
-		caseInsensitive = false;
+	@FluentSetter
+	public PartList set(List<NameValuePair> values) {
+
+		if (values != null) {
+			for (int i1 = 0, j1 = values.size(); i1 < j1; i1++) {
+				NameValuePair h = values.get(i1);
+				if (h != null) {
+					for (int i2 = 0, j2 = size(); i2 < j2; i2++) {
+						NameValuePair x = get(i2);
+						if (eq(x.getName(), h.getName())) {
+							remove(i2);
+							j2--;
+						}
+					}
+				}
+			}
+
+			for (int i = 0, j = values.size(); i < j; i++) {
+				NameValuePair x = values.get(i);
+				if (x != null) {
+					add(x);
+				}
+			}
+		}
+
+		return this;
 	}
 
 	/**
-	 * Default constructor.
+	 * Gets the first part with the given name.
+	 *
+	 * <p>
+	 * Part name comparison is case sensitive by default.
+	 *
+	 * @param name The part name.
+	 * @return The first matching part, or {@link Optional#empty()} if not found.
 	 */
-	public PartList() {
-		super(true);
-		caseInsensitive = false;
+	public Optional<NameValuePair> getFirst(String name) {
+		for (int i = 0; i < size(); i++) {
+			NameValuePair x = get(i);
+			if (eq(x.getName(), name))
+				return optional(x);
+		}
+		return empty();
 	}
 
 	/**
-	 * Returns a builder initialized with the contents of this bean.
+	 * Gets the last part with the given name.
+	 *
+	 * <p>
+	 * Part name comparison is case sensitive by default.
 	 *
-	 * @return A new builder object.
+	 * @param name The part name.
+	 * @return The last matching part, or {@link Optional#empty()} if not found.
 	 */
-	public Builder copy() {
-		return new Builder(this);
+	public Optional<NameValuePair> getLast(String name) {
+		for (int i = size() - 1; i >= 0; i--) {
+			NameValuePair x = get(i);
+			if (eq(x.getName(), name))
+				return optional(x);
+		}
+		return empty();
 	}
 
 	/**
@@ -1216,7 +652,7 @@ public class PartList extends ControlledArrayList<NameValuePair> {
 			sb.append(rest.get(i).getValue());
 		}
 
-		return optional(new BasicPart(name, sb.toString()));
+		return optional(new BasicStringPart(name, sb.toString()));
 	}
 
 	/**
@@ -1302,17 +738,20 @@ public class PartList extends ControlledArrayList<NameValuePair> {
 	}
 
 	/**
-	 * Gets all of the parts contained within this list.
+	 * Gets all of the parts.
 	 *
 	 * <p>
 	 * The returned array maintains the relative order in which the parts were added.
 	 * Each call creates a new array not backed by this list.
 	 *
-	 * @return
-	 * 	An array of all the parts in this list, or an empty array if no parts are present.
+	 * <p>
+	 * As a general rule, it's more efficient to use the other methods with consumers to
+	 * get parts.
+	 *
+	 * @return An array containing all parts, never <jk>null</jk>.
 	 */
 	public NameValuePair[] getAll() {
-		return size() == 0 ? EMPTY_ARRAY : toArray(new NameValuePair[size()]);
+		return stream().toArray(NameValuePair[]::new);
 	}
 
 	/**
@@ -1320,59 +759,24 @@ public class PartList extends ControlledArrayList<NameValuePair> {
 	 *
 	 * <p>
 	 * The returned array maintains the relative order in which the parts were added.
+	 * Part name comparison is case sensitive by default.
 	 * Parts with null values are ignored.
 	 * Each call creates a new array not backed by this list.
 	 *
-	 * @param name The part name.
-	 *
-	 * @return An array containing all matching parts, or an empty array if none are found.
-	 */
-	public NameValuePair[] getAll(String name) {
-		ArrayBuilder<NameValuePair> b = ArrayBuilder.of(NameValuePair.class).filter(NOT_NULL);
-		for (NameValuePair x : this)
-			if (eq(x.getName(), name))
-				b.add(x);
-		return b.orElse(EMPTY_ARRAY);
-	}
-
-	/**
-	 * Gets the first part with the given name.
-	 *
 	 * <p>
-	 * Part name comparison is case insensitive.
+	 * As a general rule, it's more efficient to use the other methods with consumers to
+	 * get parts.
 	 *
 	 * @param name The part name.
-	 * @return The first matching part, or <jk>null</jk> if not found.
-	 */
-	public Optional<NameValuePair> getFirst(String name) {
-		for (int i = 0; i < size(); i++) {
-			NameValuePair x = get(i);
-			if (eq(x.getName(), name))
-				return optional(x);
-		}
-		return empty();
-	}
-
-	/**
-	 * Gets the last part with the given name.
 	 *
-	 * <p>
-	 * Part name comparison is case insensitive.
-	 *
-	 * @param name The part name.
-	 * @return The last matching part, or <jk>null</jk> if not found.
+	 * @return An array containing all matching parts, never <jk>null</jk>.
 	 */
-	public Optional<NameValuePair> getLast(String name) {
-		for (int i = size() - 1; i >= 0; i--) {
-			NameValuePair x = get(i);
-			if (eq(x.getName(), name))
-				return optional(x);
-		}
-		return empty();
+	public NameValuePair[] getAll(String name) {
+		return stream().filter(x -> eq(x.getName(), name)).toArray(NameValuePair[]::new);
 	}
 
 	/**
-	 * Performs an action on the string values for all matching parts.
+	 * Performs an action on the values for all matching parts in this list.
 	 *
 	 * @param filter A predicate to apply to each element to determine if it should be included.  Can be <jk>null</jk>.
 	 * @param action An action to perform on each element.
@@ -1383,9 +787,9 @@ public class PartList extends ControlledArrayList<NameValuePair> {
 	}
 
 	/**
-	 * Performs an action on the string values for all parts with the specified name.
+	 * Performs an action on the values of all matching parts in this list.
 	 *
-	 * @param name The header name.
+	 * @param name The part name.
 	 * @param action An action to perform on each element.
 	 * @return This object.
 	 */
@@ -1400,9 +804,7 @@ public class PartList extends ControlledArrayList<NameValuePair> {
 	 * @return An array containing all values.  Never <jk>null</jk>.
 	 */
 	public String[] getValues(String name) {
-		ArrayBuilder<String> b = ArrayBuilder.of(String.class).size(1);
-		forEach(name, x -> b.add(x.getValue()));
-		return b.orElse(EMPTY_STRING_ARRAY);
+		return stream().filter(x -> eq(x.getName(), name)).map(x -> x.getValue()).toArray(String[]::new);
 	}
 
 	/**
@@ -1415,11 +817,7 @@ public class PartList extends ControlledArrayList<NameValuePair> {
 	 * @return <jk>true</jk> if at least one part with the name is present.
 	 */
 	public boolean contains(String name) {
-		for (NameValuePair x : this) {
-			if (eq(x.getName(), name))
-				return true;
-		}
-		return false;
+		return stream().anyMatch(x -> eq(x.getName(), name));
 	}
 
 	/**
@@ -1428,7 +826,7 @@ public class PartList extends ControlledArrayList<NameValuePair> {
 	 * @return A new iterator over this list of parts.
 	 */
 	public PartIterator partIterator() {
-		return new BasicPartIterator(getAll(), null, caseInsensitive);
+		return new BasicPartIterator(toArray(new NameValuePair[0]), null, caseInsensitive);
 	}
 
 	/**
@@ -1439,7 +837,7 @@ public class PartList extends ControlledArrayList<NameValuePair> {
 	 * @return A new iterator over the matching parts in this list.
 	 */
 	public PartIterator partIterator(String name) {
-		return new BasicPartIterator(getAll(), name, caseInsensitive);
+		return new BasicPartIterator(getAll(name), name, caseInsensitive);
 	}
 
 	/**
@@ -1483,11 +881,35 @@ public class PartList extends ControlledArrayList<NameValuePair> {
 	 * @return This object.
 	 */
 	public Stream<NameValuePair> stream(String name) {
-		return Arrays.stream(getAll(name)).filter(x->eq(name, x.getName()));
+		return stream().filter(x->eq(name, x.getName()));
+	}
+
+	//-------------------------------------------------------------------------------------------------------------
+	// Other methods
+	//-------------------------------------------------------------------------------------------------------------
+
+	private NameValuePair createPart(String name, Object value) {
+		boolean isResolving = varResolver != null;
+
+		if (value instanceof Supplier<?>) {
+			Supplier<?> value2 = (Supplier<?>)value;
+			return isResolving ? new BasicPart(name, resolver(value2)) : new BasicPart(name, value2);
+		}
+		return isResolving ? new BasicPart(name, resolver(value)) : new BasicPart(name, value);
+	}
+
+	private Supplier<Object> resolver(Object input) {
+		return ()->varResolver.resolve(stringify(unwrap(input)));
+	}
+
+	private Object unwrap(Object o) {
+		while (o instanceof Supplier)
+			o = ((Supplier<?>)o).get();
+		return o;
 	}
 
 	private boolean eq(String s1, String s2) {
-		return StringUtils.eq(caseInsensitive, s1, s2);
+		return caseInsensitive ? StringUtils.eqic(s1, s2) : StringUtils.eq(s1, s2);
 	}
 
 	/**
@@ -1508,4 +930,4 @@ public class PartList extends ControlledArrayList<NameValuePair> {
 		});
 		return sb.toString();
 	}
-}
+}
\ No newline at end of file
diff --git a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/resource/BasicResource.java b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/resource/BasicResource.java
index 204335041..f9f71cfa7 100644
--- a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/resource/BasicResource.java
+++ b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/resource/BasicResource.java
@@ -65,7 +65,7 @@ public class BasicResource implements HttpResource {
 	 */
 	public BasicResource(HttpResourceBuilder<?> builder) {
 		this.entity = builder.entity();
-		this.headers = builder.headers();
+		this.headers = builder.headers.copy();
 	}
 
 	/**
diff --git a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/resource/HttpResourceBuilder.java b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/resource/HttpResourceBuilder.java
index 0137ecf44..447d83da6 100644
--- a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/resource/HttpResourceBuilder.java
+++ b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/resource/HttpResourceBuilder.java
@@ -37,8 +37,7 @@ import org.apache.juneau.internal.*;
 @FluentSetters(returns="HttpResourceBuilder<T>")
 public class HttpResourceBuilder<T extends BasicResource> {
 
-	HeaderList headers = HeaderList.EMPTY;
-	HeaderList.Builder headersBuilder;
+	HeaderList headers = HeaderList.create();
 
 	BasicHttpEntity entity;
 	HttpEntityBuilder<?> entityBuilder;
@@ -92,14 +91,6 @@ public class HttpResourceBuilder<T extends BasicResource> {
 		}
 	}
 
-	HeaderList headers() {
-		if (headersBuilder != null)
-			return headersBuilder.build();
-		if (headers == null)
-			return HeaderList.EMPTY;
-		return headers;
-	}
-
 	BasicHttpEntity entity() {
 		if (entityBuilder != null)
 			return entityBuilder.build();
@@ -281,12 +272,8 @@ public class HttpResourceBuilder<T extends BasicResource> {
 	 *
 	 * @return The underlying builder for the headers.
 	 */
-	public HeaderList.Builder getHeaders() {
-		if (headersBuilder == null) {
-			headersBuilder = headers == null ? HeaderList.create() : headers.copy();
-			headers = null;
-		}
-		return headersBuilder;
+	public HeaderList getHeaders() {
+		return headers;
 	}
 
 	/**
@@ -298,7 +285,6 @@ public class HttpResourceBuilder<T extends BasicResource> {
 	@FluentSetter
 	public HttpResourceBuilder<T> headers(HeaderList value) {
 		headers = value;
-		headersBuilder = null;
 		return this;
 	}
 
@@ -310,7 +296,7 @@ public class HttpResourceBuilder<T extends BasicResource> {
 	 */
 	public HttpResourceBuilder<T> header(Header value) {
 		if (value != null)
-			getHeaders().append(value);
+			headers.append(value);
 		return this;
 	}
 
@@ -326,7 +312,7 @@ public class HttpResourceBuilder<T extends BasicResource> {
 	 */
 	public HttpResourceBuilder<T> header(String name, String value) {
 		if (name != null && value != null)
-			getHeaders().append(name, value);
+			headers.append(name, value);
 		return this;
 	}
 
@@ -349,7 +335,7 @@ public class HttpResourceBuilder<T extends BasicResource> {
 					else if (n.equalsIgnoreCase("content-length"))
 						contentLength(Long.parseLong(v));
 					else
-						getHeaders().append(h);
+						headers.append(h);
 				}
 			}
 		}
@@ -363,7 +349,7 @@ public class HttpResourceBuilder<T extends BasicResource> {
 	 * @return This object.
 	 */
 	public HttpResourceBuilder<T> headers(List<Header> values) {
-		getHeaders().append(values);
+		headers.append(values);
 		return this;
 	}
 
diff --git a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/response/BasicHttpException.java b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/response/BasicHttpException.java
index c7b2fb343..26a0639d9 100644
--- a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/response/BasicHttpException.java
+++ b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/response/BasicHttpException.java
@@ -57,8 +57,8 @@ public class BasicHttpException extends BasicRuntimeException implements HttpRes
 
 	HeaderList headers;
 	BasicStatusLine statusLine;
-	HeaderList.Builder headersBuilder;
 	BasicStatusLine.Builder statusLineBuilder;
+	private int TODO;
 	HttpEntity content;
 
 	/**
@@ -79,7 +79,7 @@ public class BasicHttpException extends BasicRuntimeException implements HttpRes
 	 */
 	public BasicHttpException(HttpExceptionBuilder<?> builder) {
 		super(builder);
-		headers = builder.buildHeaders();
+		headers = builder.headers;
 		statusLine = builder.buildStatusLine();
 		content = builder.content;
 	}
@@ -250,72 +250,72 @@ public class BasicHttpException extends BasicRuntimeException implements HttpRes
 
 	@Override /* HttpMessage */
 	public boolean containsHeader(String name) {
-		return headers().contains(name);
+		return headers.contains(name);
 	}
 
 	@Override /* HttpMessage */
 	public Header[] getHeaders(String name) {
-		return headers().getAll(name);
+		return headers.getAll(name);
 	}
 
 	@Override /* HttpMessage */
 	public Header getFirstHeader(String name) {
-		return headers().getFirst(name).orElse(null);
+		return headers.getFirst(name).orElse(null);
 	}
 
 	@Override /* HttpMessage */
 	public Header getLastHeader(String name) {
-		return headers().getLast(name).orElse(null);
+		return headers.getLast(name).orElse(null);
 	}
 
 	@Override /* HttpMessage */
 	public Header[] getAllHeaders() {
-		return headers().getAll();
+		return headers.getAll();
 	}
 
 	@Override /* HttpMessage */
 	public void addHeader(Header value) {
-		headersBuilder().append(value).build();
+		headers.append(value);
 	}
 
 	@Override /* HttpMessage */
 	public void addHeader(String name, String value) {
-		headersBuilder().append(name, value).build();
+		headers.append(name, value);
 	}
 
 	@Override /* HttpMessage */
 	public void setHeader(Header value) {
-		headersBuilder().set(value).build();
+		headers.set(value);
 	}
 
 	@Override /* HttpMessage */
 	public void setHeader(String name, String value) {
-		headersBuilder().set(name, value).build();
+		headers.set(name, value);
 	}
 
 	@Override /* HttpMessage */
 	public void setHeaders(Header[] values) {
-		headersBuilder().clear().append(values).build();
+		headers.removeAll().append(values);
 	}
 
 	@Override /* HttpMessage */
 	public void removeHeader(Header value) {
-		headersBuilder().remove(value).build();
+		headers.remove(value);
 	}
 
 	@Override /* HttpMessage */
 	public void removeHeaders(String name) {
-		headersBuilder().remove(name).build();
+		headers.remove(name);
 	}
 
 	@Override /* HttpMessage */
 	public HeaderIterator headerIterator() {
-		return headers().headerIterator();
+		return headers.headerIterator();
 	}
 
 	@Override /* HttpMessage */
 	public HeaderIterator headerIterator(String name) {
-		return headers().headerIterator(name);
+		return headers.headerIterator(name);
 	}
 
 	@SuppressWarnings("deprecation")
@@ -391,14 +391,6 @@ public class BasicHttpException extends BasicRuntimeException implements HttpRes
 		return statusLine;
 	}
 
-	private HeaderList headers() {
-		if (headers == null) {
-			headers = headersBuilder.build();
-			headersBuilder = null;
-		}
-		return headers;
-	}
-
 	private BasicStatusLine.Builder statusLineBuilder() {
 		assertModifiable();
 		if (statusLineBuilder == null) {
@@ -407,13 +399,4 @@ public class BasicHttpException extends BasicRuntimeException implements HttpRes
 		}
 		return statusLineBuilder;
 	}
-
-	private HeaderList.Builder headersBuilder() {
-		assertModifiable();
-		if (headersBuilder == null) {
-			headersBuilder = headers.copy();
-			headers = null;
-		}
-		return headersBuilder;
-	}
 }
diff --git a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/response/BasicHttpResponse.java b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/response/BasicHttpResponse.java
index 9cebf3c0b..f398ec003 100644
--- a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/response/BasicHttpResponse.java
+++ b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/response/BasicHttpResponse.java
@@ -48,8 +48,8 @@ public class BasicHttpResponse implements HttpResponse {
 
 	HeaderList headers;
 	BasicStatusLine statusLine;
-	HeaderList.Builder headersBuilder;
 	BasicStatusLine.Builder statusLineBuilder;
+	private int TODO;
 	HttpEntity content;
 	final boolean unmodifiable;
 
@@ -70,7 +70,7 @@ public class BasicHttpResponse implements HttpResponse {
 	 * @param builder The builder containing the arguments for this bean.
 	 */
 	public BasicHttpResponse(HttpResponseBuilder<?> builder) {
-		headers = builder.buildHeaders();
+		headers = builder.headers;
 		statusLine = builder.buildStatusLine();
 		content = builder.content;
 		unmodifiable = builder.unmodifiable;
@@ -112,7 +112,7 @@ public class BasicHttpResponse implements HttpResponse {
 
 	@Override /* Object */
 	public String toString() {
-		StringBuilder sb = new StringBuilder().append(statusLine()).append(' ').append(headers());
+		StringBuilder sb = new StringBuilder().append(statusLine()).append(' ').append(headers);
 		if (content != null)
 			sb.append(' ').append(content);
 		return sb.toString();
@@ -125,72 +125,72 @@ public class BasicHttpResponse implements HttpResponse {
 
 	@Override /* HttpMessage */
 	public boolean containsHeader(String name) {
-		return headers().contains(name);
+		return headers.contains(name);
 	}
 
 	@Override /* HttpMessage */
 	public Header[] getHeaders(String name) {
-		return headers().getAll(name);
+		return headers.getAll(name);
 	}
 
 	@Override /* HttpMessage */
 	public Header getFirstHeader(String name) {
-		return headers().getFirst(name).orElse(null);
+		return headers.getFirst(name).orElse(null);
 	}
 
 	@Override /* HttpMessage */
 	public Header getLastHeader(String name) {
-		return headers().getLast(name).orElse(null);
+		return headers.getLast(name).orElse(null);
 	}
 
 	@Override /* HttpMessage */
 	public Header[] getAllHeaders() {
-		return headers().getAll();
+		return headers.getAll();
 	}
 
 	@Override /* HttpMessage */
 	public void addHeader(Header value) {
-		headersBuilder().append(value).build();
+		headers.append(value);
 	}
 
 	@Override /* HttpMessage */
 	public void addHeader(String name, String value) {
-		headersBuilder().append(name, value).build();
+		headers.append(name, value);
 	}
 
 	@Override /* HttpMessage */
 	public void setHeader(Header value) {
-		headersBuilder().set(value).build();
+		headers.set(value);
 	}
 
 	@Override /* HttpMessage */
 	public void setHeader(String name, String value) {
-		headersBuilder().set(name, value).build();
+		headers.set(name, value);
 	}
 
 	@Override /* HttpMessage */
 	public void setHeaders(Header[] values) {
-		headersBuilder().clear().append(values).build();
+		headers.removeAll().append(values);
 	}
 
 	@Override /* HttpMessage */
 	public void removeHeader(Header value) {
-		headersBuilder().remove(value).build();
+		headers.remove(value);
 	}
 
 	@Override /* HttpMessage */
 	public void removeHeaders(String name) {
-		headersBuilder().remove(name).build();
+		headers.remove(name);
 	}
 
 	@Override /* HttpMessage */
 	public HeaderIterator headerIterator() {
-		return headers().headerIterator();
+		return headers.headerIterator();
 	}
 
 	@Override /* HttpMessage */
 	public HeaderIterator headerIterator(String name) {
-		return headers().headerIterator(name);
+		return headers.headerIterator(name);
 	}
 
 	@SuppressWarnings("deprecation")
@@ -266,14 +266,6 @@ public class BasicHttpResponse implements HttpResponse {
 		return statusLine;
 	}
 
-	private HeaderList headers() {
-		if (headers == null) {
-			headers = headersBuilder.build();
-			headersBuilder = null;
-		}
-		return headers;
-	}
-
 	private BasicStatusLine.Builder statusLineBuilder() {
 		assertModifiable();
 		if (statusLineBuilder == null) {
@@ -283,15 +275,6 @@ public class BasicHttpResponse implements HttpResponse {
 		return statusLineBuilder;
 	}
 
-	private HeaderList.Builder headersBuilder() {
-		assertModifiable();
-		if (headersBuilder == null) {
-			headersBuilder = headers.copy();
-			headers = null;
-		}
-		return headersBuilder;
-	}
-
 	/**
 	 * Throws an {@link UnsupportedOperationException} if the unmodifiable flag is set on this bean.
 	 */
diff --git a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/response/HttpExceptionBuilder.java b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/response/HttpExceptionBuilder.java
index 82749d30d..3546abc08 100644
--- a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/response/HttpExceptionBuilder.java
+++ b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/response/HttpExceptionBuilder.java
@@ -39,9 +39,9 @@ import org.apache.juneau.internal.*;
 public class HttpExceptionBuilder<T extends BasicHttpException> extends BasicRuntimeException.Builder {
 
 	BasicStatusLine statusLine;
-	HeaderList headers = HeaderList.EMPTY;
+	HeaderList headers = HeaderList.create();
 	BasicStatusLine.Builder statusLineBuilder;
-	HeaderList.Builder headersBuilder;
+	private int TODO;
 	HttpEntity content;
 
 	private final Class<? extends BasicHttpException> implClass;
@@ -106,14 +106,6 @@ public class HttpExceptionBuilder<T extends BasicHttpException> extends BasicRun
 		return statusLine;
 	}
 
-	HeaderList buildHeaders() {
-		if (headersBuilder != null)
-			return headersBuilder.build();
-		if (headers == null)
-			return HeaderList.EMPTY;
-		return headers;
-	}
-
 	//-----------------------------------------------------------------------------------------------------------------
 	// BasicStatusLine setters.
 	//-----------------------------------------------------------------------------------------------------------------
@@ -232,12 +224,8 @@ public class HttpExceptionBuilder<T extends BasicHttpException> extends BasicRun
 	 *
 	 * @return The underlying builder for the headers.
 	 */
-	public HeaderList.Builder getHeaders() {
-		if (headersBuilder == null) {
-			headersBuilder = headers == null ? HeaderList.create() : headers.copy();
-			headers = null;
-		}
-		return headersBuilder;
+	public HeaderList getHeaders() {
+		return headers;
 	}
 
 	/**
@@ -249,7 +237,6 @@ public class HttpExceptionBuilder<T extends BasicHttpException> extends BasicRun
 	@FluentSetter
 	public HttpExceptionBuilder<T> headers(HeaderList value) {
 		headers = value;
-		headersBuilder = null;
 		return this;
 	}
 
@@ -260,7 +247,7 @@ public class HttpExceptionBuilder<T extends BasicHttpException> extends BasicRun
 	 * @return This object.
 	 */
 	public HttpExceptionBuilder<T> header(Header value) {
-		getHeaders().append(value);
+		headers.append(value);
 		return this;
 	}
 
@@ -272,7 +259,7 @@ public class HttpExceptionBuilder<T extends BasicHttpException> extends BasicRun
 	 * @return This object.
 	 */
 	public HttpExceptionBuilder<T> header(String name, String value) {
-		getHeaders().append(name, value);
+		headers.append(name, value);
 		return this;
 	}
 
@@ -283,7 +270,7 @@ public class HttpExceptionBuilder<T extends BasicHttpException> extends BasicRun
 	 * @return This object.
 	 */
 	public HttpExceptionBuilder<T> headers(Header...values) {
-		getHeaders().append(values);
+		headers.append(values);
 		return this;
 	}
 
@@ -294,7 +281,7 @@ public class HttpExceptionBuilder<T extends BasicHttpException> extends BasicRun
 	 * @return This object.
 	 */
 	public HttpExceptionBuilder<T> headers(List<Header> values) {
-		getHeaders().append(values);
+		headers.append(values);
 		return this;
 	}
 
diff --git a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/response/HttpResponseBuilder.java b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/response/HttpResponseBuilder.java
index 4f93f6193..9be5f34ba 100644
--- a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/response/HttpResponseBuilder.java
+++ b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/response/HttpResponseBuilder.java
@@ -38,9 +38,9 @@ import org.apache.juneau.internal.*;
 public class HttpResponseBuilder<T extends BasicHttpResponse> {
 
 	BasicStatusLine statusLine;
-	HeaderList headers = HeaderList.EMPTY;
+	HeaderList headers = HeaderList.create();
 	BasicStatusLine.Builder statusLineBuilder;
-	HeaderList.Builder headersBuilder;
+	private int TODO;
 	HttpEntity content;
 	boolean unmodifiable;
 
@@ -101,14 +101,6 @@ public class HttpResponseBuilder<T extends BasicHttpResponse> {
 		return statusLine;
 	}
 
-	HeaderList buildHeaders() {
-		if (headersBuilder != null)
-			return headersBuilder.build();
-		if (headers == null)
-			return HeaderList.EMPTY;
-		return headers;
-	}
-
 	/**
 	 * Specifies whether this exception should be unmodifiable after creation.
 	 *
@@ -238,12 +230,8 @@ public class HttpResponseBuilder<T extends BasicHttpResponse> {
 	 *
 	 * @return The underlying builder for the headers.
 	 */
-	public HeaderList.Builder getHeaders() {
-		if (headersBuilder == null) {
-			headersBuilder = headers == null ? HeaderList.create() : headers.copy();
-			headers = null;
-		}
-		return headersBuilder;
+	public HeaderList getHeaders() {
+		return headers;
 	}
 
 	/**
@@ -255,7 +243,6 @@ public class HttpResponseBuilder<T extends BasicHttpResponse> {
 	@FluentSetter
 	public HttpResponseBuilder<T> headers(HeaderList value) {
 		headers = value;
-		headersBuilder = null;
 		return this;
 	}
 
@@ -266,7 +253,7 @@ public class HttpResponseBuilder<T extends BasicHttpResponse> {
 	 * @return This object.
 	 */
 	public HttpResponseBuilder<T> header(Header value) {
-		getHeaders().append(value);
+		headers.append(value);
 		return this;
 	}
 
@@ -278,7 +265,7 @@ public class HttpResponseBuilder<T extends BasicHttpResponse> {
 	 * @return This object.
 	 */
 	public HttpResponseBuilder<T> header(String name, String value) {
-		getHeaders().append(name, value);
+		headers.append(name, value);
 		return this;
 	}
 
@@ -289,7 +276,7 @@ public class HttpResponseBuilder<T extends BasicHttpResponse> {
 	 * @return This object.
 	 */
 	public HttpResponseBuilder<T> headers(Header...values) {
-		getHeaders().append(values);
+		headers.append(values);
 		return this;
 	}
 
@@ -300,7 +287,7 @@ public class HttpResponseBuilder<T extends BasicHttpResponse> {
 	 * @return This object.
 	 */
 	public HttpResponseBuilder<T> headers(List<Header> values) {
-		getHeaders().append(values);
+		headers.append(values);
 		return this;
 	}
 
@@ -312,7 +299,7 @@ public class HttpResponseBuilder<T extends BasicHttpResponse> {
 	 */
 	@FluentSetter
 	public HttpResponseBuilder<T> location(URI value) {
-		getHeaders().set(Location.of(value));
+		headers.set(Location.of(value));
 		return this;
 	}
 
@@ -324,7 +311,7 @@ public class HttpResponseBuilder<T extends BasicHttpResponse> {
 	 */
 	@FluentSetter
 	public HttpResponseBuilder<T> location(String value) {
-		getHeaders().set(Location.of(value));
+		headers.set(Location.of(value));
 		return this;
 	}
 
diff --git a/juneau-rest/juneau-rest-mock/src/main/java/org/apache/juneau/rest/mock/MockRestClient.java b/juneau-rest/juneau-rest-mock/src/main/java/org/apache/juneau/rest/mock/MockRestClient.java
index 45678faaf..78fe4c816 100644
--- a/juneau-rest/juneau-rest-mock/src/main/java/org/apache/juneau/rest/mock/MockRestClient.java
+++ b/juneau-rest/juneau-rest-mock/src/main/java/org/apache/juneau/rest/mock/MockRestClient.java
@@ -1969,7 +1969,7 @@ public class MockRestClient extends RestClient implements HttpClientConnection {
 	}
 
 	@Override /* RestClient */
-	public MockRestRequest formPostPairs(Object url, Object...parameters) throws RestCallException {
+	public MockRestRequest formPostPairs(Object url, String...parameters) throws RestCallException {
 		return (MockRestRequest)super.formPostPairs(url, parameters);
 	}
 
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
index 2edf6f153..8e92629a7 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
@@ -253,8 +253,9 @@ public class RestContext extends Context {
 		private HttpPartParser.Creator partParser;
 		private JsonSchemaGenerator.Builder jsonSchemaGenerator;
 		private BeanCreator<StaticFiles> staticFiles;
-		private HeaderList.Builder defaultRequestHeaders, defaultResponseHeaders;
+		private HeaderList defaultRequestHeaders, defaultResponseHeaders;
 		private NamedAttributeList.Builder defaultRequestAttributes;
+		private int TODO;
 		private RestOpArgList.Builder restOpArgs;
 		private BeanCreator<DebugEnablement> debugEnablement;
 		private MethodList startCallMethods, endCallMethods, postInitMethods, postInitChildFirstMethods, destroyMethods, preCallMethods, postCallMethods;
@@ -2789,11 +2790,11 @@ public class RestContext extends Context {
 		//-----------------------------------------------------------------------------------------------------------------
 
 		/**
-		 * Returns the default request headers sub-builder.
+		 * Returns the default request headers.
 		 *
-		 * @return The default request headers sub-builder.
+		 * @return The default request headers.
 		 */
-		public HeaderList.Builder defaultRequestHeaders() {
+		public HeaderList defaultRequestHeaders() {
 			if (defaultRequestHeaders == null)
 				defaultRequestHeaders = createDefaultRequestHeaders(beanStore(), resource());
 			return defaultRequestHeaders;
@@ -2899,24 +2900,24 @@ public class RestContext extends Context {
 		 * 	The REST servlet/bean instance that this context is defined against.
 		 * @return A new default request headers sub-builder.
 		 */
-		protected HeaderList.Builder createDefaultRequestHeaders(BeanStore beanStore, Supplier<?> resource) {
+		protected HeaderList createDefaultRequestHeaders(BeanStore beanStore, Supplier<?> resource) {
 
 			// Default value.
-			Value<HeaderList.Builder> v = Value.of(
+			Value<HeaderList> v = Value.of(
 				HeaderList.create()
 			);
 
 			// Replace with bean from bean store.
 			beanStore
 				.getBean(HeaderList.class, "defaultRequestHeaders")
-				.ifPresent(x -> v.get().impl(x));
+				.ifPresent(x -> v.set(x));
 
 			// Replace with bean from:  @RestInject(name="defaultRequestHeaders") public [static] HeaderList xxx(<args>)
 			beanStore
 				.createMethodFinder(HeaderList.class)
-				.addBean(HeaderList.Builder.class, v.get())
+				.addBean(HeaderList.class, v.get())
 				.find(x -> isRestBeanMethod(x, "defaultRequestHeaders"))
-				.run(x -> v.get().impl(x));
+				.run(x -> v.set(x));
 
 			return v.get();
 		}
@@ -2926,11 +2927,11 @@ public class RestContext extends Context {
 		//-----------------------------------------------------------------------------------------------------------------
 
 		/**
-		 * Returns the default response headers sub-builder.
+		 * Returns the default response headers.
 		 *
-		 * @return The default response headers sub-builder.
+		 * @return The default response headers.
 		 */
-		public HeaderList.Builder defaultResponseHeaders() {
+		public HeaderList defaultResponseHeaders() {
 			if (defaultResponseHeaders == null)
 				defaultResponseHeaders = createDefaultResponseHeaders(beanStore(), resource());
 			return defaultResponseHeaders;
@@ -3002,24 +3003,24 @@ public class RestContext extends Context {
 		 * 	The REST servlet/bean instance that this context is defined against.
 		 * @return A new default response headers sub-builder.
 		 */
-		protected HeaderList.Builder createDefaultResponseHeaders(BeanStore beanStore, Supplier<?> resource) {
+		protected HeaderList createDefaultResponseHeaders(BeanStore beanStore, Supplier<?> resource) {
 
 			// Default value.
-			Value<HeaderList.Builder> v = Value.of(
+			Value<HeaderList> v = Value.of(
 				HeaderList.create()
 			);
 
 			// Replace with bean from bean store.
 			beanStore
 				.getBean(HeaderList.class, "defaultResponseHeaders")
-				.ifPresent(x -> v.get().impl(x));
+				.ifPresent(x -> v.set(x));
 
 			// Replace with bean from:  @RestInject(name="defaultResponseHeaders") public [static] HeaderList xxx(<args>)
 			beanStore
 				.createMethodFinder(HeaderList.class)
-				.addBean(HeaderList.Builder.class, v.get())
+				.addBean(HeaderList.class, v.get())
 				.find(x -> isRestBeanMethod(x, "defaultResponseHeaders"))
-				.run(x -> v.get().impl(x));
+				.run(x -> v.set(x));
 
 			return v.get();
 		}
@@ -5513,8 +5514,8 @@ public class RestContext extends Context {
 			jsonSchemaGenerator = bs.add(JsonSchemaGenerator.class, builder.jsonSchemaGenerator().build());
 			staticFiles = bs.add(StaticFiles.class, builder.staticFiles().orElse(null));
 			bs.add(FileFinder.class, staticFiles);
-			defaultRequestHeaders = bs.add(HeaderList.class, builder.defaultRequestHeaders().build(), "defaultRequestHeaders");
-			defaultResponseHeaders = bs.add(HeaderList.class, builder.defaultResponseHeaders().build(), "defaultResponseHeaders");
+			defaultRequestHeaders = bs.add(HeaderList.class, builder.defaultRequestHeaders(), "defaultRequestHeaders");
+			defaultResponseHeaders = bs.add(HeaderList.class, builder.defaultResponseHeaders(), "defaultResponseHeaders");
 			defaultRequestAttributes = bs.add(NamedAttributeList.class, builder.defaultRequestAttributes().build(), "defaultRequestAttributes");
 			restOpArgs = builder.restOpArgs().build().asArray();
 			debugEnablement = bs.add(DebugEnablement.class, builder.debugEnablement().orElse(null));
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContext.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContext.java
index 853365ce7..ee99b730d 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContext.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContext.java
@@ -122,9 +122,10 @@ public class RestOpContext extends Context implements Comparable<RestOpContext>
 		private RestMatcherList.Builder matchers;
 		private JsonSchemaGenerator.Builder jsonSchemaGenerator;
 
-		PartList.Builder defaultRequestFormData, defaultRequestQueryData;
+		PartList defaultRequestFormData, defaultRequestQueryData;
 		NamedAttributeList.Builder defaultRequestAttributes;
-		HeaderList.Builder defaultRequestHeaders, defaultResponseHeaders;
+		private int TODO;
+		HeaderList defaultRequestHeaders, defaultResponseHeaders;
 		RestMatcherList.Builder restMatchers;
 		List<MediaType> produces, consumes;
 		Set<String> roleGuard, rolesDeclared;
@@ -1330,11 +1331,11 @@ public class RestOpContext extends Context implements Comparable<RestOpContext>
 		//-----------------------------------------------------------------------------------------------------------------
 
 		/**
-		 * Returns the default request headers sub-builder.
+		 * Returns the default request headers.
 		 *
-		 * @return The default request headers sub-builder.
+		 * @return The default request headers.
 		 */
-		public HeaderList.Builder defaultRequestHeaders() {
+		public HeaderList defaultRequestHeaders() {
 			if (defaultRequestHeaders == null)
 				defaultRequestHeaders = createDefaultRequestHeaders(beanStore(), parent, resource());
 			return defaultRequestHeaders;
@@ -1358,7 +1359,7 @@ public class RestOpContext extends Context implements Comparable<RestOpContext>
 		}
 
 		/**
-		 * Instantiates the default request headers sub-builder.
+		 * Instantiates the default request headers.
 		 *
 		 * @param beanStore
 		 * 	The factory used for creating beans and retrieving injected beans.
@@ -1368,19 +1369,19 @@ public class RestOpContext extends Context implements Comparable<RestOpContext>
 		 * 	The REST servlet/bean instance that this context is defined against.
 		 * @return A new default request headers sub-builder.
 		 */
-		protected HeaderList.Builder createDefaultRequestHeaders(BeanStore beanStore, RestContext.Builder parent, Supplier<?> resource) {
+		protected HeaderList createDefaultRequestHeaders(BeanStore beanStore, RestContext.Builder parent, Supplier<?> resource) {
 
-			Value<HeaderList.Builder> v = Value.of(
+			Value<HeaderList> v = Value.of(
 				parent.defaultRequestHeaders().copy()
 			);
 
 			// Replace with bean from:  @RestInject(name="defaultRequestHeaders",methodScope="foo") public [static] HeaderList xxx(<args>)
 			BeanStore
 				.of(beanStore, resource)
-				.addBean(HeaderList.Builder.class, v.get())
+				.addBean(HeaderList.class, v.get())
 				.createMethodFinder(HeaderList.class, resource)
 				.find(x -> matches(x, "defaultRequestHeaders"))
-				.run(x -> v.get().impl(x));
+				.run(x -> v.set(x));
 
 			return v.get();
 		}
@@ -1390,11 +1391,11 @@ public class RestOpContext extends Context implements Comparable<RestOpContext>
 		//-----------------------------------------------------------------------------------------------------------------
 
 		/**
-		 * Returns the default response headers sub-builder.
+		 * Returns the default response headers.
 		 *
-		 * @return The default response headers sub-builder.
+		 * @return The default response headers.
 		 */
-		public HeaderList.Builder defaultResponseHeaders() {
+		public HeaderList defaultResponseHeaders() {
 			if (defaultResponseHeaders == null)
 				defaultResponseHeaders = createDefaultResponseHeaders(beanStore(), parent, resource());
 			return defaultResponseHeaders;
@@ -1418,7 +1419,7 @@ public class RestOpContext extends Context implements Comparable<RestOpContext>
 		}
 
 		/**
-		 * Instantiates the default response headers sub-builder.
+		 * Instantiates the default response headers.
 		 *
 		 * @param beanStore
 		 * 	The factory used for creating beans and retrieving injected beans.
@@ -1428,19 +1429,19 @@ public class RestOpContext extends Context implements Comparable<RestOpContext>
 		 * 	The REST servlet/bean instance that this context is defined against.
 		 * @return A new default response headers sub-builder.
 		 */
-		protected HeaderList.Builder createDefaultResponseHeaders(BeanStore beanStore, RestContext.Builder parent, Supplier<?> resource) {
+		protected HeaderList createDefaultResponseHeaders(BeanStore beanStore, RestContext.Builder parent, Supplier<?> resource) {
 
-			Value<HeaderList.Builder> v = Value.of(
+			Value<HeaderList> v = Value.of(
 				parent.defaultResponseHeaders().copy()
 			);
 
 			// Replace with bean from:  @RestInject(name="defaultResponseHeaders",methodScope="foo") public [static] HeaderList xxx(<args>)
 			BeanStore
 				.of(beanStore, resource)
-				.addBean(HeaderList.Builder.class, v.get())
+				.addBean(HeaderList.class, v.get())
 				.createMethodFinder(HeaderList.class, resource)
 				.find(x -> matches(x, "defaultResponseHeaders"))
-				.run(x -> v.get().impl(x));
+				.run(x -> v.set(x));
 
 			return v.get();
 		}
@@ -1510,11 +1511,11 @@ public class RestOpContext extends Context implements Comparable<RestOpContext>
 		//-----------------------------------------------------------------------------------------------------------------
 
 		/**
-		 * Returns the default request query data sub-builder.
+		 * Returns the default request query data.
 		 *
-		 * @return The default request query data sub-builder.
+		 * @return The default request query data.
 		 */
-		public PartList.Builder defaultRequestQueryData() {
+		public PartList defaultRequestQueryData() {
 			if (defaultRequestQueryData == null)
 				defaultRequestQueryData = createDefaultRequestQueryData(beanStore(), parent, resource());
 			return defaultRequestQueryData;
@@ -1538,7 +1539,7 @@ public class RestOpContext extends Context implements Comparable<RestOpContext>
 		}
 
 		/**
-		 * Instantiates the default request query data sub-builder.
+		 * Instantiates the default request query data.
 		 *
 		 * @param beanStore
 		 * 	The factory used for creating beans and retrieving injected beans.
@@ -1548,19 +1549,19 @@ public class RestOpContext extends Context implements Comparable<RestOpContext>
 		 * 	The REST servlet/bean instance that this context is defined against.
 		 * @return A new default request query data sub-builder.
 		 */
-		protected PartList.Builder createDefaultRequestQueryData(BeanStore beanStore, RestContext.Builder parent, Supplier<?> resource) {
+		protected PartList createDefaultRequestQueryData(BeanStore beanStore, RestContext.Builder parent, Supplier<?> resource) {
 
-			Value<PartList.Builder> v = Value.of(
+			Value<PartList> v = Value.of(
 				PartList.create()
 			);
 
 			// Replace with bean from:  @RestInject(name="defaultRequestQueryData",methodScope="foo") public [static] PartList xxx(<args>)
 			BeanStore
 				.of(beanStore, resource)
-				.addBean(PartList.Builder.class, v.get())
+				.addBean(PartList.class, v.get())
 				.createMethodFinder(PartList.class, resource)
 				.find(x -> matches(x, "defaultRequestQueryData"))
-				.run(x -> v.get().impl(x));
+				.run(x -> v.set(x));
 
 			return v.get();
 		}
@@ -1570,11 +1571,11 @@ public class RestOpContext extends Context implements Comparable<RestOpContext>
 		//-----------------------------------------------------------------------------------------------------------------
 
 		/**
-		 * Returns the default request form data sub-builder.
+		 * Returns the default request form data.
 		 *
-		 * @return The default request form data sub-builder.
+		 * @return The default request form data.
 		 */
-		public PartList.Builder defaultRequestFormData() {
+		public PartList defaultRequestFormData() {
 			if (defaultRequestFormData == null)
 				defaultRequestFormData = createDefaultRequestFormData(beanStore(), parent, resource());
 			return defaultRequestFormData;
@@ -1598,7 +1599,7 @@ public class RestOpContext extends Context implements Comparable<RestOpContext>
 		}
 
 		/**
-		 * Instantiates the default request form data sub-builder.
+		 * Instantiates the default request form data.
 		 *
 		 * @param beanStore
 		 * 	The factory used for creating beans and retrieving injected beans.
@@ -1608,19 +1609,19 @@ public class RestOpContext extends Context implements Comparable<RestOpContext>
 		 * 	The REST servlet/bean instance that this context is defined against.
 		 * @return A new default request form data sub-builder.
 		 */
-		protected PartList.Builder createDefaultRequestFormData(BeanStore beanStore, RestContext.Builder parent, Supplier<?> resource) {
+		protected PartList createDefaultRequestFormData(BeanStore beanStore, RestContext.Builder parent, Supplier<?> resource) {
 
-			Value<PartList.Builder> v = Value.of(
+			Value<PartList> v = Value.of(
 				PartList.create()
 			);
 
 			// Replace with bean from:  @RestInject(name="defaultRequestFormData",methodScope="foo") public [static] PartList xxx(<args>)
 			BeanStore
 				.of(beanStore, resource)
-				.addBean(PartList.Builder.class, v.get())
+				.addBean(PartList.class, v.get())
 				.createMethodFinder(PartList.class, resource)
 				.find(x -> matches(x, "defaultRequestFormData"))
-				.run(x -> v.get().impl(x));
+				.run(x -> v.set(x));
 
 			return v.get();
 		}
@@ -2301,10 +2302,10 @@ public class RestOpContext extends Context implements Comparable<RestOpContext>
 			supportedAcceptTypes = unmodifiable(builder.produces != null ? builder.produces : serializers.getSupportedMediaTypes());
 			supportedContentTypes = unmodifiable(builder.consumes != null ? builder.consumes : parsers.getSupportedMediaTypes());
 
-			defaultRequestHeaders = builder.defaultRequestHeaders().build();
-			defaultResponseHeaders = builder.defaultResponseHeaders().build();
-			defaultRequestQueryData = builder.defaultRequestQueryData().build();
-			defaultRequestFormData = builder.defaultRequestFormData().build();
+			defaultRequestHeaders = builder.defaultRequestHeaders();
+			defaultResponseHeaders = builder.defaultResponseHeaders();
+			defaultRequestQueryData = builder.defaultRequestQueryData();
+			defaultRequestFormData = builder.defaultRequestFormData();
 			defaultRequestAttributes = builder.defaultRequestAttributes().build();
 
 			int _hierarchyDepth = 0;
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/header/HeaderList_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/header/HeaderList_Test.java
index cad508411..101f82e91 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/header/HeaderList_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/header/HeaderList_Test.java
@@ -46,25 +46,25 @@ public class HeaderList_Test {
 
 	@Test
 	public void a01_basic() {
-		HeaderList.Builder x = HeaderList.create();
+		HeaderList x = HeaderList.create();
 
-		assertObject(x.build()).isString("[]");
+		assertObject(x).isString("[]");
 		x.append(FOO_1);
-		assertObject(x.build()).isString("[Foo: 1]");
+		assertObject(x).isString("[Foo: 1]");
 		x.append(FOO_2);
-		assertObject(x.build()).isString("[Foo: 1, Foo: 2]");
+		assertObject(x).isString("[Foo: 1, Foo: 2]");
 		x.append(HeaderList.of().getAll());
-		assertObject(x.build()).isString("[Foo: 1, Foo: 2]");
+		assertObject(x).isString("[Foo: 1, Foo: 2]");
 		x.append(HeaderList.of(FOO_3).getAll());
-		assertObject(x.build()).isString("[Foo: 1, Foo: 2, Foo: 3]");
+		assertObject(x).isString("[Foo: 1, Foo: 2, Foo: 3]");
 		x.append(HeaderList.of(FOO_4, FOO_5).getAll());
-		assertObject(x.build()).isString("[Foo: 1, Foo: 2, Foo: 3, Foo: 4, Foo: 5]");
+		assertObject(x).isString("[Foo: 1, Foo: 2, Foo: 3, Foo: 4, Foo: 5]");
 		x.append(HeaderList.of(FOO_6, FOO_7).getAll());
-		assertObject(x.build()).isString("[Foo: 1, Foo: 2, Foo: 3, Foo: 4, Foo: 5, Foo: 6, Foo: 7]");
+		assertObject(x).isString("[Foo: 1, Foo: 2, Foo: 3, Foo: 4, Foo: 5, Foo: 6, Foo: 7]");
 		x.append((Header)null);
-		assertObject(x.build()).isString("[Foo: 1, Foo: 2, Foo: 3, Foo: 4, Foo: 5, Foo: 6, Foo: 7]");
+		assertObject(x).isString("[Foo: 1, Foo: 2, Foo: 3, Foo: 4, Foo: 5, Foo: 6, Foo: 7]");
 		x.append((List<Header>)null);
-		assertObject(x.build()).isString("[Foo: 1, Foo: 2, Foo: 3, Foo: 4, Foo: 5, Foo: 6, Foo: 7]");
+		assertObject(x).isString("[Foo: 1, Foo: 2, Foo: 3, Foo: 4, Foo: 5, Foo: 6, Foo: 7]");
 
 		assertObject(new HeaderList.Void()).isString("[]");
 	}
@@ -74,10 +74,10 @@ public class HeaderList_Test {
 		HeaderList x;
 
 		x = headerList(FOO_1, FOO_2, null);
-		assertObject(x).isString("[Foo: 1, Foo: 2, null]");
+		assertObject(x).isString("[Foo: 1, Foo: 2]");
 
 		x = headerList(alist(FOO_1, FOO_2, null));
-		assertObject(x).isString("[Foo: 1, Foo: 2, null]");
+		assertObject(x).isString("[Foo: 1, Foo: 2]");
 
 		x = headerList("Foo","1","Foo","2");
 		assertObject(x).isString("[Foo: 1, Foo: 2]");
@@ -113,7 +113,7 @@ public class HeaderList_Test {
 	public void a03_addMethods() {
 		String pname = "HeaderSupplierTest.x";
 
-		HeaderList.Builder x = HeaderList.create().resolving();
+		HeaderList x = HeaderList.create().resolving();
 		System.setProperty(pname, "y");
 
 		x.append("X1","bar");
@@ -122,27 +122,27 @@ public class HeaderList_Test {
 		x.append("X4",()->"$S{"+pname+"}");
 		x.append(SerializedHeader.of("X5","bar",openApiSession(),null,false));
 
-		assertObject(x.build()).isString("[X1: bar, X2: y, X3: bar, X4: y, X5: bar]");
+		assertObject(x).isString("[X1: bar, X2: y, X3: bar, X4: y, X5: bar]");
 
 		System.setProperty(pname, "z");
 
-		assertObject(x.build()).isString("[X1: bar, X2: z, X3: bar, X4: z, X5: bar]");
+		assertObject(x).isString("[X1: bar, X2: z, X3: bar, X4: z, X5: bar]");
 
 		System.clearProperty(pname);
 	}
 
 	@Test
 	public void a04_toArrayMethods() {
-		HeaderList.Builder x = HeaderList
+		HeaderList x = HeaderList
 			.create()
 			.append("X1","1")
 			.append(headerList("X2","2").getAll());
-		assertObject(x.build()).isString("[X1: 1, X2: 2]");
+		assertObject(x).isString("[X1: 1, X2: 2]");
 	}
 
 	@Test
 	public void a05_copy() {
-		HeaderList x = HeaderList.of(FOO_1).copy().build();
+		HeaderList x = HeaderList.of(FOO_1).copy();
 		assertObject(x).isString("[Foo: 1]");
 	}
 
@@ -291,7 +291,7 @@ public class HeaderList_Test {
 
 	@Test
 	public void a18_caseSensitive() {
-		HeaderList x = HeaderList.create().caseSensitive().append(FOO_1, FOO_2, X_x).build();
+		HeaderList x = HeaderList.create().caseSensitive(true).append(FOO_1, FOO_2, X_x);
 		assertArray(x.getAll("Foo")).isString("[Foo: 1, Foo: 2]");
 		assertArray(x.getAll("FOO")).isString("[]");
 	}
@@ -308,15 +308,15 @@ public class HeaderList_Test {
 
 	@Test
 	public void b01_builder_clear() {
-		HeaderList.Builder x = HeaderList.create();
+		HeaderList x = HeaderList.create();
 		x.append(FOO_1);
 		x.clear();
-		assertObject(x.build()).isString("[]");
+		assertObject(x).isString("[]");
 	}
 
 	@Test
 	public void b02_builder_append() {
-		HeaderList x1 = HeaderList.create().append(FOO_1).build();
+		HeaderList x1 = HeaderList.create().append(FOO_1);
 		HeaderList x2 = HeaderList
 			.create()
 			.append()
@@ -328,14 +328,13 @@ public class HeaderList_Test {
 			.append("Bar", "b1")
 			.append("Bar", ()->"b2")
 			.append((List<Header>)null)
-			.append(alist(FOO_4))
-			.build();
+			.append(alist(FOO_4));
 		assertObject(x2).isString("[Foo: 1, Foo: 2, Foo: 3, Bar: b1, Bar: b2, Foo: 4]");
 	}
 
 	@Test
 	public void b03_builder_prepend() {
-		HeaderList x1 = HeaderList.create().append(FOO_1).build();
+		HeaderList x1 = HeaderList.create().append(FOO_1);
 		HeaderList x2 = HeaderList
 			.create()
 			.prepend()
@@ -347,8 +346,7 @@ public class HeaderList_Test {
 			.prepend("Bar", "b1")
 			.prepend("Bar", ()->"b2")
 			.prepend((List<Header>)null)
-			.prepend(alist(FOO_4))
-			.build();
+			.prepend(alist(FOO_4));
 		assertObject(x2).isString("[Foo: 4, Bar: b2, Bar: b1, Foo: 2, Foo: 3, Foo: 1]");
 	}
 
@@ -362,11 +360,10 @@ public class HeaderList_Test {
 			.remove(HeaderList.of(FOO_1))
 			.remove(FOO_2)
 			.remove(FOO_3, FOO_4)
-			.remove(alist(FOO_5))
-			.build();
+			.remove(alist(FOO_5));
 		assertObject(x).isString("[Foo: 6, Foo: 7]");
 
-		x = HeaderList.create().append(FOO_1,FOO_2).remove((String[])null).remove("Bar","Foo").build();
+		x = HeaderList.create().append(FOO_1,FOO_2).remove((String[])null).remove("Bar","Foo");
 		assertObject(x).isString("[]");
 	}
 
@@ -380,60 +377,52 @@ public class HeaderList_Test {
 			.set(FOO_3)
 			.set(BAR_1)
 			.set((Header)null)
-			.set((HeaderList)null)
-			.build();
+			.set((HeaderList)null);
 		assertObject(x).isString("[Foo: 3, Bar: 1]");
 
 		x = HeaderList
 			.create()
 			.append(BAR_1,FOO_1,FOO_2,BAR_2)
-			.set(FOO_3)
-			.build();
+			.set(FOO_3);
 		assertObject(x).isString("[Bar: 1, Foo: 3, Bar: 2]");
 
 		x = HeaderList
 			.create()
 			.append(BAR_1,FOO_1,FOO_2,BAR_2)
 			.set((Header[])null)
-			.set(null,FOO_3,FOO_4,FOO_5)
-			.build();
+			.set(null,FOO_3,FOO_4,FOO_5);
 		assertObject(x).isString("[Bar: 1, Bar: 2, Foo: 3, Foo: 4, Foo: 5]");
 
 		x = HeaderList
 			.create()
 			.append(BAR_1,FOO_1,FOO_2,BAR_2)
 			.set((List<Header>)null)
-			.set(alist(null,FOO_3,FOO_4,FOO_5))
-			.build();
+			.set(alist(null,FOO_3,FOO_4,FOO_5));
 		assertObject(x).isString("[Bar: 1, Bar: 2, Foo: 3, Foo: 4, Foo: 5]");
 
 		x = HeaderList
 			.create()
 			.append(BAR_1,FOO_1,FOO_2,BAR_2)
-			.set("FOO", "x")
-			.build();
+			.set("FOO", "x");
 		assertObject(x).isString("[Bar: 1, FOO: x, Bar: 2]");
 
 		x = HeaderList
 			.create()
 			.append(BAR_1,FOO_1,FOO_2,BAR_2)
-			.set("FOO", ()->"x")
-			.build();
+			.set("FOO", ()->"x");
 		assertObject(x).isString("[Bar: 1, FOO: x, Bar: 2]");
 
 		x = HeaderList
 			.create()
-			.caseSensitive()
+			.caseSensitive(true)
 			.append(BAR_1,FOO_1,FOO_2,BAR_2)
-			.set("FOO", ()->"x")
-			.build();
+			.set("FOO", ()->"x");
 		assertObject(x).isString("[Bar: 1, Foo: 1, Foo: 2, Bar: 2, FOO: x]");
 
 		x = HeaderList
 			.create()
 			.append(BAR_1,FOO_1,FOO_2,BAR_2)
-			.set(HeaderList.of(FOO_3,FOO_4))
-			.build();
+			.set(HeaderList.of(FOO_3,FOO_4));
 		assertObject(x).isString("[Bar: 1, Bar: 2, Foo: 3, Foo: 4]");
 	}
 
@@ -459,7 +448,7 @@ public class HeaderList_Test {
 		assertObject(i3.nextHeader()).isString("Accept: text/xml");
 		assertThrown(()->i3.nextHeader()).asMessage().is("Iteration already finished.");
 
-		HeaderList x2 = HeaderList.create().append(Accept.TEXT_XML,ContentType.TEXT_XML).caseSensitive().build();
+		HeaderList x2 = HeaderList.create().append(Accept.TEXT_XML,ContentType.TEXT_XML).caseSensitive(true);
 
 		HeaderIterator i4 = x2.headerIterator("Accept");
 		assertObject(i4.nextHeader()).isString("Accept: text/xml");
@@ -477,57 +466,55 @@ public class HeaderList_Test {
 
 	@Test
 	public void d01_defaultHeaders() {
-		HeaderList x1 = HeaderList.create().setDefault(Accept.TEXT_XML).build();
+		HeaderList x1 = HeaderList.create().setDefault(Accept.TEXT_XML);
 		assertObject(x1).isString("[Accept: text/xml]");
 
-		HeaderList x2 = HeaderList.create().set(Accept.TEXT_PLAIN).setDefault(Accept.TEXT_XML).build();
+		HeaderList x2 = HeaderList.create().set(Accept.TEXT_PLAIN).setDefault(Accept.TEXT_XML);
 		assertObject(x2).isString("[Accept: text/plain]");
 
-		HeaderList x3 = HeaderList.create().set(ContentType.TEXT_XML,Accept.TEXT_PLAIN,ContentType.TEXT_XML).setDefault(Accept.TEXT_XML).build();
+		HeaderList x3 = HeaderList.create().set(ContentType.TEXT_XML,Accept.TEXT_PLAIN,ContentType.TEXT_XML).setDefault(Accept.TEXT_XML);
 		assertObject(x3).isString("[Content-Type: text/xml, Accept: text/plain, Content-Type: text/xml]");
 
-		HeaderList x4 = HeaderList.create().set(ContentType.TEXT_XML,ContentType.TEXT_XML).setDefault(Accept.TEXT_XML).build();
+		HeaderList x4 = HeaderList.create().set(ContentType.TEXT_XML,ContentType.TEXT_XML).setDefault(Accept.TEXT_XML);
 		assertObject(x4).isString("[Content-Type: text/xml, Content-Type: text/xml, Accept: text/xml]");
 
-		HeaderList x5 = HeaderList.create().set(ContentType.TEXT_XML,ContentType.TEXT_XML).setDefault(Accept.TEXT_XML).setDefault(ContentType.TEXT_HTML).build();
+		HeaderList x5 = HeaderList.create().set(ContentType.TEXT_XML,ContentType.TEXT_XML).setDefault(Accept.TEXT_XML).setDefault(ContentType.TEXT_HTML);
 		assertObject(x5).isString("[Content-Type: text/xml, Content-Type: text/xml, Accept: text/xml]");
 
-		HeaderList x6 = HeaderList.create().setDefault(Accept.TEXT_XML,Accept.TEXT_PLAIN).build();
-		assertObject(x6).isString("[Accept: text/xml, Accept: text/plain]");
+		HeaderList x6 = HeaderList.create().setDefault(Accept.TEXT_XML,Accept.TEXT_PLAIN);
+		assertObject(x6).isString("[Accept: text/xml]");
 
-		HeaderList x7 = HeaderList.create().setDefault(Accept.TEXT_XML).setDefault(Accept.TEXT_PLAIN).build();
-		assertObject(x7).isString("[Accept: text/plain]");
+		HeaderList x7 = HeaderList.create().setDefault(Accept.TEXT_XML).setDefault(Accept.TEXT_PLAIN);
+		assertObject(x7).isString("[Accept: text/xml]");
 
-		HeaderList x8 = HeaderList.create().setDefault(Accept.TEXT_XML,Accept.TEXT_HTML).setDefault(Accept.TEXT_PLAIN).build();
-		assertObject(x8).isString("[Accept: text/plain]");
+		HeaderList x8 = HeaderList.create().setDefault(Accept.TEXT_XML,Accept.TEXT_HTML).setDefault(Accept.TEXT_PLAIN);
+		assertObject(x8).isString("[Accept: text/xml]");
 
 		HeaderList x9 = HeaderList
 			.create()
 			.setDefault((Header)null)
 			.setDefault((HeaderList)null)
 			.setDefault((Header[])null)
-			.setDefault((List<Header>)null)
-			.build();
+			.setDefault((List<Header>)null);
 		assertObject(x9).isString("[]");
 
-		HeaderList x10 = HeaderList.create().setDefault("Accept","text/xml").build();
+		HeaderList x10 = HeaderList.create().setDefault("Accept","text/xml");
 		assertObject(x10).isString("[Accept: text/xml]");
 
-		HeaderList x11 = HeaderList.create().setDefault("Accept",()->"text/xml").build();
+		HeaderList x11 = HeaderList.create().setDefault("Accept",()->"text/xml");
 		assertObject(x11).isString("[Accept: text/xml]");
 
-		HeaderList x12 = HeaderList.create().set(ContentType.TEXT_XML,ContentType.TEXT_PLAIN).setDefault(alist(Accept.TEXT_XML,ContentType.TEXT_HTML,null)).build();
+		HeaderList x12 = HeaderList.create().set(ContentType.TEXT_XML,ContentType.TEXT_PLAIN).setDefault(alist(Accept.TEXT_XML,ContentType.TEXT_HTML,null));
 		assertObject(x12).isString("[Content-Type: text/xml, Content-Type: text/plain, Accept: text/xml]");
 
-		HeaderList x13 = HeaderList.create().set(ContentType.TEXT_XML,ContentType.TEXT_PLAIN).setDefault(HeaderList.of(Accept.TEXT_XML,ContentType.TEXT_HTML,null)).build();
+		HeaderList x13 = HeaderList.create().set(ContentType.TEXT_XML,ContentType.TEXT_PLAIN).setDefault(HeaderList.of(Accept.TEXT_XML,ContentType.TEXT_HTML,null));
 		assertObject(x13).isString("[Content-Type: text/xml, Content-Type: text/plain, Accept: text/xml]");
 
 		HeaderList x14 = HeaderList.create().set(ContentType.TEXT_XML,ContentType.TEXT_PLAIN)
 			.setDefault(alist(Accept.TEXT_XML,ContentType.TEXT_HTML,null))
 			.setDefault(alist(Accept.TEXT_HTML,ContentType.TEXT_XML,null))
-			.setDefault(alist(Age.of(1)))
-			.build();
-		assertObject(x14).isString("[Content-Type: text/xml, Content-Type: text/plain, Accept: text/html, Age: 1]");
+			.setDefault(alist(Age.of(1)));
+		assertObject(x14).isString("[Content-Type: text/xml, Content-Type: text/plain, Accept: text/xml, Age: 1]");
 	}
 
 	//-----------------------------------------------------------------------------------------------------------------
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/part/PartList_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/part/PartList_Test.java
index c359f78af..d1c41361b 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/part/PartList_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/part/PartList_Test.java
@@ -72,25 +72,25 @@ public class PartList_Test {
 
 	@Test
 	public void a01_basic() {
-		PartList.Builder x = PartList.create();
+		PartList x = PartList.create();
 
-		assertObject(x.build()).isString("");
+		assertObject(x).isString("");
 		x.append(FOO_1);
-		assertObject(x.build()).isString("Foo=1");
+		assertObject(x).isString("Foo=1");
 		x.append(FOO_2);
-		assertObject(x.build()).isString("Foo=1&Foo=2");
+		assertObject(x).isString("Foo=1&Foo=2");
 		x.append(PartList.of().getAll());
-		assertObject(x.build()).isString("Foo=1&Foo=2");
+		assertObject(x).isString("Foo=1&Foo=2");
 		x.append(PartList.of(FOO_3).getAll());
-		assertObject(x.build()).isString("Foo=1&Foo=2&Foo=3");
+		assertObject(x).isString("Foo=1&Foo=2&Foo=3");
 		x.append(PartList.of(FOO_4, FOO_5).getAll());
-		assertObject(x.build()).isString("Foo=1&Foo=2&Foo=3&Foo=4&Foo=5");
+		assertObject(x).isString("Foo=1&Foo=2&Foo=3&Foo=4&Foo=5");
 		x.append(PartList.of(FOO_6, FOO_7).getAll());
-		assertObject(x.build()).isString("Foo=1&Foo=2&Foo=3&Foo=4&Foo=5&Foo=6&Foo=7");
+		assertObject(x).isString("Foo=1&Foo=2&Foo=3&Foo=4&Foo=5&Foo=6&Foo=7");
 		x.append((NameValuePair)null);
-		assertObject(x.build()).isString("Foo=1&Foo=2&Foo=3&Foo=4&Foo=5&Foo=6&Foo=7");
+		assertObject(x).isString("Foo=1&Foo=2&Foo=3&Foo=4&Foo=5&Foo=6&Foo=7");
 		x.append((List<NameValuePair>)null);
-		assertObject(x.build()).isString("Foo=1&Foo=2&Foo=3&Foo=4&Foo=5&Foo=6&Foo=7");
+		assertObject(x).isString("Foo=1&Foo=2&Foo=3&Foo=4&Foo=5&Foo=6&Foo=7");
 
 		assertObject(new PartList.Void()).isString("");
 	}
@@ -128,7 +128,7 @@ public class PartList_Test {
 		x = PartList.of(FOO_1);
 		assertObject(x).isString("Foo=1");
 
-		x = PartList.ofPairs((Object[])null);
+		x = PartList.ofPairs((String[])null);
 		assertObject(x).isString("");
 
 		x = PartList.ofPairs();
@@ -139,7 +139,7 @@ public class PartList_Test {
 	public void a03_addMethods() {
 		String pname = "PartSupplierTest.x";
 
-		PartList.Builder x = PartList.create().resolving();
+		PartList x = PartList.create().resolving();
 		System.setProperty(pname, "y");
 
 		x.append("X1","bar");
@@ -148,27 +148,27 @@ public class PartList_Test {
 		x.append("X4",()->"$S{"+pname+"}");
 		x.append(new SerializedPart("X5","bar",HttpPartType.QUERY,openApiSession(),null,false));
 
-		assertObject(x.build()).isString("X1=bar&X2=y&X3=bar&X4=y&X5=bar");
+		assertObject(x).isString("X1=bar&X2=y&X3=bar&X4=y&X5=bar");
 
 		System.setProperty(pname, "z");
 
-		assertObject(x.build()).isString("X1=bar&X2=z&X3=bar&X4=z&X5=bar");
+		assertObject(x).isString("X1=bar&X2=z&X3=bar&X4=z&X5=bar");
 
 		System.clearProperty(pname);
 	}
 
 	@Test
 	public void a04_toArrayMethods() {
-		PartList.Builder x = PartList
+		PartList x = PartList
 			.create()
 			.append("X1","1")
 			.append(partList("X2","2").getAll());
-		assertObject(x.build()).isString("X1=1&X2=2");
+		assertObject(x).isString("X1=1&X2=2");
 	}
 
 	@Test
 	public void a05_copy() {
-		PartList x = PartList.of(FOO_1).copy().build();
+		PartList x = PartList.of(FOO_1).copy();
 		assertObject(x).isString("Foo=1");
 	}
 
@@ -315,11 +315,11 @@ public class PartList_Test {
 
 	@Test
 	public void a18_caseSensitive() {
-		PartList x1 = PartList.create().append(FOO_1, FOO_2, X_x).build();
+		PartList x1 = PartList.create().append(FOO_1, FOO_2, X_x);
 		assertArray(x1.getAll("Foo")).isString("[Foo=1, Foo=2]");
 		assertArray(x1.getAll("FOO")).isString("[]");
 
-		PartList x2 = x1.copy().caseInsensitive().build();
+		PartList x2 = x1.copy().caseInsensitive(true);
 		assertArray(x2.getAll("Foo")).isString("[Foo=1, Foo=2]");
 		assertArray(x2.getAll("FOO")).isString("[Foo=1, Foo=2]");
 	}
@@ -336,15 +336,15 @@ public class PartList_Test {
 
 	@Test
 	public void b01_builder_clear() {
-		PartList.Builder x = PartList.create();
+		PartList x = PartList.create();
 		x.append(FOO_1);
 		x.clear();
-		assertObject(x.build()).isString("");
+		assertObject(x).isString("");
 	}
 
 	@Test
 	public void b02_builder_append() {
-		PartList x1 = PartList.create().append(FOO_1).build();
+		PartList x1 = PartList.create().append(FOO_1);
 		PartList x2 = PartList
 			.create()
 			.append()
@@ -356,14 +356,13 @@ public class PartList_Test {
 			.append("Bar", "b1")
 			.append("Bar", ()->"b2")
 			.append((List<NameValuePair>)null)
-			.append(alist(FOO_4))
-			.build();
+			.append(alist(FOO_4));
 		assertObject(x2).isString("Foo=1&Foo=2&Foo=3&Bar=b1&Bar=b2&Foo=4");
 	}
 
 	@Test
 	public void b03_builder_prepend() {
-		PartList x1 = PartList.create().append(FOO_1).build();
+		PartList x1 = PartList.create().append(FOO_1);
 		PartList x2 = PartList
 			.create()
 			.prepend()
@@ -375,8 +374,7 @@ public class PartList_Test {
 			.prepend("Bar", "b1")
 			.prepend("Bar", ()->"b2")
 			.prepend((List<NameValuePair>)null)
-			.prepend(alist(FOO_4))
-			.build();
+			.prepend(alist(FOO_4));
 		assertObject(x2).isString("Foo=4&Bar=b2&Bar=b1&Foo=2&Foo=3&Foo=1");
 	}
 
@@ -390,11 +388,10 @@ public class PartList_Test {
 			.remove(PartList.of(FOO_1))
 			.remove(FOO_2)
 			.remove(FOO_3, FOO_4)
-			.remove(alist(FOO_5))
-			.build();
+			.remove(alist(FOO_5));
 		assertObject(x).isString("Foo=6&Foo=7");
 
-		x = PartList.create().append(FOO_1,FOO_2).remove((String[])null).remove("Bar","Foo").build();
+		x = PartList.create().append(FOO_1,FOO_2).remove((String[])null).remove("Bar","Foo");
 		assertObject(x).isString("");
 	}
 
@@ -408,60 +405,53 @@ public class PartList_Test {
 			.set(FOO_3)
 			.set(BAR_1)
 			.set((NameValuePair)null)
-			.set((PartList)null)
-			.build();
+			.set((PartList)null);
 		assertObject(x).isString("Foo=3&Bar=1");
 
 		x = PartList
 			.create()
 			.append(BAR_1,FOO_1,FOO_2,BAR_2)
-			.set(FOO_3)
-			.build();
+			.set(FOO_3);
 		assertObject(x).isString("Bar=1&Foo=3&Bar=2");
 
 		x = PartList
 			.create()
 			.append(BAR_1,FOO_1,FOO_2,BAR_2)
 			.set((NameValuePair[])null)
-			.set(null,FOO_3,FOO_4,FOO_5)
-			.build();
+			.set(null,FOO_3,FOO_4,FOO_5);
 		assertObject(x).isString("Bar=1&Bar=2&Foo=3&Foo=4&Foo=5");
 
 		x = PartList
 			.create()
 			.append(BAR_1,FOO_1,FOO_2,BAR_2)
 			.set((List<NameValuePair>)null)
-			.set(alist(null,FOO_3,FOO_4,FOO_5))
-			.build();
+			.set(alist(null,FOO_3,FOO_4,FOO_5));
 		assertObject(x).isString("Bar=1&Bar=2&Foo=3&Foo=4&Foo=5");
 
 		x = PartList
 			.create()
 			.append(BAR_1,FOO_1,FOO_2,BAR_2)
-			.set("FOO", "x")
-			.build();
+			.caseInsensitive(true)
+			.set("FOO", "x");
 		assertObject(x).isString("Bar=1&FOO=x&Bar=2");
 
 		x = PartList
 			.create()
 			.append(BAR_1,FOO_1,FOO_2,BAR_2)
-			.set("FOO", ()->"x")
-			.build();
+			.caseInsensitive(true)
+			.set("FOO", ()->"x");
 		assertObject(x).isString("Bar=1&FOO=x&Bar=2");
 
 		x = PartList
 			.create()
-			.caseInsensitive()
 			.append(BAR_1,FOO_1,FOO_2,BAR_2)
-			.set("FOO", ()->"x")
-			.build();
+			.set("FOO", ()->"x");
 		assertObject(x).isString("Bar=1&Foo=1&Foo=2&Bar=2&FOO=x");
 
 		x = PartList
 			.create()
 			.append(BAR_1,FOO_1,FOO_2,BAR_2)
-			.set(PartList.of(FOO_3,FOO_4))
-			.build();
+			.set(PartList.of(FOO_3,FOO_4));
 		assertObject(x).isString("Bar=1&Bar=2&Foo=3&Foo=4");
 	}
 
@@ -490,7 +480,7 @@ public class PartList_Test {
 		PartIterator i4 = x.partIterator("A");
 		assertThrown(()->i4.next()).asMessage().is("Iteration already finished.");
 
-		PartList x2 = PartList.create().append(APart.X,BPart.X).caseInsensitive().build();
+		PartList x2 = PartList.create().append(APart.X,BPart.X).caseInsensitive(true);
 
 		PartIterator i5 = x2.partIterator("A");
 		assertObject(i5.next()).isString("a=x");
@@ -505,57 +495,52 @@ public class PartList_Test {
 
 	@Test
 	public void d01_defaultParts() {
-		PartList x1 = PartList.create().setDefault(APart.X).build();
+		PartList x1 = PartList.create().setDefault(APart.X);
 		assertObject(x1).isString("a=x");
 
-		PartList x2 = PartList.create().set(APart.X).setDefault(APart.Y).build();
+		PartList x2 = PartList.create().set(APart.X).setDefault(APart.Y);
 		assertObject(x2).isString("a=x");
 
-		PartList x3 = PartList.create().set(BPart.X,APart.X,BPart.Y).setDefault(APart.Y).build();
+		PartList x3 = PartList.create().set(BPart.X,APart.X,BPart.Y).setDefault(APart.Y);
 		assertObject(x3).isString("b=x&a=x&b=y");
 
-		PartList x4 = PartList.create().set(BPart.X,BPart.Y).setDefault(APart.X).build();
+		PartList x4 = PartList.create().set(BPart.X,BPart.Y).setDefault(APart.X);
 		assertObject(x4).isString("b=x&b=y&a=x");
 
-		PartList x5 = PartList.create().set(BPart.X,BPart.Y).setDefault(APart.X).setDefault(BPart.X).build();
+		PartList x5 = PartList.create().set(BPart.X,BPart.Y).setDefault(APart.X).setDefault(BPart.X);
 		assertObject(x5).isString("b=x&b=y&a=x");
 
-		PartList x6 = PartList.create().setDefault(APart.X,APart.Y).build();
-		assertObject(x6).isString("a=x&a=y");
-
-		PartList x7 = PartList.create().setDefault(APart.X).setDefault(APart.Y).build();
-		assertObject(x7).isString("a=y");
+		PartList x7 = PartList.create().setDefault(APart.X).setDefault(APart.Y);
+		assertObject(x7).isString("a=x");
 
-		PartList x8 = PartList.create().setDefault(APart.X,APart.Y).setDefault(APart.Z).build();
-		assertObject(x8).isString("a=z");
+		PartList x8 = PartList.create().setDefault(APart.X,APart.Y).setDefault(APart.Z);
+		assertObject(x8).isString("a=x");
 
 		PartList x9 = PartList
 			.create()
 			.setDefault((NameValuePair)null)
 			.setDefault((PartList)null)
 			.setDefault((NameValuePair[])null)
-			.setDefault((List<NameValuePair>)null)
-			.build();
+			.setDefault((List<NameValuePair>)null);
 		assertObject(x9).isString("");
 
-		PartList x10 = PartList.create().setDefault("a","x").build();
+		PartList x10 = PartList.create().setDefault("a","x");
 		assertObject(x10).isString("a=x");
 
-		PartList x11 = PartList.create().setDefault("a",()->"x").build();
+		PartList x11 = PartList.create().setDefault("a",()->"x");
 		assertObject(x11).isString("a=x");
 
-		PartList x12 = PartList.create().set(BPart.X,BPart.Y).setDefault(alist(APart.X,BPart.Z,null)).build();
+		PartList x12 = PartList.create().set(BPart.X,BPart.Y).setDefault(alist(APart.X,BPart.Z,null));
 		assertObject(x12).isString("b=x&b=y&a=x");
 
-		PartList x13 = PartList.create().set(BPart.X,BPart.Y).setDefault(PartList.of(APart.X,BPart.Z,null)).build();
+		PartList x13 = PartList.create().set(BPart.X,BPart.Y).setDefault(PartList.of(APart.X,BPart.Z,null));
 		assertObject(x13).isString("b=x&b=y&a=x");
 
 		PartList x14 = PartList.create().set(BPart.X,BPart.Y)
 			.setDefault(alist(APart.X,BPart.X,null))
 			.setDefault(alist(APart.Y,BPart.Y,null))
-			.setDefault(alist(CPart.X))
-			.build();
-		assertObject(x14).isString("b=x&b=y&a=y&c=x");
+			.setDefault(alist(CPart.X));
+		assertObject(x14).isString("b=x&b=y&a=x&c=x");
 	}
 
 	//-----------------------------------------------------------------------------------------------------------------
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_FormDataAnnotation_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_FormDataAnnotation_Test.java
index e92e5384d..8ce01eb85 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_FormDataAnnotation_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_FormDataAnnotation_Test.java
@@ -833,7 +833,7 @@ public class Remote_FormDataAnnotation_Test {
 	public static class K3a {
 		@FormData
 		public PartList getA() {
-			return parts("a1","v1","a2",123,"a3",null,"a4","");
+			return parts("a1","v1","a2","123","a3",null,"a4","");
 		}
 		@FormData("*")
 		public PartList getB() {
@@ -841,7 +841,7 @@ public class Remote_FormDataAnnotation_Test {
 		}
 		@FormData("*")
 		public PartList getC() {
-			return parts("c1","v1","c2",123,"c3",null,"c4","");
+			return parts("c1","v1","c2","123","c3",null,"c4","");
 		}
 		@FormData("*")
 		public PartList getD() {
@@ -849,7 +849,7 @@ public class Remote_FormDataAnnotation_Test {
 		}
 		@FormData
 		public NameValuePair[] getE() {
-			return parts("e1","v1","e2",123,"e3",null,"e4","").getAll();
+			return parts("e1","v1","e2","123","e3",null,"e4","").getAll();
 		}
 	}
 
@@ -972,7 +972,7 @@ public class Remote_FormDataAnnotation_Test {
 		return basicPart(name,val);
 	}
 
-	private static PartList parts(Object...pairs) {
+	private static PartList parts(String...pairs) {
 		return partList(pairs);
 	}
 
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_PathAnnotation_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_PathAnnotation_Test.java
index 1a8e64e46..cd516de99 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_PathAnnotation_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_PathAnnotation_Test.java
@@ -690,7 +690,7 @@ public class Remote_PathAnnotation_Test {
 	public static class K3a {
 		@Path("*") @Schema(aev=true)
 		public PartList getA() {
-			return parts("a1","v1","a2",123,"a3",null,"a4","");
+			return parts("a1","v1","a2","123","a3",null,"a4","");
 		}
 		@Path("/*")
 		public PartList getB() {
@@ -698,7 +698,7 @@ public class Remote_PathAnnotation_Test {
 		}
 		@Path("*") @Schema(aev=true)
 		public PartList getC() {
-			return parts("c1","v1","c2",123,"c3",null,"c4","");
+			return parts("c1","v1","c2","123","c3",null,"c4","");
 		}
 		@Path("/*")
 		public PartList getD() {
@@ -706,7 +706,7 @@ public class Remote_PathAnnotation_Test {
 		}
 		@Path @Schema(aev=true)
 		public NameValuePair[] getE() {
-			return parts("e1","v1","e2",123,"e3",null,"e4","").getAll();
+			return parts("e1","v1","e2","123","e3",null,"e4","").getAll();
 		}
 	}
 
@@ -773,7 +773,7 @@ public class Remote_PathAnnotation_Test {
 	// Helper methods.
 	//------------------------------------------------------------------------------------------------------------------
 
-	private static PartList parts(Object...pairs) {
+	private static PartList parts(String...pairs) {
 		return partList(pairs);
 	}
 
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_QueryAnnotation_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_QueryAnnotation_Test.java
index 43edf0866..2de0a6120 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_QueryAnnotation_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_QueryAnnotation_Test.java
@@ -798,7 +798,7 @@ public class Remote_QueryAnnotation_Test {
 	public static class K3a {
 		@Query() @Schema(aev=true)
 		public PartList getA() {
-			return parts("a1","v1","a2",123,"a3",null,"a4","");
+			return parts("a1","v1","a2","123","a3",null,"a4","");
 		}
 		@Query("*")
 		public PartList getB() {
@@ -806,7 +806,7 @@ public class Remote_QueryAnnotation_Test {
 		}
 		@Query("*") @Schema(aev=true)
 		public PartList getC() {
-			return parts("c1","v1","c2",123,"c3",null,"c4","");
+			return parts("c1","v1","c2","123","c3",null,"c4","");
 		}
 		@Query("*")
 		public PartList getD() {
@@ -814,7 +814,7 @@ public class Remote_QueryAnnotation_Test {
 		}
 		@Query() @Schema(aev=true)
 		public NameValuePair[] getE() {
-			return parts("e1","v1","e2",123,"e3",null,"e4","").getAll();
+			return parts("e1","v1","e2","123","e3",null,"e4","").getAll();
 		}
 	}
 
@@ -932,7 +932,7 @@ public class Remote_QueryAnnotation_Test {
 	// Helper methods.
 	//------------------------------------------------------------------------------------------------------------------
 
-	private static PartList parts(Object...pairs) {
+	private static PartList parts(String...pairs) {
 		return partList(pairs);
 	}
 
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_Test.java
index aae253a64..f82da20d4 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_Test.java
@@ -574,7 +574,7 @@ public class Remote_Test {
 			super(
 				create()
 				.append(basicHeader("Foo","baz"))
-				.append(HeaderList.create().append(basicHeader("Foo",()->"qux")).build().getAll())
+				.append(HeaderList.create().append(basicHeader("Foo",()->"qux")).getAll())
 			);
 		}
 	}
@@ -595,7 +595,7 @@ public class Remote_Test {
 	@SuppressWarnings("serial")
 	public static class F2b extends HeaderList {
 		public F2b() {
-			super(true);
+			super();
 			throw new NullPointerException("foo");
 		}
 	}
diff --git a/juneau-utest/src/test/java/org/apache/juneau/rest/Header_Accept_Test.java b/juneau-utest/src/test/java/org/apache/juneau/rest/Header_Accept_Test.java
index fcfaea7a1..a44fba746 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/rest/Header_Accept_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/rest/Header_Accept_Test.java
@@ -197,11 +197,11 @@ public class Header_Accept_Test {
 	//------------------------------------------------------------------------------------------------------------------
 
 	@Rest(
-		defaultRequestHeaders={" Accept : text/s2 "},
+		defaultRequestHeaders={" Accept : text/s3 "},
 		serializers={S1.class,S2.class}
 	)
 	public static class E {
-		@RestOp(defaultRequestHeaders={"Accept: text/s3"}, serializers=S3.class)
+		@RestOp(defaultRequestHeaders={"Accept: text/s2"}, serializers=S3.class)
 		public String put(@Content String in) {
 			return in;
 		}
@@ -234,11 +234,11 @@ public class Header_Accept_Test {
 	//------------------------------------------------------------------------------------------------------------------
 
 	@Rest(
-		defaultRequestHeaders={" Accept : text/s2 "},
+		defaultRequestHeaders={" Accept : text/s3 "},
 		serializers={S1.class,S2.class}
 	)
 	public static class F {
-		@RestOp(defaultRequestHeaders={"Accept: text/s3"}, serializers={SerializerSet.Inherit.class, S3.class})
+		@RestOp(defaultRequestHeaders={"Accept: text/s2"}, serializers={SerializerSet.Inherit.class, S3.class})
 		public String put(@Content String in) {
 			return in;
 		}
diff --git a/juneau-utest/src/test/java/org/apache/juneau/rest/Header_ContentType_Test.java b/juneau-utest/src/test/java/org/apache/juneau/rest/Header_ContentType_Test.java
index bfcfc1083..3af567f8e 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/rest/Header_ContentType_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/rest/Header_ContentType_Test.java
@@ -139,11 +139,11 @@ public class Header_ContentType_Test {
 	//------------------------------------------------------------------------------------------------------------------
 
 	@Rest(
-		defaultRequestHeaders={" Content-Type : text/p2 "},
+		defaultRequestHeaders={" Content-Type : text/p3 "},
 		parsers={P1.class,P2.class}
 	)
 	public static class D {
-		@RestPut(defaultRequestHeaders={"Content-Type: text/p3"}, parsers=P3.class)
+		@RestPut(defaultRequestHeaders={"Content-Type: text/p2"}, parsers=P3.class)
 		public String a(@Content String in) {
 			return in;
 		}
@@ -180,11 +180,11 @@ public class Header_ContentType_Test {
 	//------------------------------------------------------------------------------------------------------------------
 
 	@Rest(
-		defaultRequestHeaders={" Content-Type : text/p2 "},
+		defaultRequestHeaders={" Content-Type : text/p3 "},
 		parsers={P1.class,P2.class}
 	)
 	public static class E {
-		@RestPut(defaultRequestHeaders={"Content-Type: text/p3"}, parsers={Inherit.class,P3.class})
+		@RestPut(defaultRequestHeaders={"Content-Type: text/p2"}, parsers={Inherit.class,P3.class})
 		public String a(@Content String in) {
 			return in;
 		}
diff --git a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/FormData_Test.java b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/FormData_Test.java
index 4628da59f..504e927f3 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/FormData_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/FormData_Test.java
@@ -140,7 +140,7 @@ public class FormData_Test {
 		c.post("/c").contentType("application/x-www-form-urlencoded").run().assertContent("{f1:'1',f2:'2',f3:'3'}");
 		c.post("/c").contentType("application/x-www-form-urlencoded").formData("f1",4).formData("f2",5).formData("f3",6).run().assertContent("{f1:'4',f2:'5',f3:'6'}");
 
-		c.post("/d").contentType("application/x-www-form-urlencoded").run().assertContent("{f1:'4',f2:'5',f3:'6'}");
+		c.post("/d").contentType("application/x-www-form-urlencoded").run().assertContent("{f1:'1',f2:'2',f3:'3'}");
 		c.post("/d").contentType("application/x-www-form-urlencoded").formData("f1",7).formData("f2",8).formData("f3",9).run().assertContent("{f1:'7',f2:'8',f3:'9'}");
 	}
 
diff --git a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Query_Test.java b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Query_Test.java
index 0132cd83d..a4666d491 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Query_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Query_Test.java
@@ -221,7 +221,7 @@ public class Query_Test {
 		d.get("/b").queryData("f1",4).queryData("f2",5).queryData("f3",6).run().assertContent("{f1:'4',f2:'5',f3:'6'}");
 		d.get("/c").run().assertContent("{f1:'1',f2:'2',f3:'3'}");
 		d.get("/c").queryData("f1",4).queryData("f2",5).queryData("f3",6).run().assertContent("{f1:'4',f2:'5',f3:'6'}");
-		d.get("/d").run().assertContent("{f1:'4',f2:'5',f3:'6'}");
+		d.get("/d").run().assertContent("{f1:'1',f2:'2',f3:'3'}");
 		d.get("/d").queryData("f1",7).queryData("f2",8).queryData("f3",9).run().assertContent("{f1:'7',f2:'8',f3:'9'}");
 	}
 
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 cda8b5de3..03244e337 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
@@ -172,7 +172,7 @@ public class RestClient_BasicCalls_Test {
 			stringResource("{f:1}").build(),
 			bean,
 			stringEntity("{f:1}").build(),
-			parts("f",1)
+			parts("f","1")
 		);
 		for (Object body : bodies) {
 			client().headers(body instanceof PartList ? APPLICATION_FORM_URLENCODED : APPLICATION_JSON).build().put("/bean",body).run().assertContent("{f:1}");
@@ -215,7 +215,7 @@ public class RestClient_BasicCalls_Test {
 			stringResource("{f:1}").build(),
 			bean,
 			stringEntity("{f:1}").build(),
-			parts("f",1)
+			parts("f","1")
 		);
 		for (Object body : bodies) {
 			client().headers(body instanceof PartList ? APPLICATION_FORM_URLENCODED : APPLICATION_JSON).build().post("/bean",body).run().assertContent("{f:1}");
@@ -333,7 +333,7 @@ public class RestClient_BasicCalls_Test {
 
 	@Test
 	public void a21_formPostPairs() throws Exception {
-		client().build().formPostPairs("/bean",new StringBuilder("f"),new StringBuilder("1")).accept("application/json+simple").run().assertContent("{f:1}");
+		client().build().formPostPairs("/bean","f","1").accept("application/json+simple").run().assertContent("{f:1}");
 	}
 
 	@Test
@@ -355,7 +355,7 @@ public class RestClient_BasicCalls_Test {
 			stringResource("{f:1}").build(),
 			bean,
 			stringEntity("{f:1}").build(),
-			parts("f",1)
+			parts("f","1")
 		);
 		RestClient x = client().build();
 		for (Object body : bodies) {
@@ -392,7 +392,7 @@ public class RestClient_BasicCalls_Test {
 			stringResource("{f:1}").build(),
 			bean,
 			stringEntity("{f:1}").build(),
-			parts("f",1)
+			parts("f","1")
 		);
 		RestClient x = client().build();
 		for (Object body : bodies) {
@@ -443,7 +443,7 @@ public class RestClient_BasicCalls_Test {
 		return basicPart(name, val);
 	}
 
-	private static PartList parts(Object...pairs) {
+	private static PartList parts(String...pairs) {
 		return partList(pairs);
 	}
 
diff --git a/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_FormData_Test.java b/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_FormData_Test.java
index 041af5165..7a5a73081 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_FormData_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_FormData_Test.java
@@ -173,7 +173,7 @@ public class RestClient_FormData_Test {
 		return serializedPart(name, val).schema(schema);
 	}
 
-	private static PartList parts(Object...pairs) {
+	private static PartList parts(String...pairs) {
 		return partList(pairs);
 	}