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 2021/04/21 16:23:46 UTC

[juneau] branch master updated: Improvements to Header subclasses.

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 a88b5f5  Improvements to Header subclasses.
a88b5f5 is described below

commit a88b5f59873a615095b5415dc4d819f89eb9b825
Author: JamesBognar <ja...@salesforce.com>
AuthorDate: Wed Apr 21 12:23:10 2021 -0400

    Improvements to Header subclasses.
---
 .../main/ConfigurablePropertyCodeGenerator.java    |    1 -
 .../part/Partable.java => ListOperation.java}      |   57 +-
 .../org/apache/juneau/assertions/Assertions.java   |   34 +
 .../juneau/assertions/FluentVersionAssertion.java  |  133 ++
 .../apache/juneau/assertions/VersionAssertion.java |   88 +
 .../java/org/apache/juneau/http/HttpHeaders.java   | 2320 ++++++++------------
 .../java/org/apache/juneau/http/HttpParts.java     |   21 +-
 .../java/org/apache/juneau/http/header/Accept.java |   87 +-
 .../apache/juneau/http/header/AcceptCharset.java   |   72 +-
 .../apache/juneau/http/header/AcceptEncoding.java  |   72 +-
 .../apache/juneau/http/header/AcceptLanguage.java  |   76 +-
 .../apache/juneau/http/header/AcceptRanges.java    |   48 +-
 .../java/org/apache/juneau/http/header/Age.java    |   76 +-
 .../java/org/apache/juneau/http/header/Allow.java  |   80 +-
 .../apache/juneau/http/header/Authorization.java   |   48 +-
 .../juneau/http/header/BasicBooleanHeader.java     |  127 +-
 .../juneau/http/header/BasicCsvArrayHeader.java    |  174 +-
 .../apache/juneau/http/header/BasicDateHeader.java |  142 +-
 .../http/header/BasicEntityTagArrayHeader.java     |  135 +-
 .../juneau/http/header/BasicEntityTagHeader.java   |  110 +-
 .../org/apache/juneau/http/header/BasicHeader.java |  154 +-
 .../juneau/http/header/BasicIntegerHeader.java     |  128 +-
 .../apache/juneau/http/header/BasicLongHeader.java |  122 +-
 .../http/header/BasicMediaRangeArrayHeader.java    |  105 +-
 .../juneau/http/header/BasicMediaTypeHeader.java   |  131 +-
 .../juneau/http/header/BasicStringHeader.java      |  104 +-
 .../http/header/BasicStringRangeArrayHeader.java   |  122 +-
 .../apache/juneau/http/header/BasicUriHeader.java  |  120 +-
 .../apache/juneau/http/header/CacheControl.java    |   48 +-
 .../apache/juneau/http/header/ClientVersion.java   |  114 +-
 .../org/apache/juneau/http/header/Connection.java  |   61 +-
 .../juneau/http/header/ContentDisposition.java     |   67 +-
 .../apache/juneau/http/header/ContentEncoding.java |   48 +-
 .../apache/juneau/http/header/ContentLanguage.java |   80 +-
 .../apache/juneau/http/header/ContentLength.java   |   76 +-
 .../apache/juneau/http/header/ContentLocation.java |   76 +-
 .../apache/juneau/http/header/ContentRange.java    |   48 +-
 .../org/apache/juneau/http/header/ContentType.java |   92 +-
 .../java/org/apache/juneau/http/header/Date.java   |   80 +-
 .../java/org/apache/juneau/http/header/Debug.java  |   74 +-
 .../java/org/apache/juneau/http/header/ETag.java   |   73 +-
 .../org/apache/juneau/http/header/EntityTag.java   |    2 +-
 .../java/org/apache/juneau/http/header/Expect.java |   48 +-
 .../org/apache/juneau/http/header/Expires.java     |   80 +-
 .../org/apache/juneau/http/header/Forwarded.java   |   48 +-
 .../java/org/apache/juneau/http/header/From.java   |   48 +-
 .../org/apache/juneau/http/header/HeaderList.java  |    5 +-
 .../juneau/http/header/HeaderListBuilder.java      |  261 ++-
 .../java/org/apache/juneau/http/header/Host.java   |   48 +-
 .../org/apache/juneau/http/header/IfMatch.java     |   80 +-
 .../apache/juneau/http/header/IfModifiedSince.java |   80 +-
 .../org/apache/juneau/http/header/IfNoneMatch.java |   80 +-
 .../org/apache/juneau/http/header/IfRange.java     |  158 +-
 .../juneau/http/header/IfUnmodifiedSince.java      |   80 +-
 .../apache/juneau/http/header/LastModified.java    |   80 +-
 .../org/apache/juneau/http/header/Location.java    |   76 +-
 .../org/apache/juneau/http/header/MaxForwards.java |   76 +-
 .../org/apache/juneau/http/header/MediaRanges.java |    2 +-
 .../org/apache/juneau/http/header/NoTrace.java     |   77 +-
 .../java/org/apache/juneau/http/header/Origin.java |   48 +-
 .../java/org/apache/juneau/http/header/Pragma.java |   48 +-
 .../juneau/http/header/ProxyAuthenticate.java      |   48 +-
 .../juneau/http/header/ProxyAuthorization.java     |   48 +-
 .../java/org/apache/juneau/http/header/Range.java  |   48 +-
 .../org/apache/juneau/http/header/Referer.java     |   76 +-
 .../org/apache/juneau/http/header/RetryAfter.java  |  159 +-
 .../juneau/http/header/SerializedHeader.java       |  108 +-
 .../java/org/apache/juneau/http/header/Server.java |   48 +-
 .../apache/juneau/http/header/StringRanges.java    |    2 +-
 .../java/org/apache/juneau/http/header/TE.java     |   82 +-
 .../java/org/apache/juneau/http/header/Thrown.java |   98 +-
 .../org/apache/juneau/http/header/Trailer.java     |   48 +-
 .../juneau/http/header/TransferEncoding.java       |   48 +-
 .../org/apache/juneau/http/header/Upgrade.java     |   80 +-
 .../org/apache/juneau/http/header/UserAgent.java   |   48 +-
 .../java/org/apache/juneau/http/header/Vary.java   |   48 +-
 .../java/org/apache/juneau/http/header/Via.java    |   80 +-
 .../org/apache/juneau/http/header/Warning.java     |   48 +-
 .../apache/juneau/http/header/WwwAuthenticate.java |   48 +-
 .../apache/juneau/http/part/BasicBooleanPart.java  |    2 +-
 .../apache/juneau/http/part/BasicCsvArrayPart.java |    2 +-
 .../org/apache/juneau/http/part/BasicDatePart.java |    2 +-
 .../apache/juneau/http/part/BasicIntegerPart.java  |    2 +-
 .../org/apache/juneau/http/part/BasicLongPart.java |    2 +-
 .../org/apache/juneau/http/part/BasicPart.java     |   32 +-
 .../apache/juneau/http/part/BasicPartIterator.java |    7 +-
 .../apache/juneau/http/part/BasicStringPart.java   |    2 +-
 .../org/apache/juneau/http/part/BasicUriPart.java  |    2 +-
 .../part/{Partable.java => NameValuePairable.java} |    6 +-
 .../org/apache/juneau/http/part/PartIterator.java  |    6 +-
 .../java/org/apache/juneau/http/part/PartList.java |   72 +-
 .../apache/juneau/http/part/PartListBuilder.java   |   57 +-
 .../apache/juneau/http/part/SerializedPart.java    |    5 -
 .../juneau/http/response/HttpExceptionBuilder.java |    2 +-
 .../ExceptionBuilder.java}                         |   61 +-
 .../Part.java => internal/ExceptionUtils.java}     |   30 +-
 .../org/apache/juneau/internal/ObjectUtils.java    |   12 +
 .../java/org/apache/juneau/internal/Version.java   |   92 +-
 .../apache/juneau/rest/client/ResponseHeader.java  |    6 +-
 .../org/apache/juneau/rest/client/RestClient.java  |    5 +-
 .../juneau/rest/client/RestClientBuilder.java      |   11 +-
 .../org/apache/juneau/rest/client/RestRequest.java |   45 +-
 .../assertion/FluentResponseHeaderAssertion.java   |   10 -
 .../juneau/rest/client/remote/RemoteMeta.java      |    2 +-
 .../apache/juneau/rest/RestOperationContext.java   |    5 +-
 .../juneau/rest/annotation/RestAnnotation.java     |    4 +-
 .../rest/annotation/RestDeleteAnnotation.java      |    4 +-
 .../juneau/rest/annotation/RestGetAnnotation.java  |    4 +-
 .../juneau/rest/annotation/RestOpAnnotation.java   |    4 +-
 .../juneau/rest/annotation/RestPostAnnotation.java |    4 +-
 .../juneau/rest/annotation/RestPutAnnotation.java  |    4 +-
 .../assertions/FluentRequestHeaderAssertion.java   |   10 -
 .../org/apache/juneau/http/BasicHeader_Test.java   |   67 +-
 .../org/apache/juneau/http/BasicPart_Test.java     |   10 +-
 .../org/apache/juneau/http/HttpHeaders_Test.java   |   91 +
 .../org/apache/juneau/http/StringRanges_Test.java  |    2 +-
 .../juneau/http/header/AcceptCharset_Test.java     |   16 +-
 .../juneau/http/header/AcceptEncoding_Test.java    |   16 +-
 .../juneau/http/header/AcceptLanguage_Test.java    |   16 +-
 .../juneau/http/header/AcceptRanges_Test.java      |   12 +-
 .../org/apache/juneau/http/header/Accept_Test.java |   18 +-
 .../org/apache/juneau/http/header/Age_Test.java    |   17 +-
 .../org/apache/juneau/http/header/Allow_Test.java  |   18 +-
 .../juneau/http/header/Authorization_Test.java     |   12 +-
 ...ding_Test.java => BasicBooleanHeader_Test.java} |   35 +-
 .../http/header/BasicCsvArrayHeader_Test.java      |   35 +-
 .../juneau/http/header/BasicDateHeader_Test.java   |   46 +-
 .../header/BasicEntityTagArrayHeader_Test.java     |   36 +-
 .../http/header/BasicEntityTagHeader_Test.java     |   17 +-
 .../http/header/BasicIntegerHeader_Test.java       |   34 +-
 .../juneau/http/header/BasicLongHeader_Test.java   |   36 +-
 .../header/BasicMediaRangeArrayHeader_Test.java    |   24 +-
 .../http/header/BasicMediaTypeHeader_Test.java     |   22 +-
 .../juneau/http/header/BasicStringHeader_Test.java |   36 +-
 .../header/BasicStringRangeArrayHeader_Test.java   |   28 +-
 .../juneau/http/header/BasicUriHeader_Test.java    |   26 +-
 .../juneau/http/header/CacheControl_Test.java      |   16 +-
 .../juneau/http/header/ClientVersion_Test.java     |   18 +-
 .../apache/juneau/http/header/Connection_Test.java |   16 +-
 .../http/header/ContentDisposition_Test.java       |   16 +-
 .../juneau/http/header/ContentEncoding_Test.java   |   16 +-
 .../juneau/http/header/ContentLanguage_Test.java   |   18 +-
 .../juneau/http/header/ContentLength_Test.java     |   17 +-
 .../juneau/http/header/ContentLocation_Test.java   |   19 +-
 .../juneau/http/header/ContentRange_Test.java      |   16 +-
 .../juneau/http/header/ContentType_Test.java       |   21 +-
 .../org/apache/juneau/http/header/Date_Test.java   |   19 +-
 .../org/apache/juneau/http/header/ETag_Test.java   |   16 +-
 .../org/apache/juneau/http/header/Expect_Test.java |   16 +-
 .../apache/juneau/http/header/Expires_Test.java    |   19 +-
 .../apache/juneau/http/header/Forwarded_Test.java  |   16 +-
 .../org/apache/juneau/http/header/From_Test.java   |   16 +-
 .../apache/juneau/http/header/HeaderList_Test.java |    4 +-
 .../org/apache/juneau/http/header/Host_Test.java   |   16 +-
 .../apache/juneau/http/header/IfMatch_Test.java    |   20 +-
 .../juneau/http/header/IfModifiedSince_Test.java   |   19 +-
 .../juneau/http/header/IfNoneMatch_Test.java       |   20 +-
 .../apache/juneau/http/header/IfRange_Test.java    |   56 +-
 .../juneau/http/header/IfUnmodifiedSince_Test.java |   19 +-
 .../juneau/http/header/LastModified_Test.java      |   19 +-
 .../apache/juneau/http/header/Location_Test.java   |   19 +-
 .../juneau/http/header/MaxForwards_Test.java       |   17 +-
 .../apache/juneau/http/header/NoTrace_Test.java    |   18 +-
 .../org/apache/juneau/http/header/Origin_Test.java |   16 +-
 .../org/apache/juneau/http/header/Pragma_Test.java |   16 +-
 .../juneau/http/header/ProxyAuthenticate_Test.java |   16 +-
 .../http/header/ProxyAuthorization_Test.java       |   16 +-
 .../org/apache/juneau/http/header/Range_Test.java  |   16 +-
 .../apache/juneau/http/header/Referer_Test.java    |   19 +-
 .../apache/juneau/http/header/RetryAfter_Test.java |   42 +-
 .../org/apache/juneau/http/header/Server_Test.java |   16 +-
 .../org/apache/juneau/http/header/TE_Test.java     |   16 +-
 .../apache/juneau/http/header/Trailer_Test.java    |   16 +-
 .../juneau/http/header/TransferEncoding_Test.java  |   16 +-
 .../apache/juneau/http/header/Upgrade_Test.java    |   18 +-
 .../apache/juneau/http/header/UserAgent_Test.java  |   16 +-
 .../org/apache/juneau/http/header/Vary_Test.java   |   16 +-
 .../org/apache/juneau/http/header/Via_Test.java    |   18 +-
 .../apache/juneau/http/header/Warning_Test.java    |   16 +-
 .../juneau/http/header/WwwAuthenticate_Test.java   |   16 +-
 .../org/apache/juneau/http/part/PartList_Test.java |   45 +-
 .../remote/Remote_FormDataAnnotation_Test.java     |    2 +-
 .../http/remote/Remote_HeaderAnnotation_Test.java  |   12 +-
 .../org/apache/juneau/rest/RestOp_Params_Test.java |    2 +-
 .../rest/client/RestClient_Headers_Test.java       |   23 +-
 .../rest/client/RestClient_Response_Body_Test.java |    2 +-
 .../client/RestClient_Response_Headers_Test.java   |   14 +-
 .../rest/client/RestClient_Response_Test.java      |   11 +-
 .../apache/juneau/rest/client/RestClient_Test.java |    2 +-
 189 files changed, 5713 insertions(+), 4805 deletions(-)

diff --git a/juneau-all/src/java/main/ConfigurablePropertyCodeGenerator.java b/juneau-all/src/java/main/ConfigurablePropertyCodeGenerator.java
index 2daecca..86ce143 100644
--- a/juneau-all/src/java/main/ConfigurablePropertyCodeGenerator.java
+++ b/juneau-all/src/java/main/ConfigurablePropertyCodeGenerator.java
@@ -160,7 +160,6 @@ public class ConfigurablePropertyCodeGenerator {
 		ParserBuilder.class,
 		ParserGroupBuilder.class,
 		ParserSessionArgs.class,
-		Part.class,
 		PartialContent.class,
 		PermanentRedirect.class,
 		PlainTextParserBuilder.class,
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/part/Partable.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ListOperation.java
similarity index 55%
copy from juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/part/Partable.java
copy to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ListOperation.java
index 40b3aac..3ccfebc 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/part/Partable.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ListOperation.java
@@ -10,19 +10,62 @@
 // * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
 // * specific language governing permissions and limitations under the License.                                              *
 // ***************************************************************************************************************************
-package org.apache.juneau.http.part;
+package org.apache.juneau;
 
-import org.apache.http.*;
+import java.util.*;
 
 /**
- * Identifies a class that can be converted to a {@link Part} object.
+ * Identifies how to add elements to a list.
+ * {@reviewed}
  */
-public interface Partable {
+public enum ListOperation {
 
 	/**
-	 * Convert the object to a {@link NameValuePair}.
+	 * Elements should be added to the end of the list.
+	 */
+	APPEND,
+
+	/**
+	 * Elements should be added to the beginning of the list.
+	 */
+	PREPEND,
+
+	/**
+	 * Elements should be replaced inline and/or appended to the end of the list.
+	 */
+	SET,
+
+	/**
+	 * Elements should be added as default values that are added to the list if they're not already set.
+	 */
+	DEFAULT,
+
+	/**
+	 * Don't add the value if it's <jk>null</jk> or an empty string.
+	 */
+	@Deprecated
+	SKIP_IF_EMPTY;
+
+	/**
+	 * Default flags.
+	 */
+	@Deprecated
+	public static final EnumSet<ListOperation> DEFAULT_FLAGS = EnumSet.of(APPEND);
+
+	/**
+	 * Default skip-if-empty flags.
+	 */
+	@Deprecated
+	public static final EnumSet<ListOperation> SKIP_IF_EMPTY_FLAGS = EnumSet.of(APPEND, SKIP_IF_EMPTY);
+
+	/**
+	 * Returns {@link #DEFAULT_FLAGS} if the enum set is <jk>null</jk> or empty.
 	 *
-	 * @return The object converted to a {@link NameValuePair}.
+	 * @param s The set to check.
+	 * @return Either the same set or {@link #DEFAULT_FLAGS}.  Never <jk>null</jk>.
 	 */
-	Part asPart();
+	@Deprecated
+	public static EnumSet<ListOperation> orDefault(EnumSet<ListOperation> s) {
+		return s == null || s.isEmpty() ? DEFAULT_FLAGS : s;
+	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/Assertions.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/Assertions.java
index b941e50..02576b3 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/Assertions.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/Assertions.java
@@ -19,6 +19,7 @@ import java.time.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.internal.*;
 
 /**
  * Main class for creation of assertions for testing.
@@ -59,6 +60,39 @@ public class Assertions {
 	}
 
 	/**
+	 * Used for assertion calls against {@link Version} objects.
+	 *
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode w800'>
+	 * 	<jc>// Validates the specified major version is greater than 2.</jc>
+	 * 	<jsm>assertVersion</jsm>(<jv>version</jv>).major().isGreaterThan(2);
+	 * </p>
+	 *
+	 * @param value The version object being wrapped.
+	 * @return A new {@link VersionAssertion} object.  Never <jk>null</jk>.
+	 */
+	public static final VersionAssertion assertVersion(Version value) {
+		return VersionAssertion.create(value);
+	}
+
+	/**
+	 * Used for assertion calls against {@link Version} objects.
+	 *
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode w800'>
+	 * 	<jc>// Validates the specified major version is greater than 2.</jc>
+	 * 	<jsm>assertVersion</jsm>(<jv>version</jv>).major().isGreaterThan(2);
+	 * </p>
+	 *
+	 * @param value The version object being wrapped.
+	 * @return A new {@link VersionAssertion} object.  Never <jk>null</jk>.
+	 */
+	public static final VersionAssertion assertVersion(Optional<Version> value) {
+		assertArgNotNull("value", value);
+		return assertVersion(value.orElse(null));
+	}
+
+	/**
 	 * Used for assertion calls against {@link ZonedDateTime} objects.
 	 *
 	 * <h5 class='section'>Example:</h5>
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/FluentVersionAssertion.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/FluentVersionAssertion.java
new file mode 100644
index 0000000..a04968f
--- /dev/null
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/FluentVersionAssertion.java
@@ -0,0 +1,133 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.assertions;
+
+import java.io.*;
+
+import org.apache.juneau.internal.*;
+
+/**
+ * Used for fluent assertion calls against {@link Version} objects.
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bcode w800'>
+ * 	<jc>// Validates the response expiration is after the current date.</jc>
+ * 	<jv>client</jv>
+ * 		.get(<jsf>URL</jsf>)
+ * 		.run()
+ * 		.getHeader(ClientVersion.<jk>class</jk>).assertVersion().major().isGreaterThanOrEqual(2);
+ * </p>
+ *
+ * @param <R> The return type.
+ */
+@FluentSetters(returns="FluentVersionAssertion<R>")
+public class FluentVersionAssertion<R> extends FluentComparableAssertion<Version,R> {
+
+	public static final boolean NEEDS_TESTING = true;
+
+	private final Version value;
+
+	/**
+	 * Constructor.
+	 *
+	 * @param value The value being tested.
+	 * @param returns The object to return after the test.
+	 */
+	public FluentVersionAssertion(Version value, R returns) {
+		this(null, value, returns);
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param creator The assertion that created this assertion.
+	 * @param value The value being tested.
+	 * @param returns The object to return after the test.
+	 */
+	public FluentVersionAssertion(Assertion creator, Version value, R returns) {
+		super(creator, value, returns);
+		this.value = value;
+	}
+
+	/**
+	 * Extracts the specified version part (zero-indexed position).
+	 *
+	 * @param index The index of the version part to extract.
+	 * @return The response object (for method chaining).
+	 */
+	public FluentIntegerAssertion<R> part(int index) {
+		exists();
+		return new FluentIntegerAssertion<>(this, this.value.getPart(index).orElse(null), returns());
+	}
+
+	/**
+	 * Extracts the major part of the version string (index position 0).
+	 *
+	 * @return The response object (for method chaining).
+	 */
+	public FluentIntegerAssertion<R> major() {
+		return part(0);
+	}
+
+	/**
+	 * Extracts the minor part of the version string (index position 1).
+	 *
+	 * @return The response object (for method chaining).
+	 */
+	public FluentIntegerAssertion<R> minor() {
+		return part(1);
+	}
+
+	/**
+	 * Extracts the maintenance part of the version string (index position 2).
+	 *
+	 * @return The response object (for method chaining).
+	 */
+	public FluentIntegerAssertion<R> maintenance() {
+		return part(2);
+	}
+
+	// <FluentSetters>
+
+	@Override /* GENERATED - Assertion */
+	public FluentVersionAssertion<R> msg(String msg, Object...args) {
+		super.msg(msg, args);
+		return this;
+	}
+
+	@Override /* GENERATED - Assertion */
+	public FluentVersionAssertion<R> out(PrintStream value) {
+		super.out(value);
+		return this;
+	}
+
+	@Override /* GENERATED - Assertion */
+	public FluentVersionAssertion<R> silent() {
+		super.silent();
+		return this;
+	}
+
+	@Override /* GENERATED - Assertion */
+	public FluentVersionAssertion<R> stdout() {
+		super.stdout();
+		return this;
+	}
+
+	@Override /* GENERATED - Assertion */
+	public FluentVersionAssertion<R> throwable(Class<? extends java.lang.RuntimeException> value) {
+		super.throwable(value);
+		return this;
+	}
+
+	// </FluentSetters>
+}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/VersionAssertion.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/VersionAssertion.java
new file mode 100644
index 0000000..e50fe0c
--- /dev/null
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/assertions/VersionAssertion.java
@@ -0,0 +1,88 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.assertions;
+
+import java.io.*;
+
+import org.apache.juneau.internal.*;
+
+/**
+ * Used for assertion calls against {@link Version} objects.
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bcode w800'>
+ * 	<jc>// Validates the specified date is after the current date.</jc>
+ * 	<jsm>assertVersion</jsm>(<jv>myVersion</jv>).major().isGreaterThan(2);
+ * </p>
+ */
+@FluentSetters(returns="VersionAssertion")
+public class VersionAssertion extends FluentVersionAssertion<VersionAssertion> {
+
+	/**
+	 * Creator.
+	 *
+	 * @param value The version being wrapped.
+	 * @return A new {@link VersionAssertion} object.
+	 */
+	public static VersionAssertion create(Version value) {
+		return new VersionAssertion(value);
+	}
+
+	/**
+	 * Creator.
+	 *
+	 * @param value The version being wrapped.
+	 */
+	public VersionAssertion(Version value) {
+		super(value, null);
+	}
+
+	@Override
+	protected VersionAssertion returns() {
+		return this;
+	}
+
+	// <FluentSetters>
+
+	@Override /* GENERATED - Assertion */
+	public VersionAssertion msg(String msg, Object...args) {
+		super.msg(msg, args);
+		return this;
+	}
+
+	@Override /* GENERATED - Assertion */
+	public VersionAssertion out(PrintStream value) {
+		super.out(value);
+		return this;
+	}
+
+	@Override /* GENERATED - Assertion */
+	public VersionAssertion silent() {
+		super.silent();
+		return this;
+	}
+
+	@Override /* GENERATED - Assertion */
+	public VersionAssertion stdout() {
+		super.stdout();
+		return this;
+	}
+
+	@Override /* GENERATED - Assertion */
+	public VersionAssertion throwable(Class<? extends java.lang.RuntimeException> value) {
+		super.throwable(value);
+		return this;
+	}
+
+	// </FluentSetters>
+}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HttpHeaders.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HttpHeaders.java
index 6ac29c0..eb08ef6 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HttpHeaders.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HttpHeaders.java
@@ -12,6 +12,10 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.http;
 
+import static org.apache.juneau.internal.ExceptionUtils.*;
+import static org.apache.juneau.internal.StringUtils.*;
+
+import java.net.*;
 import java.time.*;
 import java.util.*;
 import java.util.function.*;
@@ -19,6 +23,11 @@ import java.util.function.*;
 import org.apache.http.*;
 import org.apache.juneau.http.header.*;
 import org.apache.juneau.http.header.Date;
+import org.apache.juneau.http.part.*;
+import org.apache.juneau.httppart.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.oapi.*;
+import org.apache.juneau.reflect.*;
 
 /**
  * Standard predefined HTTP headers.
@@ -26,6 +35,52 @@ import org.apache.juneau.http.header.Date;
  */
 public class HttpHeaders {
 
+	@SuppressWarnings("javadoc")
+	public static final Accept
+		ACCEPT_APPLICATION_ATOM_XML = Accept.APPLICATION_ATOM_XML,
+		ACCEPT_APPLICATION_FORM_URLENCODED = Accept.APPLICATION_FORM_URLENCODED,
+		ACCEPT_APPLICATION_JSON = Accept.APPLICATION_JSON,
+		ACCEPT_APPLICATION_OCTET_STREAM = Accept.APPLICATION_OCTET_STREAM,
+		ACCEPT_APPLICATION_SOAP_XML = Accept.APPLICATION_SOAP_XML,
+		ACCEPT_APPLICATION_SVG_XML = Accept.APPLICATION_SVG_XML,
+		ACCEPT_APPLICATION_XHTML_XML = Accept.APPLICATION_XHTML_XML,
+		ACCEPT_APPLICATION_XML = Accept.APPLICATION_XML,
+		ACCEPT_IMAGE_BMP = Accept.IMAGE_BMP,
+		ACCEPT_IMAGE_GIF = Accept.IMAGE_GIF,
+		ACCEPT_IMAGE_JPEG = Accept.IMAGE_JPEG,
+		ACCEPT_IMAGE_PNG = Accept.IMAGE_PNG,
+		ACCEPT_IMAGE_SVG = Accept.IMAGE_SVG,
+		ACCEPT_IMAGE_TIFF = Accept.IMAGE_TIFF,
+		ACCEPT_IMAGE_WEBP = Accept.IMAGE_WEBP,
+		ACCEPT_MULTIPART_FORM_DATA = Accept.MULTIPART_FORM_DATA,
+		ACCEPT_TEXT_HTML = Accept.TEXT_HTML,
+		ACCEPT_TEXT_PLAIN = Accept.TEXT_PLAIN,
+		ACCEPT_TEXT_XML = Accept.TEXT_XML,
+		ACCEPT_WILDCARD = Accept.WILDCARD;
+
+	@SuppressWarnings("javadoc")
+	public static final ContentType
+		CONTENTTYPE_APPLICATION_ATOM_XML = ContentType.APPLICATION_ATOM_XML,
+		CONTENTTYPE_APPLICATION_FORM_URLENCODED = ContentType.APPLICATION_FORM_URLENCODED,
+		CONTENTTYPE_APPLICATION_JSON = ContentType.APPLICATION_JSON,
+		CONTENTTYPE_APPLICATION_OCTET_STREAM = ContentType.APPLICATION_OCTET_STREAM,
+		CONTENTTYPE_APPLICATION_SOAP_XML = ContentType.APPLICATION_SOAP_XML,
+		CONTENTTYPE_APPLICATION_SVG_XML = ContentType.APPLICATION_SVG_XML,
+		CONTENTTYPE_APPLICATION_XHTML_XML = ContentType.APPLICATION_XHTML_XML,
+		CONTENTTYPE_APPLICATION_XML = ContentType.APPLICATION_XML,
+		CONTENTTYPE_IMAGE_BMP = ContentType.IMAGE_BMP,
+		CONTENTTYPE_IMAGE_GIF = ContentType.IMAGE_GIF,
+		CONTENTTYPE_IMAGE_JPEG = ContentType.IMAGE_JPEG,
+		CONTENTTYPE_IMAGE_PNG = ContentType.IMAGE_PNG,
+		CONTENTTYPE_IMAGE_SVG = ContentType.IMAGE_SVG,
+		CONTENTTYPE_IMAGE_TIFF = ContentType.IMAGE_TIFF,
+		CONTENTTYPE_IMAGE_WEBP = ContentType.IMAGE_WEBP,
+		CONTENTTYPE_MULTIPART_FORM_DATA = ContentType.MULTIPART_FORM_DATA,
+		CONTENTTYPE_TEXT_HTML = ContentType.TEXT_HTML,
+		CONTENTTYPE_TEXT_PLAIN = ContentType.TEXT_PLAIN,
+		CONTENTTYPE_TEXT_XML = ContentType.TEXT_XML,
+		CONTENTTYPE_WILDCARD = ContentType.WILDCARD;
+
 	//-----------------------------------------------------------------------------------------------------------------
 	// Standard HTTP headers
 	//-----------------------------------------------------------------------------------------------------------------
@@ -33,8 +88,11 @@ public class HttpHeaders {
 	/**
 	 * Creates a new {@link Accept} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be parsable by {@link MediaRanges#of(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
 	public static final Accept accept(String value) {
 		return Accept.of(value);
@@ -45,14 +103,22 @@ public class HttpHeaders {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
+	 */
+	public static final Accept accept(MediaRanges value) {
+		return Accept.of(value);
+	}
+
+	/**
+	 * Creates a new {@link Accept} header.
+	 *
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Accept accept(Object value) {
+	public static final Accept accept(MediaType value) {
 		return Accept.of(value);
 	}
 
@@ -63,23 +129,22 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Accept accept(Supplier<?> value) {
+	public static final Accept accept(Supplier<MediaRanges> value) {
 		return Accept.of(value);
 	}
 
 	/**
 	 * Creates a new {@link AcceptCharset} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be parsable by {@link StringRanges#of(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
 	public static final AcceptCharset acceptCharset(String value) {
 		return AcceptCharset.of(value);
@@ -90,15 +155,10 @@ public class HttpHeaders {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String} - Converted using {@link StringRanges#of(String)}.
-	 * 		<li><c>StringRange[]</c> - Left as-is.
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final AcceptCharset acceptCharset(Object value) {
+	public static final AcceptCharset acceptCharset(StringRanges value) {
 		return AcceptCharset.of(value);
 	}
 
@@ -109,24 +169,22 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String} - Converted using {@link StringRanges#of(String)}.
-	 * 		<li><c>StringRange[]</c> - Left as-is.
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final AcceptCharset acceptCharset(Supplier<?> value) {
+	public static final AcceptCharset acceptCharset(Supplier<StringRanges> value) {
 		return AcceptCharset.of(value);
 	}
 
 	/**
 	 * Creates a new {@link AcceptEncoding} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be parsable by {@link StringRanges#of(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
 	public static final AcceptEncoding acceptEncoding(String value) {
 		return AcceptEncoding.of(value);
@@ -137,15 +195,10 @@ public class HttpHeaders {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String} - Converted using {@link StringRanges#of(String)}.
-	 * 		<li><c>StringRange[]</c> - Left as-is.
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final AcceptEncoding acceptEncoding(Object value) {
+	public static final AcceptEncoding acceptEncoding(StringRanges value) {
 		return AcceptEncoding.of(value);
 	}
 
@@ -156,24 +209,22 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String} - Converted using {@link StringRanges#of(String)}.
-	 * 		<li><c>StringRange[]</c> - Left as-is.
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final AcceptEncoding acceptEncoding(Supplier<?> value) {
+	public static final AcceptEncoding acceptEncoding(Supplier<StringRanges> value) {
 		return AcceptEncoding.of(value);
 	}
 
 	/**
 	 * Creates a new {@link AcceptLanguage} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be parsable by {@link StringRanges#of(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
 	public static final AcceptLanguage acceptLanguage(String value) {
 		return AcceptLanguage.of(value);
@@ -184,15 +235,10 @@ public class HttpHeaders {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String} - Converted using {@link StringRanges#of(String)}.
-	 * 		<li><c>StringRange[]</c> - Left as-is.
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final AcceptLanguage acceptLanguage(Object value) {
+	public static final AcceptLanguage acceptLanguage(StringRanges value) {
 		return AcceptLanguage.of(value);
 	}
 
@@ -203,42 +249,23 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String} - Converted using {@link StringRanges#of(String)}.
-	 * 		<li><c>StringRange[]</c> - Left as-is.
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final AcceptLanguage acceptLanguage(Supplier<?> value) {
+	public static final AcceptLanguage acceptLanguage(Supplier<StringRanges> value) {
 		return AcceptLanguage.of(value);
 	}
 
 	/**
 	 * Creates a new {@link AcceptRanges} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
-	 */
-	public static final AcceptRanges acceptRanges(String value) {
-		return AcceptRanges.of(value);
-	}
-
-	/**
-	 * Creates a new {@link AcceptRanges} header.
-	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final AcceptRanges acceptRanges(Object value) {
+	public static final AcceptRanges acceptRanges(String value) {
 		return AcceptRanges.of(value);
 	}
 
@@ -249,24 +276,22 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final AcceptRanges acceptRanges(Supplier<?> value) {
+	public static final AcceptRanges acceptRanges(Supplier<String> value) {
 		return AcceptRanges.of(value);
 	}
 
 	/**
 	 * Creates a new {@link Age} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be parsable using {@link Integer#parseInt(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
 	public static final Age age(String value) {
 		return Age.of(value);
@@ -277,15 +302,10 @@ public class HttpHeaders {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link Number} - Converted to an integer using {@link Number#intValue()}.
-	 * 		<li>{@link String} - Parsed using {@link Integer#parseInt(String)}.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Age age(Object value) {
+	public static final Age age(Integer value) {
 		return Age.of(value);
 	}
 
@@ -296,24 +316,21 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link Number} - Converted to an integer using {@link Number#intValue()}.
-	 * 		<li>{@link String} - Parsed using {@link Integer#parseInt(String)}.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Age age(Supplier<?> value) {
+	public static final Age age(Supplier<Integer> value) {
 		return Age.of(value);
 	}
 
 	/**
 	 * Creates a new {@link Allow} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
 	public static final Allow allow(String value) {
 		return Allow.of(value);
@@ -324,17 +341,10 @@ public class HttpHeaders {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - A comma-delimited string.
-	 * 		<li><c>String[]</c> - A pre-parsed value.
-	 * 		<li>Any other array type - Converted to <c>String[]</c>.
-	 * 		<li>Any {@link Collection} - Converted to <c>String[]</c>.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Allow allow(Object value) {
+	public static final Allow allow(List<String> value) {
 		return Allow.of(value);
 	}
 
@@ -345,44 +355,23 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - A comma-delimited string.
-	 * 		<li><c>String[]</c> - A pre-parsed value.
-	 * 		<li>Any other array type - Converted to <c>String[]</c>.
-	 * 		<li>Any {@link Collection} - Converted to <c>String[]</c>.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Allow allow(Supplier<?> value) {
+	public static final Allow allow(Supplier<List<String>> value) {
 		return Allow.of(value);
 	}
 
 	/**
 	 * Creates a new {@link Authorization} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
-	 */
-	public static final Authorization authorization(String value) {
-		return Authorization.of(value);
-	}
-
-	/**
-	 * Creates a new {@link Authorization} header.
-	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Authorization authorization(Object value) {
+	public static final Authorization authorization(String value) {
 		return Authorization.of(value);
 	}
 
@@ -393,42 +382,23 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Authorization authorization(Supplier<?> value) {
+	public static final Authorization authorization(Supplier<String> value) {
 		return Authorization.of(value);
 	}
 
 	/**
 	 * Creates a new {@link CacheControl} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
-	 */
-	public static final CacheControl cacheControl(String value) {
-		return CacheControl.of(value);
-	}
-
-	/**
-	 * Creates a new {@link CacheControl} header.
-	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final CacheControl cacheControl(Object value) {
+	public static final CacheControl cacheControl(String value) {
 		return CacheControl.of(value);
 	}
 
@@ -439,24 +409,22 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final CacheControl cacheControl(Supplier<?> value) {
+	public static final CacheControl cacheControl(Supplier<String> value) {
 		return CacheControl.of(value);
 	}
 
 	/**
 	 * Creates a new {@link ClientVersion} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be parsable by {@link Version#of(String)}
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
 	public static final ClientVersion clientVersion(String value) {
 		return ClientVersion.of(value);
@@ -467,14 +435,10 @@ public class HttpHeaders {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final ClientVersion clientVersion(Object value) {
+	public static final ClientVersion clientVersion(Version value) {
 		return ClientVersion.of(value);
 	}
 
@@ -485,41 +449,23 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final ClientVersion clientVersion(Supplier<?> value) {
+	public static final ClientVersion clientVersion(Supplier<Version> value) {
 		return ClientVersion.of(value);
 	}
 
 	/**
 	 * Creates a new {@link Connection} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
-	 */
-	public static final Connection connection(String value) {
-		return Connection.of(value);
-	}
-
-	/**
-	 * Creates a new {@link Connection} header.
-	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Connection connection(Object value) {
+	public static final Connection connection(String value) {
 		return Connection.of(value);
 	}
 
@@ -530,24 +476,22 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Connection connection(Supplier<?> value) {
+	public static final Connection connection(Supplier<String> value) {
 		return Connection.of(value);
 	}
 
 	/**
 	 * Creates a new {@link ContentDisposition} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be parsable by {@link StringRanges#of(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
 	public static final ContentDisposition contentDisposition(String value) {
 		return ContentDisposition.of(value);
@@ -558,14 +502,10 @@ public class HttpHeaders {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final ContentDisposition contentDisposition(Object value) {
+	public static final ContentDisposition contentDisposition(StringRanges value) {
 		return ContentDisposition.of(value);
 	}
 
@@ -576,41 +516,23 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final ContentDisposition contentDisposition(Supplier<?> value) {
+	public static final ContentDisposition contentDisposition(Supplier<StringRanges> value) {
 		return ContentDisposition.of(value);
 	}
 
 	/**
 	 * Creates a new {@link ContentEncoding} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
-	 */
-	public static final ContentEncoding contentEncoding(String value) {
-		return ContentEncoding.of(value);
-	}
-
-	/**
-	 * Creates a new {@link ContentEncoding} header.
-	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final ContentEncoding contentEncoding(Object value) {
+	public static final ContentEncoding contentEncoding(String value) {
 		return ContentEncoding.of(value);
 	}
 
@@ -621,23 +543,21 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final ContentEncoding contentEncoding(Supplier<?> value) {
+	public static final ContentEncoding contentEncoding(Supplier<String> value) {
 		return ContentEncoding.of(value);
 	}
 
 	/**
 	 * Creates a new {@link ContentLanguage} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
 	public static final ContentLanguage contentLanguage(String value) {
 		return ContentLanguage.of(value);
@@ -648,17 +568,10 @@ public class HttpHeaders {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - A comma-delimited string.
-	 * 		<li><c>String[]</c> - A pre-parsed value.
-	 * 		<li>Any other array type - Converted to <c>String[]</c>.
-	 * 		<li>Any {@link Collection} - Converted to <c>String[]</c>.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final ContentLanguage contentLanguage(Object value) {
+	public static final ContentLanguage contentLanguage(List<String> value) {
 		return ContentLanguage.of(value);
 	}
 
@@ -669,26 +582,22 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - A comma-delimited string.
-	 * 		<li><c>String[]</c> - A pre-parsed value.
-	 * 		<li>Any other array type - Converted to <c>String[]</c>.
-	 * 		<li>Any {@link Collection} - Converted to <c>String[]</c>.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final ContentLanguage contentLanguage(Supplier<?> value) {
+	public static final ContentLanguage contentLanguage(Supplier<List<String>> value) {
 		return ContentLanguage.of(value);
 	}
 
 	/**
 	 * Creates a new {@link ContentLength} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be parsable using {@link Long#parseLong(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
 	public static final ContentLength contentLength(String value) {
 		return ContentLength.of(value);
@@ -699,15 +608,10 @@ public class HttpHeaders {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link Number} - Converted to a long using {@link Number#longValue()}.
-	 * 		<li>{@link String} - Parsed using {@link Long#parseLong(String)}.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final ContentLength contentLength(Object value) {
+	public static final ContentLength contentLength(Long value) {
 		return ContentLength.of(value);
 	}
 
@@ -718,24 +622,22 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link Number} - Converted to a long using {@link Number#longValue()}.
-	 * 		<li>{@link String} - Parsed using {@link Long#parseLong(String)}.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final ContentLength contentLength(Supplier<?> value) {
+	public static final ContentLength contentLength(Supplier<Long> value) {
 		return ContentLength.of(value);
 	}
 
 	/**
 	 * Creates a new {@link ContentLocation} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be parsable by {@link URI#create(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
 	public static final ContentLocation contentLocation(String value) {
 		return ContentLocation.of(value);
@@ -746,14 +648,10 @@ public class HttpHeaders {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final ContentLocation contentLocation(Object value) {
+	public static final ContentLocation contentLocation(URI value) {
 		return ContentLocation.of(value);
 	}
 
@@ -764,41 +662,23 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final ContentLocation contentLocation(Supplier<?> value) {
+	public static final ContentLocation contentLocation(Supplier<URI> value) {
 		return ContentLocation.of(value);
 	}
 
 	/**
 	 * Creates a new {@link ContentRange} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
-	 */
-	public static final ContentRange contentRange(String value) {
-		return ContentRange.of(value);
-	}
-
-	/**
-	 * Creates a new {@link ContentRange} header.
-	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final ContentRange contentRange(Object value) {
+	public static final ContentRange contentRange(String value) {
 		return ContentRange.of(value);
 	}
 
@@ -809,23 +689,22 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final ContentRange contentRange(Supplier<?> value) {
+	public static final ContentRange contentRange(Supplier<String> value) {
 		return ContentRange.of(value);
 	}
 
 	/**
 	 * Creates a new {@link ContentType} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be parsable by {@link MediaType#of(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
 	public static final ContentType contentType(String value) {
 		return ContentType.of(value);
@@ -834,27 +713,12 @@ public class HttpHeaders {
 	/**
 	 * Creates a new {@link ContentType} header.
 	 *
-	 * @param value The header value.
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
-	 */
-	public static final ContentType contentType(MediaType value) {
-		return ContentType.of(value);
-	}
-
-	/**
-	 * Creates a new {@link ContentType} header.
-	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String} - Converted using {@link MediaType#of(String)}.
-	 * 		<li>{@link MediaType}.
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final ContentType contentType(Object value) {
+	public static final ContentType contentType(MediaType value) {
 		return ContentType.of(value);
 	}
 
@@ -865,24 +729,22 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String} - Converted using {@link MediaType#of(String)}.
-	 * 		<li>{@link MediaType}.
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final ContentType contentType(Supplier<?> value) {
+	public static final ContentType contentType(Supplier<MediaType> value) {
 		return ContentType.of(value);
 	}
 
 	/**
 	 * Creates a new {@link Date} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be an RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>).
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
 	public static final Date date(String value) {
 		return Date.of(value);
@@ -893,16 +755,10 @@ public class HttpHeaders {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - An RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>).
-	 * 		<li>{@link ZonedDateTime}
-	 * 		<li>{@link Calendar}
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final Date date(Object value) {
+	public static final Date date(ZonedDateTime value) {
 		return Date.of(value);
 	}
 
@@ -913,74 +769,93 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - An RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>).
-	 * 		<li>{@link ZonedDateTime}
-	 * 		<li>{@link Calendar}
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final Date date(Supplier<?> value) {
+	public static final Date date(Supplier<ZonedDateTime> value) {
 		return Date.of(value);
 	}
 
 	/**
-	 * Creates a new {@link ETag} header.
+	 * Creates a new {@link Debug} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be parsable by {@link Boolean#parseBoolean(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
 	 */
-	public static final ETag eTag(String value) {
-		return ETag.of(value);
+	public static final Debug debug(String value) {
+		return Debug.of(value);
 	}
 
 	/**
-	 * Creates a new {@link ETag} header.
+	 * Creates a new {@link Debug} header.
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
+	 * 	<br>Must be parsable by {@link Boolean#parseBoolean(String)}.
+	 * 	<br>Can be <jk>null</jk>.
 	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
 	 */
-	public static final ETag eTag(Object value) {
-		return ETag.of(value);
+	public static final Debug debug(Boolean value) {
+		return Debug.of(value);
 	}
 
 	/**
-	 * Creates a new {@link ETag} header with a delayed value.
+	 * Creates a new {@link Debug} header with a delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
 	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
+	 * 	<br>Can be <jk>null</jk>.
 	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
 	 */
-	public static final ETag eTag(Supplier<?> value) {
+	public static final Debug debug(Supplier<Boolean> value) {
+		return Debug.of(value);
+	}
+
+	/**
+	 * Creates a new {@link ETag} header.
+	 *
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be an entity tag value (e.g. <js>"\"xyzzy\""</js>).
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
+	 */
+	public static final ETag eTag(String value) {
 		return ETag.of(value);
 	}
 
 	/**
-	 * Creates a new {@link Expect} header.
+	 * Creates a new {@link ETag} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Expect expect(String value) {
-		return Expect.of(value);
+	public static final ETag eTag(EntityTag value) {
+		return ETag.of(value);
+	}
+
+	/**
+	 * Creates a new {@link ETag} header with a delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
+	 *
+	 * @param value
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
+	 */
+	public static final ETag eTag(Supplier<EntityTag> value) {
+		return ETag.of(value);
 	}
 
 	/**
@@ -988,14 +863,10 @@ public class HttpHeaders {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Expect expect(Object value) {
+	public static final Expect expect(String value) {
 		return Expect.of(value);
 	}
 
@@ -1006,23 +877,22 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Expect expect(Supplier<?> value) {
+	public static final Expect expect(Supplier<String> value) {
 		return Expect.of(value);
 	}
 
 	/**
 	 * Creates a new {@link Expires} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be an RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>).
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
 	public static final Expires expires(String value) {
 		return Expires.of(value);
@@ -1033,16 +903,10 @@ public class HttpHeaders {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - An RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>).
-	 * 		<li>{@link ZonedDateTime}
-	 * 		<li>{@link Calendar}
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final Expires expires(Object value) {
+	public static final Expires expires(ZonedDateTime value) {
 		return Expires.of(value);
 	}
 
@@ -1053,43 +917,23 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - An RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>).
-	 * 		<li>{@link ZonedDateTime}
-	 * 		<li>{@link Calendar}
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final Expires expires(Supplier<?> value) {
+	public static final Expires expires(Supplier<ZonedDateTime> value) {
 		return Expires.of(value);
 	}
 
 	/**
 	 * Creates a new {@link Forwarded} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
-	 */
-	public static final Forwarded forwarded(String value) {
-		return Forwarded.of(value);
-	}
-
-	/**
-	 * Creates a new {@link Forwarded} header.
-	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Forwarded forwarded(Object value) {
+	public static final Forwarded forwarded(String value) {
 		return Forwarded.of(value);
 	}
 
@@ -1100,41 +944,23 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Forwarded forwarded(Supplier<?> value) {
+	public static final Forwarded forwarded(Supplier<String> value) {
 		return Forwarded.of(value);
 	}
 
 	/**
 	 * Creates a new {@link From} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
-	 */
-	public static final From from(String value) {
-		return From.of(value);
-	}
-
-	/**
-	 * Creates a new {@link From} header.
-	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final From from(Object value) {
+	public static final From from(String value) {
 		return From.of(value);
 	}
 
@@ -1145,41 +971,23 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final From from(Supplier<?> value) {
+	public static final From from(Supplier<String> value) {
 		return From.of(value);
 	}
 
 	/**
 	 * Creates a new {@link Host} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
-	 */
-	public static final Host host(String value) {
-		return Host.of(value);
-	}
-
-	/**
-	 * Creates a new {@link Host} header.
-	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Host host(Object value) {
+	public static final Host host(String value) {
 		return Host.of(value);
 	}
 
@@ -1190,23 +998,22 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Host host(Supplier<?> value) {
+	public static final Host host(Supplier<String> value) {
 		return Host.of(value);
 	}
 
 	/**
 	 * Creates a new {@link IfMatch} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be a comma-delimited list of entity validator values (e.g. <js>"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""</js>).
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
 	public static final IfMatch ifMatch(String value) {
 		return IfMatch.of(value);
@@ -1217,16 +1024,10 @@ public class HttpHeaders {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - A comma-delimited list of entity validator values (e.g. <js>"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""</js>).
-	 * 		<li>A collection or array of {@link EntityTag} objects.
-	 * 		<li>A collection or array of anything else - Converted to Strings.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final IfMatch ifMatch(Object value) {
+	public static final IfMatch ifMatch(List<EntityTag> value) {
 		return IfMatch.of(value);
 	}
 
@@ -1237,25 +1038,22 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - A comma-delimited list of entity validator values (e.g. <js>"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""</js>).
-	 * 		<li>A collection or array of {@link EntityTag} objects.
-	 * 		<li>A collection or array of anything else - Converted to Strings.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final IfMatch ifMatch(Supplier<?> value) {
+	public static final IfMatch ifMatch(Supplier<List<EntityTag>> value) {
 		return IfMatch.of(value);
 	}
 
 	/**
 	 * Creates a new {@link IfModifiedSince} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be an RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>).
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
 	public static final IfModifiedSince ifModifiedSince(String value) {
 		return IfModifiedSince.of(value);
@@ -1266,16 +1064,10 @@ public class HttpHeaders {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - An RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>).
-	 * 		<li>{@link ZonedDateTime}
-	 * 		<li>{@link Calendar}
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final IfModifiedSince ifModifiedSince(Object value) {
+	public static final IfModifiedSince ifModifiedSince(ZonedDateTime value) {
 		return IfModifiedSince.of(value);
 	}
 
@@ -1286,25 +1078,22 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - An RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>).
-	 * 		<li>{@link ZonedDateTime}
-	 * 		<li>{@link Calendar}
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final IfModifiedSince ifModifiedSince(Supplier<?> value) {
+	public static final IfModifiedSince ifModifiedSince(Supplier<ZonedDateTime> value) {
 		return IfModifiedSince.of(value);
 	}
 
 	/**
 	 * Creates a new {@link IfNoneMatch} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be a comma-delimited list of entity validator values (e.g. <js>"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""</js>).
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
 	public static final IfNoneMatch ifNoneMatch(String value) {
 		return IfNoneMatch.of(value);
@@ -1315,16 +1104,10 @@ public class HttpHeaders {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - A comma-delimited list of entity validator values (e.g. <js>"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""</js>).
-	 * 		<li>A collection or array of {@link EntityTag} objects.
-	 * 		<li>A collection or array of anything else - Converted to Strings.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final IfNoneMatch ifNoneMatch(Object value) {
+	public static final IfNoneMatch ifNoneMatch(List<EntityTag> value) {
 		return IfNoneMatch.of(value);
 	}
 
@@ -1335,25 +1118,22 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - A comma-delimited list of entity validator values (e.g. <js>"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""</js>).
-	 * 		<li>A collection or array of {@link EntityTag} objects.
-	 * 		<li>A collection or array of anything else - Converted to Strings.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final IfNoneMatch ifNoneMatch(Supplier<?> value) {
+	public static final IfNoneMatch ifNoneMatch(Supplier<List<EntityTag>> value) {
 		return IfNoneMatch.of(value);
 	}
 
 	/**
 	 * Creates a new {@link IfRange} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be an RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>).
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
 	public static final IfRange ifRange(String value) {
 		return IfRange.of(value);
@@ -1364,14 +1144,22 @@ public class HttpHeaders {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
+	 */
+	public static final IfRange ifRange(ZonedDateTime value) {
+		return IfRange.of(value);
+	}
+
+	/**
+	 * Creates a new {@link IfRange} header.
+	 *
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final IfRange ifRange(Object value) {
+	public static final IfRange ifRange(EntityTag value) {
 		return IfRange.of(value);
 	}
 
@@ -1382,13 +1170,10 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Supplier must supply either {@link EntityTag} or {@link ZonedDateTime} objects.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
 	public static final IfRange ifRange(Supplier<?> value) {
 		return IfRange.of(value);
@@ -1397,8 +1182,11 @@ public class HttpHeaders {
 	/**
 	 * Creates a new {@link IfUnmodifiedSince} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be an RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>).
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
 	public static final IfUnmodifiedSince ifUnmodifiedSince(String value) {
 		return IfUnmodifiedSince.of(value);
@@ -1409,16 +1197,10 @@ public class HttpHeaders {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - An RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>).
-	 * 		<li>{@link ZonedDateTime}
-	 * 		<li>{@link Calendar}
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final IfUnmodifiedSince ifUnmodifiedSince(Object value) {
+	public static final IfUnmodifiedSince ifUnmodifiedSince(ZonedDateTime value) {
 		return IfUnmodifiedSince.of(value);
 	}
 
@@ -1429,25 +1211,22 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - An RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>).
-	 * 		<li>{@link ZonedDateTime}
-	 * 		<li>{@link Calendar}
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final IfUnmodifiedSince ifUnmodifiedSince(Supplier<?> value) {
+	public static final IfUnmodifiedSince ifUnmodifiedSince(Supplier<ZonedDateTime> value) {
 		return IfUnmodifiedSince.of(value);
 	}
 
 	/**
 	 * Creates a new {@link LastModified} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be an RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>).
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
 	public static final LastModified lastModified(String value) {
 		return LastModified.of(value);
@@ -1458,16 +1237,10 @@ public class HttpHeaders {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - An RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>).
-	 * 		<li>{@link ZonedDateTime}
-	 * 		<li>{@link Calendar}
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final LastModified lastModified(Object value) {
+	public static final LastModified lastModified(ZonedDateTime value) {
 		return LastModified.of(value);
 	}
 
@@ -1478,43 +1251,36 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - An RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>).
-	 * 		<li>{@link ZonedDateTime}
-	 * 		<li>{@link Calendar}
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final LastModified lastModified(Supplier<?> value) {
+	public static final LastModified lastModified(Supplier<ZonedDateTime> value) {
 		return LastModified.of(value);
 	}
 
 	/**
-	 * Creates a new {@link Referer} header.
+	 * Creates a new {@link Location} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be parsable by {@link URI#create(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
 	public static final Location location(String value) {
 		return Location.of(value);
 	}
 
 	/**
-	 * Creates a new {@link Referer} header.
+	 * Creates a new {@link Location} header.
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Location location(Object value) {
+	public static final Location location(URI value) {
 		return Location.of(value);
 	}
 
@@ -1525,23 +1291,22 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Location location(Supplier<?> value) {
+	public static final Location location(Supplier<URI> value) {
 		return Location.of(value);
 	}
 
 	/**
 	 * Creates a new {@link MaxForwards} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be parsable using {@link Integer#parseInt(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
 	public static final MaxForwards maxForwards(String value) {
 		return MaxForwards.of(value);
@@ -1552,15 +1317,10 @@ public class HttpHeaders {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link Number} - Converted to an integer using {@link Number#intValue()}.
-	 * 		<li>{@link String} - Parsed using {@link Integer#parseInt(String)}.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final MaxForwards maxForwards(Object value) {
+	public static final MaxForwards maxForwards(Integer value) {
 		return MaxForwards.of(value);
 	}
 
@@ -1571,24 +1331,22 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link Number} - Converted to an integer using {@link Number#intValue()}.
-	 * 		<li>{@link String} - Parsed using {@link Integer#parseInt(String)}.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final MaxForwards maxForwards(Supplier<?> value) {
+	public static final MaxForwards maxForwards(Supplier<Integer> value) {
 		return MaxForwards.of(value);
 	}
 
 	/**
 	 * Creates a new {@link NoTrace} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be parsable by {@link Boolean#parseBoolean(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
 	 */
 	public static final NoTrace noTrace(String value) {
 		return NoTrace.of(value);
@@ -1599,14 +1357,10 @@ public class HttpHeaders {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
+	 * 	<br>Can be <jk>null</jk>.
 	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
 	 */
-	public static final NoTrace noTrace(Object value) {
+	public static final NoTrace noTrace(Boolean value) {
 		return NoTrace.of(value);
 	}
 
@@ -1618,40 +1372,22 @@ public class HttpHeaders {
 	 *
 	 * @param value
 	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
+	 * 	<br>Can be <jk>null</jk>.
 	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
 	 */
-	public static final NoTrace noTrace(Supplier<?> value) {
+	public static final NoTrace noTrace(Supplier<Boolean> value) {
 		return NoTrace.of(value);
 	}
 
 	/**
 	 * Creates a new {@link Origin} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
-	 */
-	public static final Origin origin(String value) {
-		return Origin.of(value);
-	}
-
-	/**
-	 * Creates a new {@link Origin} header.
-	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Origin origin(Object value) {
+	public static final Origin origin(String value) {
 		return Origin.of(value);
 	}
 
@@ -1662,41 +1398,23 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Origin origin(Supplier<?> value) {
+	public static final Origin origin(Supplier<String> value) {
 		return Origin.of(value);
 	}
 
 	/**
 	 * Creates a new {@link Pragma} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
-	 */
-	public static final Pragma pragma(String value) {
-		return Pragma.of(value);
-	}
-
-	/**
-	 * Creates a new {@link Pragma} header.
-	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Pragma pragma(Object value) {
+	public static final Pragma pragma(String value) {
 		return Pragma.of(value);
 	}
 
@@ -1707,41 +1425,23 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Pragma pragma(Supplier<?> value) {
+	public static final Pragma pragma(Supplier<String> value) {
 		return Pragma.of(value);
 	}
 
 	/**
 	 * Creates a new {@link ProxyAuthenticate} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
-	 */
-	public static final ProxyAuthenticate proxyAuthenticate(String value) {
-		return ProxyAuthenticate.of(value);
-	}
-
-	/**
-	 * Creates a new {@link ProxyAuthenticate} header.
-	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final ProxyAuthenticate proxyAuthenticate(Object value) {
+	public static final ProxyAuthenticate proxyAuthenticate(String value) {
 		return ProxyAuthenticate.of(value);
 	}
 
@@ -1752,41 +1452,23 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final ProxyAuthenticate proxyAuthenticate(Supplier<?> value) {
+	public static final ProxyAuthenticate proxyAuthenticate(Supplier<String> value) {
 		return ProxyAuthenticate.of(value);
 	}
 
 	/**
 	 * Creates a new {@link ProxyAuthorization} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
-	 */
-	public static final ProxyAuthorization proxyAuthorization(String value) {
-		return ProxyAuthorization.of(value);
-	}
-
-	/**
-	 * Creates a new {@link ProxyAuthorization} header.
-	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final ProxyAuthorization proxyAuthorization(Object value) {
+	public static final ProxyAuthorization proxyAuthorization(String value) {
 		return ProxyAuthorization.of(value);
 	}
 
@@ -1797,41 +1479,23 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final ProxyAuthorization proxyAuthorization(Supplier<?> value) {
+	public static final ProxyAuthorization proxyAuthorization(Supplier<String> value) {
 		return ProxyAuthorization.of(value);
 	}
 
 	/**
 	 * Creates a new {@link Range} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
-	 */
-	public static final Range range(String value) {
-		return Range.of(value);
-	}
-
-	/**
-	 * Creates a new {@link Range} header.
-	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Range range(Object value) {
+	public static final Range range(String value) {
 		return Range.of(value);
 	}
 
@@ -1842,23 +1506,22 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Range range(Supplier<?> value) {
+	public static final Range range(Supplier<String> value) {
 		return Range.of(value);
 	}
 
 	/**
 	 * Creates a new {@link Referer} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be parsable by {@link URI#create(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
 	public static final Referer referer(String value) {
 		return Referer.of(value);
@@ -1869,14 +1532,11 @@ public class HttpHeaders {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Must be parsable by {@link URI#create(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Referer referer(Object value) {
+	public static final Referer referer(URI value) {
 		return Referer.of(value);
 	}
 
@@ -1887,23 +1547,22 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Referer referer(Supplier<?> value) {
+	public static final Referer referer(Supplier<URI> value) {
 		return Referer.of(value);
 	}
 
 	/**
 	 * Creates a new {@link RetryAfter} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be an RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>) or an integer.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
 	public static final RetryAfter retryAfter(String value) {
 		return RetryAfter.of(value);
@@ -1914,44 +1573,39 @@ public class HttpHeaders {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final RetryAfter retryAfter(Object value) {
+	public static final RetryAfter retryAfter(ZonedDateTime value) {
 		return RetryAfter.of(value);
 	}
 
 	/**
-	 * Creates a new {@link RetryAfter} header with a delayed value.
-	 *
-	 * <p>
-	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
+	 * Creates a new {@link RetryAfter} header.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final RetryAfter retryAfter(Supplier<?> value) {
+	public static final RetryAfter retryAfter(Integer value) {
 		return RetryAfter.of(value);
 	}
 
 	/**
-	 * Creates a new {@link Server} header.
+	 * Creates a new {@link RetryAfter} header with a delayed value.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
+	 *
+	 * @param value
+	 * 	The supplier of the header value.
+	 * 	<br>Supplier must supply either {@link Integer} or {@link ZonedDateTime} objects.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final Server server(String value) {
-		return Server.of(value);
+	public static final RetryAfter retryAfter(Supplier<?> value) {
+		return RetryAfter.of(value);
 	}
 
 	/**
@@ -1959,14 +1613,10 @@ public class HttpHeaders {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Server server(Object value) {
+	public static final Server server(String value) {
 		return Server.of(value);
 	}
 
@@ -1977,23 +1627,22 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Server server(Supplier<?> value) {
+	public static final Server server(Supplier<String> value) {
 		return Server.of(value);
 	}
 
 	/**
 	 * Creates a new {@link TE} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be parsable by {@link StringRanges#of(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
 	public static final TE te(String value) {
 		return TE.of(value);
@@ -2004,15 +1653,10 @@ public class HttpHeaders {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String} - Converted using {@link StringRanges#of(String)}.
-	 * 		<li><c>StringRange[]</c> - Left as-is.
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final TE te(Object value) {
+	public static final TE te(StringRanges value) {
 		return TE.of(value);
 	}
 
@@ -2023,16 +1667,11 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String} - Converted using {@link StringRanges#of(String)}.
-	 * 		<li><c>StringRange[]</c> - Left as-is.
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final TE te(Supplier<?> value) {
+	public static final TE te(Supplier<StringRanges> value) {
 		return TE.of(value);
 	}
 
@@ -2041,9 +1680,10 @@ public class HttpHeaders {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Thrown thrown(Throwable value) {
+	public static final Thrown thrown(String value) {
 		return Thrown.of(value);
 	}
 
@@ -2052,48 +1692,37 @@ public class HttpHeaders {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Thrown thrown(String value) {
+	public static final Thrown thrown(Throwable...value) {
 		return Thrown.of(value);
 	}
 
 	/**
 	 * Creates a new {@link Trailer} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
 	public static final Trailer trailer(String value) {
 		return Trailer.of(value);
 	}
 
 	/**
-	 * Creates a new {@link Trailer} header.
-	 *
-	 * @param value The header value.
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
-	 */
-	public static final Trailer trailer(Object value) {
-		return Trailer.of(value);
-	}
-
-	/**
 	 * Creates a new {@link Trailer} header with a delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Trailer trailer(Supplier<?> value) {
+	public static final Trailer trailer(Supplier<String> value) {
 		return Trailer.of(value);
 	}
 
@@ -2101,31 +1730,11 @@ public class HttpHeaders {
 	 * Creates a new {@link TransferEncoding} header.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
-	 */
-	public static final TransferEncoding transferEncoding(String value) {
-		return TransferEncoding.of(value);
-	}
-
-	/**
-	 * Creates a new {@link TransferEncoding} header.
-	 *
-	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final TransferEncoding transferEncoding(Object value) {
+	public static final TransferEncoding transferEncoding(String value) {
 		return TransferEncoding.of(value);
 	}
 
@@ -2136,23 +1745,21 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final TransferEncoding transferEncoding(Supplier<?> value) {
+	public static final TransferEncoding transferEncoding(Supplier<String> value) {
 		return TransferEncoding.of(value);
 	}
 
 	/**
 	 * Creates a new {@link Upgrade} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
 	public static final Upgrade upgrade(String value) {
 		return Upgrade.of(value);
@@ -2163,17 +1770,10 @@ public class HttpHeaders {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - A comma-delimited string.
-	 * 		<li><c>String[]</c> - A pre-parsed value.
-	 * 		<li>Any other array type - Converted to <c>String[]</c>.
-	 * 		<li>Any {@link Collection} - Converted to <c>String[]</c>.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Upgrade upgrade(Object value) {
+	public static final Upgrade upgrade(List<String> value) {
 		return Upgrade.of(value);
 	}
 
@@ -2184,44 +1784,23 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - A comma-delimited string.
-	 * 		<li><c>String[]</c> - A pre-parsed value.
-	 * 		<li>Any other array type - Converted to <c>String[]</c>.
-	 * 		<li>Any {@link Collection} - Converted to <c>String[]</c>.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Upgrade upgrade(Supplier<?> value) {
+	public static final Upgrade upgrade(Supplier<List<String>> value) {
 		return Upgrade.of(value);
 	}
 
 	/**
 	 * Creates a new {@link UserAgent} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
-	 */
-	public static final UserAgent userAgent(String value) {
-		return UserAgent.of(value);
-	}
-
-	/**
-	 * Creates a new {@link UserAgent} header.
-	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final UserAgent userAgent(Object value) {
+	public static final UserAgent userAgent(String value) {
 		return UserAgent.of(value);
 	}
 
@@ -2232,41 +1811,23 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final UserAgent userAgent(Supplier<?> value) {
+	public static final UserAgent userAgent(Supplier<String> value) {
 		return UserAgent.of(value);
 	}
 
 	/**
 	 * Creates a new {@link Vary} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
-	 */
-	public static final Vary vary(String value) {
-		return Vary.of(value);
-	}
-
-	/**
-	 * Creates a new {@link Vary} header.
-	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Vary vary(Object value) {
+	public static final Vary vary(String value) {
 		return Vary.of(value);
 	}
 
@@ -2277,23 +1838,21 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Vary vary(Supplier<?> value) {
+	public static final Vary vary(Supplier<String> value) {
 		return Vary.of(value);
 	}
 
 	/**
 	 * Creates a new {@link Via} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
 	public static final Via via(String value) {
 		return Via.of(value);
@@ -2304,17 +1863,10 @@ public class HttpHeaders {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - A comma-delimited string.
-	 * 		<li><c>String[]</c> - A pre-parsed value.
-	 * 		<li>Any other array type - Converted to <c>String[]</c>.
-	 * 		<li>Any {@link Collection} - Converted to <c>String[]</c>.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Via via(Object value) {
+	public static final Via via(List<String> value) {
 		return Via.of(value);
 	}
 
@@ -2325,44 +1877,23 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - A comma-delimited string.
-	 * 		<li><c>String[]</c> - A pre-parsed value.
-	 * 		<li>Any other array type - Converted to <c>String[]</c>.
-	 * 		<li>Any {@link Collection} - Converted to <c>String[]</c>.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Via via(Supplier<?> value) {
+	public static final Via via(Supplier<List<String>> value) {
 		return Via.of(value);
 	}
 
 	/**
 	 * Creates a new {@link Warning} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
-	 */
-	public static final Warning warning(String value) {
-		return Warning.of(value);
-	}
-
-	/**
-	 * Creates a new {@link Warning} header.
-	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Warning warning(Object value) {
+	public static final Warning warning(String value) {
 		return Warning.of(value);
 	}
 
@@ -2373,41 +1904,23 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final Warning warning(Supplier<?> value) {
+	public static final Warning warning(Supplier<String> value) {
 		return Warning.of(value);
 	}
 
 	/**
 	 * Creates a new {@link WwwAuthenticate} header.
 	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
-	 */
-	public static final WwwAuthenticate wwwAuthenticate(String value) {
-		return WwwAuthenticate.of(value);
-	}
-
-	/**
-	 * Creates a new {@link WwwAuthenticate} header.
-	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final WwwAuthenticate wwwAuthenticate(Object value) {
+	public static final WwwAuthenticate wwwAuthenticate(String value) {
 		return WwwAuthenticate.of(value);
 	}
 
@@ -2418,15 +1931,11 @@ public class HttpHeaders {
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static final WwwAuthenticate wwwAuthenticate(Supplier<?> value) {
+	public static final WwwAuthenticate wwwAuthenticate(Supplier<String> value) {
 		return WwwAuthenticate.of(value);
 	}
 
@@ -2438,8 +1947,11 @@ public class HttpHeaders {
 	 * Creates a new {@link BasicBooleanHeader} header.
 	 *
 	 * @param name The header name.
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be parsable by {@link Boolean#parseBoolean(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
 	public static final BasicBooleanHeader booleanHeader(String name, String value) {
 		return BasicBooleanHeader.of(name, value);
@@ -2451,15 +1963,10 @@ public class HttpHeaders {
 	 * @param name The header name.
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link Boolean} - As-is.
-	 * 		<li>{@link String} - Parsed using {@link Boolean#parseBoolean(String)}.
-	 * 		<li>Anything else - Converted to <c>String</c> and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final BasicBooleanHeader booleanHeader(String name, Object value) {
+	public static final BasicBooleanHeader booleanHeader(String name, Boolean value) {
 		return BasicBooleanHeader.of(name, value);
 	}
 
@@ -2471,16 +1978,11 @@ public class HttpHeaders {
 	 *
 	 * @param name The header name.
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link Boolean} - As-is.
-	 * 		<li>{@link String} - Parsed using {@link Boolean#parseBoolean(String)}.
-	 * 		<li>Anything else - Converted to <c>String</c> and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final BasicBooleanHeader booleanHeader(String name, Supplier<?> value) {
+	public static final BasicBooleanHeader booleanHeader(String name, Supplier<Boolean> value) {
 		return BasicBooleanHeader.of(name, value);
 	}
 
@@ -2488,8 +1990,11 @@ public class HttpHeaders {
 	 * Creates a new {@link BasicCsvArrayHeader} header.
 	 *
 	 * @param name The header name.
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be a comma-delimited list.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
 	public static final BasicCsvArrayHeader csvArrayHeader(String name, String value) {
 		return BasicCsvArrayHeader.of(name, value);
@@ -2501,17 +2006,10 @@ public class HttpHeaders {
 	 * @param name The header name.
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - A comma-delimited string.
-	 * 		<li><c>String[]</c> - A pre-parsed value.
-	 * 		<li>Any other array type - Converted to <c>String[]</c>.
-	 * 		<li>Any {@link Collection} - Converted to <c>String[]</c>.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final BasicCsvArrayHeader csvArrayHeader(String name, Object value) {
+	public static final BasicCsvArrayHeader csvArrayHeader(String name, List<String> value) {
 		return BasicCsvArrayHeader.of(name, value);
 	}
 
@@ -2523,18 +2021,11 @@ public class HttpHeaders {
 	 *
 	 * @param name The header name.
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - A comma-delimited string.
-	 * 		<li><c>String[]</c> - A pre-parsed value.
-	 * 		<li>Any other array type - Converted to <c>String[]</c>.
-	 * 		<li>Any {@link Collection} - Converted to <c>String[]</c>.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final BasicCsvArrayHeader csvArrayHeader(String name, Supplier<?> value) {
+	public static final BasicCsvArrayHeader csvArrayHeader(String name, Supplier<List<String>> value) {
 		return BasicCsvArrayHeader.of(name, value);
 	}
 
@@ -2542,8 +2033,11 @@ public class HttpHeaders {
 	 * Creates a new {@link BasicDateHeader} header.
 	 *
 	 * @param name The header name.
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be an RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>).
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
 	public static final BasicDateHeader dateHeader(String name, String value) {
 		return BasicDateHeader.of(name, value);
@@ -2555,16 +2049,10 @@ public class HttpHeaders {
 	 * @param name The header name.
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - An RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>).
-	 * 		<li>{@link ZonedDateTime}
-	 * 		<li>{@link Calendar}
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final BasicDateHeader dateHeader(String name, Object value) {
+	public static final BasicDateHeader dateHeader(String name, ZonedDateTime value) {
 		return BasicDateHeader.of(name, value);
 	}
 
@@ -2576,71 +2064,23 @@ public class HttpHeaders {
 	 *
 	 * @param name The header name.
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - An RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>).
-	 * 		<li>{@link ZonedDateTime}
-	 * 		<li>{@link Calendar}
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final BasicDateHeader dateHeader(String name, Supplier<?> value) {
+	public static final BasicDateHeader dateHeader(String name, Supplier<ZonedDateTime> value) {
 		return BasicDateHeader.of(name, value);
 	}
 
 	/**
-	 * Creates a new {@link Debug} header.
-	 *
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
-	 */
-	public static final Debug debug(String value) {
-		return Debug.of(value);
-	}
-
-	/**
-	 * Creates a new {@link Debug} header.
-	 *
-	 * @param value
-	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link Boolean}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()}.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
-	 */
-	public static final Debug debug(Object value) {
-		return Debug.of(value);
-	}
-
-	/**
-	 * Creates a new {@link Debug} header with a delayed value.
-	 *
-	 * <p>
-	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
-	 *
-	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link Boolean}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()}.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
-	 */
-	public static final Debug debug(Supplier<?> value) {
-		return Debug.of(value);
-	}
-
-	/**
 	 * Creates a new {@link BasicEntityTagArrayHeader} header.
 	 *
 	 * @param name The header name.
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be a comma-delimited list of entity validator values (e.g. <js>"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""</js>).
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
 	public static final BasicEntityTagArrayHeader entityTagArrayHeader(String name, String value) {
 		return BasicEntityTagArrayHeader.of(name, value);
@@ -2652,16 +2092,10 @@ public class HttpHeaders {
 	 * @param name The header name.
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - A comma-delimited list of entity validator values (e.g. <js>"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""</js>).
-	 * 		<li>A collection or array of {@link EntityTag} objects.
-	 * 		<li>A collection or array of anything else - Converted to Strings.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final BasicEntityTagArrayHeader entityTagArrayHeader(String name, Object value) {
+	public static final BasicEntityTagArrayHeader entityTagArrayHeader(String name, List<EntityTag> value) {
 		return BasicEntityTagArrayHeader.of(name, value);
 	}
 
@@ -2673,17 +2107,11 @@ public class HttpHeaders {
 	 *
 	 * @param name The header name.
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - A comma-delimited list of entity validator values (e.g. <js>"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""</js>).
-	 * 		<li>A collection or array of {@link EntityTag} objects.
-	 * 		<li>A collection or array of anything else - Converted to Strings.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final BasicEntityTagArrayHeader entityTagArrayHeader(String name, Supplier<?> value) {
+	public static final BasicEntityTagArrayHeader entityTagArrayHeader(String name, Supplier<List<EntityTag>> value) {
 		return BasicEntityTagArrayHeader.of(name, value);
 	}
 
@@ -2691,8 +2119,11 @@ public class HttpHeaders {
 	 * Creates a new {@link BasicEntityTagHeader} header.
 	 *
 	 * @param name The header name.
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be an entity tag value (e.g. <js>"\"xyzzy\""</js>).
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
 	public static final BasicEntityTagHeader entityTagHeader(String name, String value) {
 		return BasicEntityTagHeader.of(name, value);
@@ -2704,16 +2135,10 @@ public class HttpHeaders {
 	 * @param name The header name.
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - A comma-delimited list of entity validator values (e.g. <js>"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""</js>).
-	 * 		<li>A collection or array of {@link EntityTag} objects.
-	 * 		<li>A collection or array of anything else - Converted to Strings.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final BasicEntityTagHeader entityTagHeader(String name, Object value) {
+	public static final BasicEntityTagHeader entityTagHeader(String name, EntityTag value) {
 		return BasicEntityTagHeader.of(name, value);
 	}
 
@@ -2725,17 +2150,11 @@ public class HttpHeaders {
 	 *
 	 * @param name The header name.
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - A comma-delimited list of entity validator values (e.g. <js>"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""</js>).
-	 * 		<li>A collection or array of {@link EntityTag} objects.
-	 * 		<li>A collection or array of anything else - Converted to Strings.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final BasicEntityTagHeader entityTagHeader(String name, Supplier<?> value) {
+	public static final BasicEntityTagHeader entityTagHeader(String name, Supplier<EntityTag> value) {
 		return BasicEntityTagHeader.of(name, value);
 	}
 
@@ -2743,8 +2162,11 @@ public class HttpHeaders {
 	 * Creates a new {@link BasicIntegerHeader} header.
 	 *
 	 * @param name The header name.
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be parsable using {@link Integer#parseInt(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
 	public static final BasicIntegerHeader integerHeader(String name, String value) {
 		return BasicIntegerHeader.of(name, value);
@@ -2756,15 +2178,10 @@ public class HttpHeaders {
 	 * @param name The header name.
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link Number} - Converted to an integer using {@link Number#intValue()}.
-	 * 		<li>{@link String} - Parsed using {@link Integer#parseInt(String)}.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final BasicIntegerHeader integerHeader(String name, Object value) {
+	public static final BasicIntegerHeader integerHeader(String name, Integer value) {
 		return BasicIntegerHeader.of(name, value);
 	}
 
@@ -2776,16 +2193,11 @@ public class HttpHeaders {
 	 *
 	 * @param name The header name.
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link Number} - Converted to an integer using {@link Number#intValue()}.
-	 * 		<li>{@link String} - Parsed using {@link Integer#parseInt(String)}.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final BasicIntegerHeader integerHeader(String name, Supplier<?> value) {
+	public static final BasicIntegerHeader integerHeader(String name, Supplier<Integer> value) {
 		return BasicIntegerHeader.of(name, value);
 	}
 
@@ -2793,8 +2205,11 @@ public class HttpHeaders {
 	 * Creates a new {@link BasicLongHeader} header.
 	 *
 	 * @param name The header name.
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be parsable by {@link Long#parseLong(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
 	public static final BasicLongHeader longHeader(String name, String value) {
 		return BasicLongHeader.of(name, value);
@@ -2806,15 +2221,11 @@ public class HttpHeaders {
 	 * @param name The header name.
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link Number} - Converted to a long using {@link Number#longValue()}.
-	 * 		<li>{@link String} - Parsed using {@link Long#parseLong(String)}.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Must be parsable by {@link Long#parseLong(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final BasicLongHeader longHeader(String name, Object value) {
+	public static final BasicLongHeader longHeader(String name, Long value) {
 		return BasicLongHeader.of(name, value);
 	}
 
@@ -2826,16 +2237,11 @@ public class HttpHeaders {
 	 *
 	 * @param name The header name.
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link Number} - Converted to a long using {@link Number#longValue()}.
-	 * 		<li>{@link String} - Parsed using {@link Long#parseLong(String)}.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final BasicLongHeader longHeader(String name, Supplier<?> value) {
+	public static final BasicLongHeader longHeader(String name, Supplier<Long> value) {
 		return BasicLongHeader.of(name, value);
 	}
 
@@ -2843,8 +2249,11 @@ public class HttpHeaders {
 	 * Creates a new {@link BasicMediaRangeArrayHeader} header.
 	 *
 	 * @param name The header name.
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be parsable by {@link MediaRanges#of(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
 	public static final BasicMediaRangeArrayHeader mediaRangeArrayHeader(String name, String value) {
 		return BasicMediaRangeArrayHeader.of(name, value);
@@ -2856,14 +2265,10 @@ public class HttpHeaders {
 	 * @param name The header name.
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final BasicMediaRangeArrayHeader mediaRangeArrayHeader(String name, Object value) {
+	public static final BasicMediaRangeArrayHeader mediaRangeArrayHeader(String name, MediaRanges value) {
 		return BasicMediaRangeArrayHeader.of(name, value);
 	}
 
@@ -2875,24 +2280,26 @@ public class HttpHeaders {
 	 *
 	 * @param name The header name.
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The header value.
+	 * 	<br>Must be parsable by {@link MediaRanges#of(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final BasicMediaRangeArrayHeader mediaRangeArrayHeader(String name, Supplier<?> value) {
-		return BasicMediaRangeArrayHeader.of(name, value);
+	public static final BasicMediaRangeArrayHeader mediaRangeArrayHeader(String name, Supplier<MediaRanges> value) {
+		if (isEmpty(name) || value == null)
+			return null;
+		return new BasicMediaRangeArrayHeader(name, value);
 	}
 
 	/**
 	 * Creates a new {@link BasicMediaTypeHeader} header.
 	 *
 	 * @param name The header name.
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be parsable by {@link MediaType#of(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
 	public static final BasicMediaTypeHeader mediaTypeHeader(String name, String value) {
 		return BasicMediaTypeHeader.of(name, value);
@@ -2904,14 +2311,10 @@ public class HttpHeaders {
 	 * @param name The header name.
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final BasicMediaTypeHeader mediaTypeHeader(String name, Object value) {
+	public static final BasicMediaTypeHeader mediaTypeHeader(String name, MediaType value) {
 		return BasicMediaTypeHeader.of(name, value);
 	}
 
@@ -2923,16 +2326,14 @@ public class HttpHeaders {
 	 *
 	 * @param name The header name.
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final BasicMediaTypeHeader mediaTypeHeader(String name, Supplier<?> value) {
-		return BasicMediaTypeHeader.of(name, value);
+	public static final BasicMediaTypeHeader mediaTypeHeader(String name, Supplier<MediaType> value) {
+		if (isEmpty(name) || value == null)
+			return null;
+		return new BasicMediaTypeHeader(name, value);
 	}
 
 	/**
@@ -2941,22 +2342,18 @@ public class HttpHeaders {
 	 * @param pair The pair string.
 	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
 	 */
-	public static final BasicHeader basicHeader(String pair) {
-		return BasicHeader.ofPair(pair);
+	public static final BasicStringHeader stringHeader(String pair) {
+		return BasicStringHeader.ofPair(pair);
 	}
 
 	/**
 	 * Creates a new {@link BasicHeader} header.
 	 *
-	 * @param name The header name.
+	 * @param name The parameter name.
 	 * @param value
-	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()}.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The parameter value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
 	public static final BasicHeader basicHeader(String name, Object value) {
 		return BasicHeader.of(name, value);
@@ -2970,16 +2367,12 @@ public class HttpHeaders {
 	 *
 	 * @param name The header name.
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()}.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
-	 */
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
+	 * */
 	public static final BasicHeader basicHeader(String name, Supplier<?> value) {
-		return BasicHeader.of(name, value);
+		return new BasicHeader(name, value);
 	}
 
 	/**
@@ -2987,39 +2380,73 @@ public class HttpHeaders {
 	 *
 	 * @param name The header name.
 	 * @param value
-	 * 	The header value.
-	 * 	<br>Can be any POJO.
-	 * @return A new header bean.
+	 * 	The POJO to serialize as the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty.
 	 */
 	public static final SerializedHeader serializedHeader(String name, Object value) {
 		return SerializedHeader.of(name, value);
 	}
 
 	/**
-	 * Creates a new {@link SerializedHeader} header with a delayed value.
+	 * Creates a new {@link SerializedHeader} header.
+	 *
+	 * @param name The HTTP header name name.
+	 * @param value
+	 * 	The POJO to serialize as the header value.
+	 * @param serializer
+	 * 	The serializer to use for serializing the value to a string value.
+	 * @param schema
+	 * 	The schema object that defines the format of the output.
+	 * 	<br>If <jk>null</jk>, defaults to the schema defined on the serializer.
+	 * 	<br>If that's also <jk>null</jk>, defaults to {@link HttpPartSchema#DEFAULT}.
+	 * 	<br>Only used if serializer is schema-aware (e.g. {@link OpenApiSerializer}).
+	 * 	<br>Can also be a {@link Supplier}.
+	 * @param skipIfEmpty If value is a blank string, the value should return as <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty.
+	 */
+	public static SerializedHeader serializedHeader(String name, Object value, HttpPartSerializerSession serializer, HttpPartSchema schema, boolean skipIfEmpty) {
+		return SerializedHeader.of(name, value, serializer, schema, skipIfEmpty);
+	}
+
+	/**
+	 * Creates a new {@link SerializedHeader} header.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
-	 * @param name The header name.
+	 * @param name The HTTP header name name.
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any POJO.
-	 * @return A new header bean.
+	 * 	The supplier of the POJO to serialize as the header value.
+	 * @param serializer
+	 * 	The serializer to use for serializing the value to a string value.
+	 * @param schema
+	 * 	The schema object that defines the format of the output.
+	 * 	<br>If <jk>null</jk>, defaults to the schema defined on the serializer.
+	 * 	<br>If that's also <jk>null</jk>, defaults to {@link HttpPartSchema#DEFAULT}.
+	 * 	<br>Only used if serializer is schema-aware (e.g. {@link OpenApiSerializer}).
+	 * 	<br>Can also be a {@link Supplier}.
+	 * @param skipIfEmpty If value is a blank string, the value should return as <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty.
 	 */
-	public static final SerializedHeader serializedHeader(String name, Supplier<?> value) {
-		return SerializedHeader.of(name, value);
+	public static SerializedHeader serializedHeader(String name, Supplier<?> value, HttpPartSerializerSession serializer, HttpPartSchema schema, boolean skipIfEmpty) {
+		return SerializedHeader.of(name, value, serializer, schema, skipIfEmpty);
 	}
 
 	/**
-	 * Creates a new {@link BasicStringHeader} header.
+	 * Creates a new {@link SerializedHeader} header with a delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link Header#getValue()}.
 	 *
 	 * @param name The header name.
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The supplier of the POJO to serialize as the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty.
 	 */
-	public static final BasicStringHeader stringHeader(String name, String value) {
-		return BasicStringHeader.of(name, value);
+	public static final SerializedHeader serializedHeader(String name, Supplier<?> value) {
+		return SerializedHeader.of(name, value);
 	}
 
 	/**
@@ -3028,14 +2455,10 @@ public class HttpHeaders {
 	 * @param name The header name.
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()}.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final BasicStringHeader stringHeader(String name, Object value) {
+	public static final BasicStringHeader stringHeader(String name, String value) {
 		return BasicStringHeader.of(name, value);
 	}
 
@@ -3047,15 +2470,11 @@ public class HttpHeaders {
 	 *
 	 * @param name The header name.
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()}.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final BasicStringHeader stringHeader(String name, Supplier<?> value) {
+	public static final BasicStringHeader stringHeader(String name, Supplier<String> value) {
 		return BasicStringHeader.of(name, value);
 	}
 
@@ -3063,8 +2482,11 @@ public class HttpHeaders {
 	 * Creates a new {@link BasicStringRangeArrayHeader} header.
 	 *
 	 * @param name The header name.
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be parsable by {@link StringRanges#of(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
 	public static final BasicStringRangeArrayHeader stringRangeArrayHeader(String name, String value) {
 		return BasicStringRangeArrayHeader.of(name, value);
@@ -3075,16 +2497,11 @@ public class HttpHeaders {
 	 *
 	 * @param name The header name.
 	 * @param value
-	 * 	The parameter value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String} - Converted using {@link StringRanges#of(String)}.
-	 * 		<li>{@link StringRanges} - Left as-is.
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final BasicStringRangeArrayHeader stringRangeArrayHeader(String name, Object value) {
+	public static final BasicStringRangeArrayHeader stringRangeArrayHeader(String name, StringRanges value) {
 		return BasicStringRangeArrayHeader.of(name, value);
 	}
 
@@ -3096,16 +2513,11 @@ public class HttpHeaders {
 	 *
 	 * @param name The header name.
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String} - Converted using {@link StringRanges#of(String)}.
-	 * 		<li>{@link StringRanges} - Left as-is.
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final BasicStringRangeArrayHeader stringRangeArrayHeader(String name, Supplier<?> value) {
+	public static final BasicStringRangeArrayHeader stringRangeArrayHeader(String name, Supplier<StringRanges> value) {
 		return BasicStringRangeArrayHeader.of(name, value);
 	}
 
@@ -3113,8 +2525,11 @@ public class HttpHeaders {
 	 * Creates a new {@link BasicUriHeader} header.
 	 *
 	 * @param name The header name.
-	 * @param value The header value.
-	 * @return A new (possibly cached) header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be parsable by {@link URI#create(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
 	public static final BasicUriHeader uriHeader(String name, String value) {
 		return BasicUriHeader.of(name, value);
@@ -3126,14 +2541,10 @@ public class HttpHeaders {
 	 * @param name The header name.
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final BasicUriHeader uriHeader(String name, Object value) {
+	public static final BasicUriHeader uriHeader(String name, URI value) {
 		return BasicUriHeader.of(name, value);
 	}
 
@@ -3145,15 +2556,11 @@ public class HttpHeaders {
 	 *
 	 * @param name The header name.
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be a supplier of any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static final BasicUriHeader uriHeader(String name, Supplier<?> value) {
+	public static final BasicUriHeader uriHeader(String name, Supplier<URI> value) {
 		return BasicUriHeader.of(name, value);
 	}
 
@@ -3231,7 +2638,46 @@ public class HttpHeaders {
 	 * @throws RuntimeException If odd number of parameters were specified.
 	 * @return A new instance.
 	 */
-	public static HeaderList headerList(Object...pairs) {
+	public static HeaderList headerList(String...pairs) {
 		return HeaderList.ofPairs(pairs);
 	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// Utility methods.
+	//-----------------------------------------------------------------------------------------------------------------
+
+	/**
+	 * Returns <jk>true</jk> if the {@link #cast(Object)} method can be used on the specified object.
+	 *
+	 * @param o The object to check.
+	 * @return <jk>true</jk> if the {@link #cast(Object)} method can be used on the specified object.
+	 */
+	public static boolean canCast(Object o) {
+		ClassInfo ci = ClassInfo.of(o);
+		return ci != null && ci.isChildOfAny(Header.class, Headerable.class, NameValuePair.class, NameValuePairable.class, Map.Entry.class);
+	}
+
+	/**
+	 * Utility method for converting an arbitrary object to a {@link Header}.
+	 *
+	 * @param o
+	 * 	The object to cast or convert to a {@link Header}.
+	 * @return Either the same object cast as a {@link Header} or converted to a {@link Header}.
+	 */
+	@SuppressWarnings("rawtypes")
+	public static Header cast(Object o) {
+		if (o instanceof Header)
+			return (Header)o;
+		if (o instanceof Headerable)
+			return ((Headerable)o).asHeader();
+		if (o instanceof NameValuePair)
+			return BasicHeader.of((NameValuePair)o);
+		if (o instanceof NameValuePairable)
+			return BasicHeader.of(((NameValuePairable)o).asNameValuePair());
+		if (o instanceof Map.Entry) {
+			Map.Entry e = (Map.Entry)o;
+			return BasicHeader.of(stringify(e.getKey()), stringify(e.getValue()));
+		}
+		throw runtimeException("Object of type {0} could not be converted to a Header.", o == null ? null : o.getClass().getName());
+	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HttpParts.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HttpParts.java
index d9e61a6..00c1344 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HttpParts.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HttpParts.java
@@ -16,6 +16,7 @@ import java.time.*;
 import java.util.*;
 import java.util.function.*;
 
+import org.apache.http.*;
 import org.apache.juneau.http.part.*;
 
 /**
@@ -45,7 +46,7 @@ public class HttpParts {
 	 * Creates a new {@link BasicBooleanPart} part with a delayed value.
 	 *
 	 * <p>
-	 * Part value is re-evaluated on each call to {@link Part#getValue()}.
+	 * Part value is re-evaluated on each call to {@link NameValuePair#getValue()}.
 	 *
 	 * @param name The part name.
 	 * @param value
@@ -86,7 +87,7 @@ public class HttpParts {
 	 * Creates a new {@link BasicCsvArrayPart} part with a delayed value.
 	 *
 	 * <p>
-	 * Part value is re-evaluated on each call to {@link Part#getValue()}.
+	 * Part value is re-evaluated on each call to {@link NameValuePair#getValue()}.
 	 *
 	 * @param name The part name.
 	 * @param value
@@ -128,7 +129,7 @@ public class HttpParts {
 	 * Creates a new {@link BasicDatePart} part with a delayed value.
 	 *
 	 * <p>
-	 * Part value is re-evaluated on each call to {@link Part#getValue()}.
+	 * Part value is re-evaluated on each call to {@link NameValuePair#getValue()}.
 	 *
 	 * @param name The part name.
 	 * @param value
@@ -168,7 +169,7 @@ public class HttpParts {
 	 * Creates a new {@link BasicIntegerPart} part with a delayed value.
 	 *
 	 * <p>
-	 * Part value is re-evaluated on each call to {@link Part#getValue()}.
+	 * Part value is re-evaluated on each call to {@link NameValuePair#getValue()}.
 	 *
 	 * @param name The part name.
 	 * @param value
@@ -207,7 +208,7 @@ public class HttpParts {
 	 * Creates a new {@link BasicLongPart} part with a delayed value.
 	 *
 	 * <p>
-	 * Part value is re-evaluated on each call to {@link Part#getValue()}.
+	 * Part value is re-evaluated on each call to {@link NameValuePair#getValue()}.
 	 *
 	 * @param name The part name.
 	 * @param value
@@ -245,7 +246,7 @@ public class HttpParts {
 	 * Creates a new {@link BasicUriPart} part with a delayed value.
 	 *
 	 * <p>
-	 * Part value is re-evaluated on each call to {@link Part#getValue()}.
+	 * Part value is re-evaluated on each call to {@link NameValuePair#getValue()}.
 	 *
 	 * @param name The header name.
 	 * @param value
@@ -286,7 +287,7 @@ public class HttpParts {
 	 * Creates a new {@link BasicPart} part with a delayed value.
 	 *
 	 * <p>
-	 * Part value is re-evaluated on each call to {@link Part#getValue()}.
+	 * Part value is re-evaluated on each call to {@link NameValuePair#getValue()}.
 	 *
 	 * @param name The part name.
 	 * @param value The part value supplier.
@@ -317,7 +318,7 @@ public class HttpParts {
 	 * Creates a new {@link BasicStringPart} part with a delayed value.
 	 *
 	 * <p>
-	 * Part value is re-evaluated on each call to {@link Part#getValue()}.
+	 * Part value is re-evaluated on each call to {@link NameValuePair#getValue()}.
 	 *
 	 * @param name The part name.
 	 * @param value
@@ -374,7 +375,7 @@ public class HttpParts {
 	 * @param parts The parts to add to the list.  Can be <jk>null</jk>.  <jk>null</jk> entries are ignored.
 	 * @return A new unmodifiable instance, never <jk>null</jk>.
 	 */
-	public static final PartList partList(List<Part> parts) {
+	public static final PartList partList(List<NameValuePair> parts) {
 		return PartList.of(parts);
 	}
 
@@ -384,7 +385,7 @@ public class HttpParts {
 	 * @param parts The parts to add to the list.  <jk>null</jk> entries are ignored.
 	 * @return A new unmodifiable instance, never <jk>null</jk>.
 	 */
-	public static final PartList partList(Part...parts) {
+	public static final PartList partList(NameValuePair...parts) {
 		return PartList.of(parts);
 	}
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Accept.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Accept.java
index 2bd132a..078a1f0 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Accept.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Accept.java
@@ -13,7 +13,6 @@
 package org.apache.juneau.http.header;
 
 import static org.apache.juneau.http.header.Constants.*;
-import static org.apache.juneau.internal.StringUtils.*;
 
 import java.util.function.*;
 
@@ -146,6 +145,7 @@ import org.apache.juneau.internal.*;
 public class Accept extends BasicMediaRangeArrayHeader {
 
 	private static final long serialVersionUID = 1L;
+	private static final String NAME = "Accept";
 
 	private static final Cache<String,Accept> CACHE = new Cache<>(NOCACHE, CACHE_MAX_SIZE);
 
@@ -174,19 +174,21 @@ public class Accept extends BasicMediaRangeArrayHeader {
 		WILDCARD = of("*/*");
 
 	/**
-	 * Returns a parsed and cached header.
+	 * Convenience creator.
 	 *
 	 * @param value
 	 * 	The header value.
-	 * @return A cached {@link AcceptCharset} object.
+	 * 	<br>Must be parsable by {@link MediaRanges#of(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
 	public static Accept of(String value) {
-		if (isEmpty(value))
+		if (value == null)
 			return null;
 		Accept x = CACHE.get(value);
 		if (x == null)
 			x = CACHE.put(value, new Accept(value));
-		return x;
+		return new Accept(value);
 	}
 
 	/**
@@ -194,63 +196,80 @@ public class Accept extends BasicMediaRangeArrayHeader {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link Accept} object.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static Accept of(Object value) {
-		if (isEmpty(value))
+	public static Accept of(MediaRanges value) {
+		if (value == null)
 			return null;
 		return new Accept(value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
+	 * Convenience creator.
+	 *
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
+	 */
+	public static Accept of(MediaType value) {
+		if (value == null)
+			return null;
+		return new Accept(value.toString());
+	}
+
+	/**
+	 * Convenience creator with delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link Accept} object.
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static Accept of(Supplier<?> value) {
+	public static Accept of(Supplier<MediaRanges> value) {
 		if (value == null)
 			return null;
 		return new Accept(value);
 	}
 
 	/**
-	 * Constructor
+	 * Constructor.
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * 	<br>Must be parsable by {@link MediaRanges#of(String)}.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public Accept(Object value) {
-		super("Accept", value);
+	public Accept(String value) {
+		super(NAME, value);
 	}
 
 	/**
-	 * Constructor
+	 * Constructor.
 	 *
 	 * @param value
 	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public Accept(String value) {
-		this((Object)value);
+	public Accept(MediaRanges value) {
+		super(NAME, value);
+	}
+
+	/**
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
+	 *
+	 * @param value
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public Accept(Supplier<MediaRanges> value) {
+		super(NAME, value);
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/AcceptCharset.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/AcceptCharset.java
index 8952a94..aa691dc 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/AcceptCharset.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/AcceptCharset.java
@@ -76,15 +76,18 @@ import org.apache.juneau.internal.*;
 public class AcceptCharset extends BasicStringRangeArrayHeader {
 
 	private static final long serialVersionUID = 1L;
+	private static final String NAME = "Accept-Charset";
 
 	private static final Cache<String,AcceptCharset> CACHE = new Cache<>(NOCACHE, CACHE_MAX_SIZE);
 
 	/**
-	 * Returns a parsed and cached header.
+	 * Convenience creator.
 	 *
 	 * @param value
 	 * 	The header value.
-	 * @return A cached {@link AcceptCharset} object.
+	 * 	<br>Must be parsable by {@link StringRanges#of(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
 	public static AcceptCharset of(String value) {
 		if (value == null)
@@ -92,7 +95,7 @@ public class AcceptCharset extends BasicStringRangeArrayHeader {
 		AcceptCharset x = CACHE.get(value);
 		if (x == null)
 			x = CACHE.put(value, new AcceptCharset(value));
-		return x;
+		return new AcceptCharset(value);
 	}
 
 	/**
@@ -100,66 +103,67 @@ public class AcceptCharset extends BasicStringRangeArrayHeader {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String} - Converted using {@link StringRanges#of(String)}.
-	 * 		<li><c>StringRange[]</c> - Left as-is.
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link AcceptCharset} object.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static AcceptCharset of(Object value) {
+	public static AcceptCharset of(StringRanges value) {
 		if (value == null)
 			return null;
 		return new AcceptCharset(value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
+	 * Convenience creator with delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String} - Converted using {@link StringRanges#of(String)}.
-	 * 		<li><c>StringRange[]</c> - Left as-is.
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link AcceptCharset} object.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static AcceptCharset of(Supplier<?> value) {
+	public static AcceptCharset of(Supplier<StringRanges> value) {
 		if (value == null)
 			return null;
 		return new AcceptCharset(value);
 	}
 
+
 	/**
-	 * Constructor
+	 * Constructor.
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String} - Converted using {@link StringRanges#of(String)}.
-	 * 		<li><c>StringRange[]</c> - Left as-is.
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * 	<br>Must be parsable by {@link StringRanges#of(String)}.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public AcceptCharset(Object value) {
-		super("Accept-Charset", value);
+	public AcceptCharset(String value) {
+		super(NAME, value);
 	}
 
 	/**
-	 * Constructor
+	 * Constructor.
 	 *
 	 * @param value
 	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public AcceptCharset(String value) {
-		this((Object)value);
+	public AcceptCharset(StringRanges value) {
+		super(NAME, value);
+	}
+
+	/**
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
+	 *
+	 * @param value
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public AcceptCharset(Supplier<StringRanges> value) {
+		super(NAME, value);
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/AcceptEncoding.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/AcceptEncoding.java
index 8d98f4e..4152312 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/AcceptEncoding.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/AcceptEncoding.java
@@ -96,15 +96,18 @@ import org.apache.juneau.internal.*;
 public class AcceptEncoding extends BasicStringRangeArrayHeader {
 
 	private static final long serialVersionUID = 1L;
+	private static final String NAME = "Accept-Encoding";
 
 	private static final Cache<String,AcceptEncoding> CACHE = new Cache<>(NOCACHE, CACHE_MAX_SIZE);
 
 	/**
-	 * Returns a parsed and cached header.
+	 * Convenience creator.
 	 *
 	 * @param value
 	 * 	The header value.
-	 * @return A cached {@link AcceptCharset} object.
+	 * 	<br>Must be parsable by {@link StringRanges#of(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
 	public static AcceptEncoding of(String value) {
 		if (value == null)
@@ -112,7 +115,7 @@ public class AcceptEncoding extends BasicStringRangeArrayHeader {
 		AcceptEncoding x = CACHE.get(value);
 		if (x == null)
 			x = CACHE.put(value, new AcceptEncoding(value));
-		return x;
+		return new AcceptEncoding(value);
 	}
 
 	/**
@@ -120,66 +123,67 @@ public class AcceptEncoding extends BasicStringRangeArrayHeader {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String} - Converted using {@link StringRanges#of(String)}.
-	 * 		<li><c>StringRange[]</c> - Left as-is.
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link AcceptEncoding} object.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static AcceptEncoding of(Object value) {
+	public static AcceptEncoding of(StringRanges value) {
 		if (value == null)
 			return null;
 		return new AcceptEncoding(value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
+	 * Convenience creator with delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String} - Converted using {@link StringRanges#of(String)}.
-	 * 		<li><c>StringRange[]</c> - Left as-is.
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link AcceptEncoding} object.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static AcceptEncoding of(Supplier<?> value) {
+	public static AcceptEncoding of(Supplier<StringRanges> value) {
 		if (value == null)
 			return null;
 		return new AcceptEncoding(value);
 	}
 
+
 	/**
-	 * Constructor
+	 * Constructor.
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String} - Converted using {@link StringRanges#of(String)}.
-	 * 		<li><c>StringRange[]</c> - Left as-is.
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * 	<br>Must be parsable by {@link StringRanges#of(String)}.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public AcceptEncoding(Object value) {
-		super("Accept-Encoding", value);
+	public AcceptEncoding(String value) {
+		super(NAME, value);
 	}
 
 	/**
-	 * Constructor
+	 * Constructor.
 	 *
 	 * @param value
 	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public AcceptEncoding(String value) {
-		this((Object)value);
+	public AcceptEncoding(StringRanges value) {
+		super(NAME, value);
+	}
+
+	/**
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
+	 *
+	 * @param value
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public AcceptEncoding(Supplier<StringRanges> value) {
+		super(NAME, value);
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/AcceptLanguage.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/AcceptLanguage.java
index f3fd1dc..b6018ca 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/AcceptLanguage.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/AcceptLanguage.java
@@ -108,15 +108,18 @@ import org.apache.juneau.internal.*;
 public class AcceptLanguage extends BasicStringRangeArrayHeader {
 
 	private static final long serialVersionUID = 1L;
+	private static final String NAME = "Accept-Language";
 
 	private static final Cache<String,AcceptLanguage> CACHE = new Cache<>(NOCACHE, CACHE_MAX_SIZE);
 
 	/**
-	 * Returns a parsed and cached header.
+	 * Convenience creator.
 	 *
 	 * @param value
 	 * 	The header value.
-	 * @return A cached {@link AcceptLanguage} object.
+	 * 	<br>Must be parsable by {@link StringRanges#of(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
 	public static AcceptLanguage of(String value) {
 		if (value == null)
@@ -124,7 +127,7 @@ public class AcceptLanguage extends BasicStringRangeArrayHeader {
 		AcceptLanguage x = CACHE.get(value);
 		if (x == null)
 			x = CACHE.put(value, new AcceptLanguage(value));
-		return x;
+		return new AcceptLanguage(value);
 	}
 
 	/**
@@ -132,62 +135,67 @@ public class AcceptLanguage extends BasicStringRangeArrayHeader {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String} - Converted using {@link StringRanges#of(String)}.
-	 * 		<li><c>StringRange[]</c> - Left as-is.
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link AcceptLanguage} object.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static AcceptLanguage of(Object value) {
+	public static AcceptLanguage of(StringRanges value) {
+		if (value == null)
+			return null;
 		return new AcceptLanguage(value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
+	 * Convenience creator with delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String} - Converted using {@link StringRanges#of(String)}.
-	 * 		<li><c>StringRange[]</c> - Left as-is.
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link AcceptLanguage} object.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static AcceptLanguage of(Supplier<?> value) {
+	public static AcceptLanguage of(Supplier<StringRanges> value) {
+		if (value == null)
+			return null;
 		return new AcceptLanguage(value);
 	}
 
+
 	/**
-	 * Constructor
+	 * Constructor.
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String} - Converted using {@link StringRanges#of(String)}.
-	 * 		<li><c>StringRange[]</c> - Left as-is.
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * 	<br>Must be parsable by {@link StringRanges#of(String)}.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public AcceptLanguage(Object value) {
-		super("Accept-Language", value);
+	public AcceptLanguage(String value) {
+		super(NAME, value);
 	}
 
 	/**
-	 * Constructor
+	 * Constructor.
 	 *
 	 * @param value
 	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public AcceptLanguage(String value) {
-		this((Object)value);
+	public AcceptLanguage(StringRanges value) {
+		super(NAME, value);
+	}
+
+	/**
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
+	 *
+	 * @param value
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public AcceptLanguage(Supplier<StringRanges> value) {
+		super(NAME, value);
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/AcceptRanges.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/AcceptRanges.java
index 8ecc752..94ed7e8 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/AcceptRanges.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/AcceptRanges.java
@@ -66,41 +66,34 @@ import org.apache.juneau.http.annotation.*;
 public class AcceptRanges extends BasicStringHeader {
 
 	private static final long serialVersionUID = 1L;
+	private static final String NAME = "Accept-Ranges";
 
 	/**
 	 * Convenience creator.
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link AcceptRanges} object.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static AcceptRanges of(Object value) {
+	public static AcceptRanges of(String value) {
 		if (value == null)
 			return null;
 		return new AcceptRanges(value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
+	 * Convenience creator with delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link AcceptRanges} object.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static AcceptRanges of(Supplier<?> value) {
+	public static AcceptRanges of(Supplier<String> value) {
 		if (value == null)
 			return null;
 		return new AcceptRanges(value);
@@ -111,24 +104,23 @@ public class AcceptRanges extends BasicStringHeader {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public AcceptRanges(Object value) {
-		super("Accept-Ranges", value);
+	public AcceptRanges(String value) {
+		super(NAME, value);
 	}
 
 	/**
-	 * Constructor
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param value
-	 * 	The header value.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public AcceptRanges(String value) {
-		this((Object)value);
+	public AcceptRanges(Supplier<String> value) {
+		super(NAME, value);
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Age.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Age.java
index 96f40a5..f86704f 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Age.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Age.java
@@ -61,43 +61,49 @@ import org.apache.juneau.http.annotation.*;
 public class Age extends BasicIntegerHeader {
 
 	private static final long serialVersionUID = 1L;
+	private static final String NAME = "Age";
 
 	/**
 	 * Convenience creator.
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link Number} - Converted to an integer using {@link Number#intValue()}.
-	 * 		<li>{@link String} - Parsed using {@link Integer#parseInt(String)}.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new {@link BasicIntegerHeader} object.
+	 * 	<br>Must be parsable using {@link Integer#parseInt(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static Age of(Object value) {
+	public static Age of(String value) {
 		if (value == null)
 			return null;
 		return new Age(value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
+	 * Convenience creator.
+	 *
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
+	 */
+	public static Age of(Integer value) {
+		if (value == null)
+			return null;
+		return new Age(value);
+	}
+
+	/**
+	 * Convenience creator with delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link Number} - Converted to an integer using {@link Number#intValue()}.
-	 * 		<li>{@link String} - Parsed using {@link Integer#parseInt(String)}.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new {@link BasicIntegerHeader} object.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static Age of(Supplier<?> value) {
+	public static Age of(Supplier<Integer> value) {
 		if (value == null)
 			return null;
 		return new Age(value);
@@ -108,25 +114,35 @@ public class Age extends BasicIntegerHeader {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link Number} - Converted to an integer using {@link Number#intValue()}.
-	 * 		<li>{@link String} - Parsed using {@link Integer#parseInt(String)}.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * 	<br>Must be parsable using {@link Integer#parseInt(String)}.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public Age(Object value) {
-		super("Age", value);
+	public Age(String value) {
+		super(NAME, value);
 	}
 
 	/**
-	 * Constructor
+	 * Constructor.
 	 *
 	 * @param value
 	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public Age(String value) {
-		this((Object)value);
+	public Age(Integer value) {
+		super(NAME, value);
+	}
+
+	/**
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
+	 *
+	 * @param value
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public Age(Supplier<Integer> value) {
+		super(NAME, value);
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Allow.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Allow.java
index cebe6d0..5edcccf 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Allow.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Allow.java
@@ -72,47 +72,48 @@ import org.apache.juneau.http.annotation.*;
 public class Allow extends BasicCsvArrayHeader {
 
 	private static final long serialVersionUID = 1L;
+	private static final String NAME = "Allow";
 
 	/**
 	 * Convenience creator.
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - A comma-delimited string.
-	 * 		<li><c>String[]</c> - A pre-parsed value.
-	 * 		<li>Any other array type - Converted to <c>String[]</c>.
-	 * 		<li>Any {@link Collection} - Converted to <c>String[]</c>.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return The parsed <c>Allow</c> header, or <jk>null</jk> if the value was null.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static Allow of(Object value) {
+	public static Allow of(String value) {
 		if (value == null)
 			return null;
 		return new Allow(value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
+	 * Convenience creator.
+	 *
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
+	 */
+	public static Allow of(List<String> value) {
+		if (value == null)
+			return null;
+		return new Allow(value);
+	}
+
+	/**
+	 * Convenience creator with delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - A comma-delimited string.
-	 * 		<li><c>String[]</c> - A pre-parsed value.
-	 * 		<li>Any other array type - Converted to <c>String[]</c>.
-	 * 		<li>Any {@link Collection} - Converted to <c>String[]</c>.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return The parsed <c>Allow</c> header, or <jk>null</jk> if the value was null.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static Allow of(Supplier<?> value) {
+	public static Allow of(Supplier<List<String>> value) {
 		if (value == null)
 			return null;
 		return new Allow(value);
@@ -123,27 +124,34 @@ public class Allow extends BasicCsvArrayHeader {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - A comma-delimited string.
-	 * 		<li><c>String[]</c> - A pre-parsed value.
-	 * 		<li>Any other array type - Converted to <c>String[]</c>.
-	 * 		<li>Any {@link Collection} - Converted to <c>String[]</c>.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public Allow(Object value) {
-		super("Allow", value);
+	public Allow(String value) {
+		super(NAME, value);
 	}
 
 	/**
-	 * Constructor
+	 * Constructor.
 	 *
 	 * @param value
 	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public Allow(String value) {
-		this((Object)value);
+	public Allow(List<String> value) {
+		super(NAME, value);
+	}
+
+	/**
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
+	 *
+	 * @param value
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public Allow(Supplier<List<String>> value) {
+		super(NAME, value);
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Authorization.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Authorization.java
index 2bcc77f..a3f37b3 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Authorization.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Authorization.java
@@ -75,41 +75,34 @@ import org.apache.juneau.http.annotation.*;
 public class Authorization extends BasicStringHeader {
 
 	private static final long serialVersionUID = 1L;
+	private static final String NAME = "Authorization";
 
 	/**
 	 * Convenience creator.
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link Authorization} object.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static Authorization of(Object value) {
+	public static Authorization of(String value) {
 		if (value == null)
 			return null;
 		return new Authorization(value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
+	 * Convenience creator with delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link Authorization} object.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static Authorization of(Supplier<?> value) {
+	public static Authorization of(Supplier<String> value) {
 		if (value == null)
 			return null;
 		return new Authorization(value);
@@ -120,24 +113,23 @@ public class Authorization extends BasicStringHeader {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public Authorization(Object value) {
-		super("Authorization", value);
+	public Authorization(String value) {
+		super(NAME, value);
 	}
 
 	/**
-	 * Constructor
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param value
-	 * 	The header value.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public Authorization(String value) {
-		this((Object)value);
+	public Authorization(Supplier<String> value) {
+		super(NAME, value);
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicBooleanHeader.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicBooleanHeader.java
index 57ace35..346065f 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicBooleanHeader.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicBooleanHeader.java
@@ -45,44 +45,52 @@ public class BasicBooleanHeader extends BasicHeader {
 	 * @param name The header name.
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link Boolean} - As-is.
-	 * 		<li>{@link String} - Parsed using {@link Boolean#parseBoolean(String)}.
-	 * 		<li>Anything else - Converted to <c>String</c> and then parsed.
-	 * 	</ul>
-	 * @return A new {@link BasicBooleanHeader} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
+	 * 	<br>Must be parsable by {@link Boolean#parseBoolean(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static BasicBooleanHeader of(String name, Object value) {
+	public static BasicBooleanHeader of(String name, String value) {
 		if (isEmpty(name) || value == null)
 			return null;
 		return new BasicBooleanHeader(name, value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
+	 * Convenience creator.
+	 *
+	 * @param name The header name.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
+	 */
+	public static BasicBooleanHeader of(String name, Boolean value) {
+		if (isEmpty(name) || value == null)
+			return null;
+		return new BasicBooleanHeader(name, value);
+	}
+
+	/**
+	 * Convenience creator with delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param name The header name.
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link Boolean} - As-is.
-	 * 		<li>{@link String} - Parsed using {@link Boolean#parseBoolean(String)}.
-	 * 		<li>Anything else - Converted to <c>String</c> and then parsed.
-	 * 	</ul>
-	 * @return A new {@link BasicBooleanHeader} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static BasicBooleanHeader of(String name, Supplier<?> value) {
+	public static BasicBooleanHeader of(String name, Supplier<Boolean> value) {
 		if (isEmpty(name) || value == null)
 			return null;
 		return new BasicBooleanHeader(name, value);
 	}
 
-	private Boolean parsed;
+
+	private final Boolean value;
+	private final Supplier<Boolean> supplier;
 
 	/**
 	 * Constructor.
@@ -90,23 +98,51 @@ public class BasicBooleanHeader extends BasicHeader {
 	 * @param name The header name.
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link Boolean} - As-is.
-	 * 		<li>{@link String} - Parsed using {@link Boolean#parseBoolean(String)}.
-	 * 		<li>Anything else - Converted to <c>String</c> and then parsed.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * 	<br>Must be parsable by {@link Boolean#parseBoolean(String)}.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public BasicBooleanHeader(String name, Object value) {
+	public BasicBooleanHeader(String name, String value) {
 		super(name, value);
-		if (! isSupplier(value))
-			parsed = getParsedValue();
+		this.value = parse(value);
+		this.supplier = null;
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param name The header name.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public BasicBooleanHeader(String name, Boolean value) {
+		super(name, serialize(value));
+		this.value = value;
+		this.supplier = null;
+	}
+
+	/**
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
+	 *
+	 * @param name The header name.
+	 * @param value
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public BasicBooleanHeader(String name, Supplier<Boolean> value) {
+		super(name, null);
+		this.value = null;
+		this.supplier = value;
 	}
 
 	@Override /* Header */
 	public String getValue() {
-		return stringify(getParsedValue());
+		if (supplier != null)
+			return serialize(supplier.get());
+		return super.getValue();
 	}
 
 	/**
@@ -115,7 +151,18 @@ public class BasicBooleanHeader extends BasicHeader {
 	 * @return The header value as a boolean.
 	 */
 	public Optional<Boolean> asBoolean() {
-		return ofNullable(getParsedValue());
+		if (supplier != null)
+			return ofNullable(supplier.get());
+		return ofNullable(value);
+	}
+
+	/**
+	 * Returns <jk>true</jk> if the header value is <jk>true</jk>.
+	 *
+	 * @return <jk>true</jk> if the header value is <jk>true</jk>.
+	 */
+	public boolean isTrue() {
+		return asBoolean().orElse(false).booleanValue();
 	}
 
 	/**
@@ -134,18 +181,14 @@ public class BasicBooleanHeader extends BasicHeader {
 	 * @throws AssertionError If assertion failed.
 	 */
 	public FluentBooleanAssertion<BasicBooleanHeader> assertBoolean() {
-		return new FluentBooleanAssertion<>(getParsedValue(), this);
+		return new FluentBooleanAssertion<>(asBoolean().orElse(null), this);
 	}
 
-	private Boolean getParsedValue() {
-		if (parsed != null)
-			return parsed;
-		Object o = getRawValue();
-		if (o == null)
-			return null;
-		if (o instanceof Boolean)
-			return (Boolean)o;
-		String s = o.toString();
-		return Boolean.parseBoolean(s);
+	private static String serialize(Boolean value) {
+		return stringify(value);
+	}
+
+	private Boolean parse(String value) {
+		return value == null ? null : Boolean.parseBoolean(value);
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicCsvArrayHeader.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicCsvArrayHeader.java
index 72b8d20..45941c2 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicCsvArrayHeader.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicCsvArrayHeader.java
@@ -13,14 +13,13 @@
 package org.apache.juneau.http.header;
 
 import static org.apache.juneau.internal.StringUtils.*;
+import static java.util.Collections.*;
 import static java.util.Optional.*;
 
-import java.lang.reflect.*;
 import java.util.*;
 import java.util.function.*;
 
 import org.apache.juneau.assertions.*;
-import org.apache.juneau.collections.*;
 
 /**
  * Category of headers that consist of a comma-delimited list of string values.
@@ -45,48 +44,51 @@ public class BasicCsvArrayHeader extends BasicHeader {
 	 * @param name The header name.
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - A comma-delimited string.
-	 * 		<li><c>String[]</c> - A pre-parsed value.
-	 * 		<li>Any other array type - Converted to <c>String[]</c>.
-	 * 		<li>Any {@link Collection} - Converted to <c>String[]</c>.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new {@link BasicCsvArrayHeader} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
+	 * 	<br>Must be a comma-delimited list.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static BasicCsvArrayHeader of(String name, Object value) {
+	public static BasicCsvArrayHeader of(String name, String value) {
 		if (isEmpty(name) || value == null)
 			return null;
 		return new BasicCsvArrayHeader(name, value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
+	 * Convenience creator.
+	 *
+	 * @param name The header name.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
+	 */
+	public static BasicCsvArrayHeader of(String name, List<String> value) {
+		if (isEmpty(name) || value == null)
+			return null;
+		return new BasicCsvArrayHeader(name, value);
+	}
+
+	/**
+	 * Convenience creator with delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param name The header name.
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - A comma-delimited string.
-	 * 		<li><c>String[]</c> - A pre-parsed value.
-	 * 		<li>Any other array type - Converted to <c>String[]</c>.
-	 * 		<li>Any {@link Collection} - Converted to <c>String[]</c>.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new {@link BasicCsvArrayHeader} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static BasicCsvArrayHeader of(String name, Supplier<?> value) {
+	public static BasicCsvArrayHeader of(String name, Supplier<List<String>> value) {
 		if (isEmpty(name) || value == null)
 			return null;
 		return new BasicCsvArrayHeader(name, value);
 	}
 
-	private List<String> parsed;
+	private final List<String> value;
+	private final Supplier<List<String>> supplier;
 
 	/**
 	 * Constructor.
@@ -94,28 +96,64 @@ public class BasicCsvArrayHeader extends BasicHeader {
 	 * @param name The header name.
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - A comma-delimited string.
-	 * 		<li><c>String[]</c> - A pre-parsed value.
-	 * 		<li>Any other array type - Converted to <c>String[]</c>.
-	 * 		<li>Any {@link Collection} - Converted to <c>String[]</c>.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * 	<br>Must be a comma-delimited list.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public BasicCsvArrayHeader(String name, Object value) {
+	public BasicCsvArrayHeader(String name, String value) {
 		super(name, value);
-		if (! isSupplier(value))
-			parsed = getParsedValue();
+		this.value = parse(value);
+		this.supplier = null;
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param name The header name.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public BasicCsvArrayHeader(String name, List<String> value) {
+		super(name, serialize(value));
+		this.value = value == null ? null : unmodifiableList(value);
+		this.supplier = null;
+	}
+
+	/**
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
+	 *
+	 * @param name The header name.
+	 * @param value
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public BasicCsvArrayHeader(String name, Supplier<List<String>> value) {
+		super(name, null);
+		this.value = null;
+		this.supplier = value;
 	}
 
 	@Override /* Header */
 	public String getValue() {
-		Object o = getRawValue();
-		if (o instanceof String)
-			return (String)o;
-		return joine(getParsedValue(), ',');
+		if (supplier != null)
+			return serialize(supplier.get());
+		return super.getValue();
+	}
+
+	/**
+	 * Returns the contents of this header as a list of strings.
+	 *
+	 * @return The contents of this header as an unmodifiable list of strings, or {@link Optional#empty()} if the value was <jk>null</jk>.
+	 */
+	public Optional<List<String>> asList() {
+		if (value != null)
+			return ofNullable(value);
+		if (supplier != null)
+			return ofNullable(supplier.get());
+		return empty();
 	}
 
 	/**
@@ -125,11 +163,13 @@ public class BasicCsvArrayHeader extends BasicHeader {
 	 * @return <jk>true</jk> if this header contains the specified value.
 	 */
 	public boolean contains(String val) {
-		List<String> vv = getParsedValue();
-		if (val != null && vv != null)
-			for (String v : vv)
-				if (eq(v, val))
+		Optional<List<String>> o = asList();
+		if (val != null && o.isPresent()) {
+			List<String> l = o.get();
+			for (int i = 0, j = l.size(); i < j; i++)
+				if (eq(val, l.get(i)))
 					return true;
+		}
 		return false;
 	}
 
@@ -140,11 +180,13 @@ public class BasicCsvArrayHeader extends BasicHeader {
 	 * @return <jk>true</jk> if this header contains the specified value.
 	 */
 	public boolean containsIgnoreCase(String val) {
-		List<String> vv = getParsedValue();
-		if (val != null && vv != null)
-			for (String v : vv)
-				if (eqic(v, val))
+		Optional<List<String>> o = asList();
+		if (val != null && o.isPresent()) {
+			List<String> l = o.get();
+			for (int i = 0, j = l.size(); i < j; i++)
+				if (eqic(val, l.get(i)))
 					return true;
+		}
 		return false;
 	}
 
@@ -164,38 +206,14 @@ public class BasicCsvArrayHeader extends BasicHeader {
 	 * @throws AssertionError If assertion failed.
 	 */
 	public FluentListAssertion<BasicCsvArrayHeader> assertList() {
-		return new FluentListAssertion<>(getParsedValue(), this);
+		return new FluentListAssertion<>(asList().orElse(null), this);
 	}
 
-	/**
-	 * Returns the contents of this header as a list of strings.
-	 *
-	 * @return The contents of this header as an unmodifiable list of strings, or {@link Optional#empty()} if the value was <jk>null</jk>.
-	 */
-	public Optional<List<String>> asList() {
-		List<String> l = getParsedValue();
-		return ofNullable(l == null ? null : Collections.unmodifiableList(l));
+	private static String serialize(List<String> value) {
+		return join(value, ", ");
 	}
 
-	private List<String> getParsedValue() {
-		if (parsed != null)
-			return parsed;
-
-		Object o = getRawValue();
-		if (o == null)
-			return null;
-
-		AList<String> l = AList.create();
-		if (o instanceof Collection) {
-			for (Object o2 : (Collection<?>)o)
-				l.add(stringify(o2));
-		} else if (o.getClass().isArray()) {
-			for (int i = 0; i < Array.getLength(o); i++)
-				l.add(stringify(Array.get(o, i)));
-		} else {
-			for (String s : split(o.toString()))
-				l.add(s);
-		}
-		return l.unmodifiable();
+	private List<String> parse(String value) {
+		return value == null ? null : unmodifiableList(Arrays.asList(split(value)));
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicDateHeader.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicDateHeader.java
index 9f0e998..bab3c22 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicDateHeader.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicDateHeader.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.header;
 
 import static java.time.format.DateTimeFormatter.*;
 import static java.time.temporal.ChronoUnit.*;
+import static org.apache.juneau.internal.ExceptionUtils.*;
 import static org.apache.juneau.internal.StringUtils.*;
 import static java.util.Optional.*;
 
@@ -46,95 +47,103 @@ public class BasicDateHeader extends BasicHeader {
 	 * @param name The header name.
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - An RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>).
-	 * 		<li>{@link ZonedDateTime}
-	 * 		<li>{@link Calendar}
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new {@link BasicDateHeader} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
+	 * 	<br>Must be an RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>).
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static BasicDateHeader of(String name, Object value) {
+	public static BasicDateHeader of(String name, String value) {
 		if (isEmpty(name) || value == null)
 			return null;
 		return new BasicDateHeader(name, value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
+	 * Convenience creator.
+	 *
+	 * @param name The header name.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
+	 */
+	public static BasicDateHeader of(String name, ZonedDateTime value) {
+		if (isEmpty(name) || value == null)
+			return null;
+		return new BasicDateHeader(name, value);
+	}
+
+	/**
+	 * Convenience creator with delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param name The header name.
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - An RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>).
-	 * 		<li>{@link ZonedDateTime}
-	 * 		<li>{@link Calendar}
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new {@link BasicDateHeader} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static BasicDateHeader of(String name, Supplier<?> value) {
+	public static BasicDateHeader of(String name, Supplier<ZonedDateTime> value) {
 		if (isEmpty(name) || value == null)
 			return null;
 		return new BasicDateHeader(name, value);
 	}
 
-	private ZonedDateTime parsed;
+	private final ZonedDateTime value;
+	private final Supplier<ZonedDateTime> supplier;
 
 	/**
 	 * Constructor.
 	 *
 	 * @param name The header name.
-	 * @param value The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - An RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>).
-	 * 		<li>{@link ZonedDateTime} - Will be truncated to seconds.
-	 * 		<li>{@link Calendar} - Will be truncated to seconds.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be an RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>).
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public BasicDateHeader(String name, Object value) {
+	public BasicDateHeader(String name, String value) {
 		super(name, value);
-		if (! isSupplier(value))
-			parsed = getParsedValue();
-	}
-
-	@Override /* Header */
-	public String getValue() {
-		Object o = getRawValue();
-		if (o == null)
-			return null;
-		if (o instanceof String)
-			return (String)o;
-		return RFC_1123_DATE_TIME.format(getParsedValue());
+		this.value = parse(value);
+		this.supplier = null;
 	}
 
 	/**
-	 * Returns this header value as a {@link java.util.Calendar}.
+	 * Constructor.
 	 *
-	 * @return This header value as a {@link java.util.Calendar}, or {@link Optional#empty()} if the header could not be parsed.
+	 * @param name The header name.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public Optional<Calendar> asCalendar() {
-		ZonedDateTime zdt = getParsedValue();
-		return ofNullable(zdt == null ? null : GregorianCalendar.from(zdt));
+	public BasicDateHeader(String name, ZonedDateTime value) {
+		super(name, serialize(value));
+		this.value = value;
+		this.supplier = null;
 	}
 
 	/**
-	 * Returns this header value as a {@link java.util.Date}.
+	 * Constructor with delayed value.
 	 *
-	 * @return This header value as a {@link java.util.Date}, or {@link Optional#empty()} if the header could not be parsed.
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
+	 *
+	 * @param name The header name.
+	 * @param value
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public Optional<java.util.Date> asDate() {
-		Calendar c = asCalendar().orElse(null);
-		return ofNullable(c == null ? null : c.getTime());
+	public BasicDateHeader(String name, Supplier<ZonedDateTime> value) {
+		super(name, null);
+		this.value = null;
+		this.supplier = value;
+	}
+
+	@Override /* Header */
+	public String getValue() {
+		if (supplier != null)
+			return serialize(supplier.get());
+		return super.getValue();
 	}
 
 	/**
@@ -143,7 +152,9 @@ public class BasicDateHeader extends BasicHeader {
 	 * @return This header value as a {@link ZonedDateTime}, or {@link Optional#empty()} if the header could not be parsed.
 	 */
 	public Optional<ZonedDateTime> asZonedDateTime() {
-		return ofNullable(getParsedValue());
+		if (supplier != null)
+			return ofNullable(supplier.get());
+		return ofNullable(value);
 	}
 
 	/**
@@ -162,19 +173,18 @@ public class BasicDateHeader extends BasicHeader {
 	 * @throws AssertionError If assertion failed.
 	 */
 	public FluentZonedDateTimeAssertion<BasicDateHeader> assertZonedDateTime() {
-		return new FluentZonedDateTimeAssertion<>(getParsedValue(), this);
+		return new FluentZonedDateTimeAssertion<>(asZonedDateTime().orElse(null), this);
 	}
 
-	private ZonedDateTime getParsedValue() {
-		if (parsed != null)
-			return parsed;
-		Object o = getRawValue();
-		if (o == null)
-			return null;
-		if (o instanceof ZonedDateTime)
-			return ((ZonedDateTime)o).truncatedTo(SECONDS);
-		if (o instanceof GregorianCalendar)
-			return ((GregorianCalendar)o).toZonedDateTime().truncatedTo(SECONDS);
-		return ZonedDateTime.from(RFC_1123_DATE_TIME.parse(o.toString())).truncatedTo(SECONDS);
+	private static String serialize(ZonedDateTime value) {
+		return value == null ? null : RFC_1123_DATE_TIME.format(value);
+	}
+
+	private static ZonedDateTime parse(String value) {
+		try {
+			return value == null ? null : ZonedDateTime.from(RFC_1123_DATE_TIME.parse(value.toString())).truncatedTo(SECONDS);
+		} catch (NumberFormatException e) {
+			throw runtimeException("Value ''{0}'' could not be parsed as a zoned date-time.");
+		}
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicEntityTagArrayHeader.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicEntityTagArrayHeader.java
index 786a5f2..4479f1c 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicEntityTagArrayHeader.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicEntityTagArrayHeader.java
@@ -13,16 +13,13 @@
 package org.apache.juneau.http.header;
 
 import static org.apache.juneau.internal.StringUtils.*;
+import static java.util.stream.Collectors.*;
 import static java.util.Optional.*;
 import static java.util.Collections.*;
 
-import java.lang.reflect.*;
 import java.util.*;
 import java.util.function.*;
 
-import org.apache.juneau.collections.*;
-import org.apache.juneau.internal.*;
-
 /**
  * Category of headers that consist of a comma-delimited list of entity validator values.
  *
@@ -48,46 +45,51 @@ public class BasicEntityTagArrayHeader extends BasicHeader {
 	 * @param name The header name.
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - A comma-delimited list of entity validator values (e.g. <js>"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""</js>).
-	 * 		<li>A collection or array of {@link EntityTag} objects.
-	 * 		<li>A collection or array of anything else - Converted to Strings.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new {@link BasicEntityTagArrayHeader} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
+	 * 	<br>Must be a comma-delimited list of entity validator values (e.g. <js>"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""</js>).
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static BasicEntityTagArrayHeader of(String name, Object value) {
+	public static BasicEntityTagArrayHeader of(String name, String value) {
 		if (isEmpty(name) || value == null)
 			return null;
 		return new BasicEntityTagArrayHeader(name, value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
+	 * Convenience creator.
+	 *
+	 * @param name The header name.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
+	 */
+	public static BasicEntityTagArrayHeader of(String name, List<EntityTag> value) {
+		if (isEmpty(name) || value == null)
+			return null;
+		return new BasicEntityTagArrayHeader(name, value);
+	}
+
+	/**
+	 * Convenience creator with delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param name The header name.
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - A comma-delimited list of entity validator values (e.g. <js>"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""</js>).
-	 * 		<li>A collection or array of {@link EntityTag} objects.
-	 * 		<li>A collection or array of anything else - Converted to Strings.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new {@link BasicEntityTagArrayHeader} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static BasicEntityTagArrayHeader of(String name, Supplier<?> value) {
+	public static BasicEntityTagArrayHeader of(String name, Supplier<List<EntityTag>> value) {
 		if (isEmpty(name) || value == null)
 			return null;
 		return new BasicEntityTagArrayHeader(name, value);
 	}
 
-	private List<EntityTag> parsed;
+	private final List<EntityTag> value;
+	private final Supplier<List<EntityTag>> supplier;
 
 	/**
 	 * Constructor.
@@ -95,27 +97,51 @@ public class BasicEntityTagArrayHeader extends BasicHeader {
 	 * @param name The header name.
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - A comma-delimited list of entity validator values (e.g. <js>"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""</js>).
-	 * 		<li>A collection or array of {@link EntityTag} objects.
-	 * 		<li>A collection or array of anything else - Converted to Strings.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * 	<br>Must be a comma-delimited list of entity validator values (e.g. <js>"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""</js>).
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public BasicEntityTagArrayHeader(String name, Object value) {
+	public BasicEntityTagArrayHeader(String name, String value) {
 		super(name, value);
-		if (! isSupplier(value))
-			parsed = getParsedValue();
+		this.value = parse(value);
+		this.supplier = null;
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param name The header name.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public BasicEntityTagArrayHeader(String name, List<EntityTag> value) {
+		super(name, serialize(value));
+		this.value = value == null ? null : unmodifiableList(value);
+		this.supplier = null;
+	}
+
+	/**
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
+	 *
+	 * @param name The header name.
+	 * @param value
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public BasicEntityTagArrayHeader(String name, Supplier<List<EntityTag>> value) {
+		super(name, null);
+		this.value = null;
+		this.supplier = value;
 	}
 
 	@Override /* Header */
 	public String getValue() {
-		Object o = getRawValue();
-		if (o instanceof String)
-			return (String)o;
-		return StringUtils.join(asEntityTags().orElse(emptyList()), ',');
+		if (supplier != null)
+			return serialize(supplier.get());
+		return super.getValue();
 	}
 
 	/**
@@ -124,29 +150,16 @@ public class BasicEntityTagArrayHeader extends BasicHeader {
 	 * @return this header value as an array of {@link EntityTag} objects, or {@link Optional#empty()} if the value was <jk>null</jk>..
 	 */
 	public Optional<List<EntityTag>> asEntityTags() {
-		return ofNullable(getParsedValue());
+		if (supplier != null)
+			return ofNullable(supplier.get());
+		return ofNullable(value);
 	}
 
-	private List<EntityTag> getParsedValue() {
-		if (parsed != null)
-			return parsed;
-		Object o = getRawValue();
-		if (o == null)
-			return null;
-		if (o instanceof EntityTag[])
-			return AList.of((EntityTag[])o).unmodifiable();
+	private static String serialize(List<EntityTag> value) {
+		return join(value, ", ");
+	}
 
-		AList<EntityTag> l = AList.create();
-		if (o instanceof Collection) {
-			for (Object o2 : (Collection<?>)o)
-				l.add(EntityTag.of(o2));
-		} else if (o.getClass().isArray()) {
-			for (int i = 0; i < Array.getLength(o); i++)
-				l.add(EntityTag.of(Array.get(o, i)));
-		} else {
-			for (String s : split(o.toString()))
-				l.add(EntityTag.of(s));
-		}
-		return l.unmodifiable();
+	private List<EntityTag> parse(String value) {
+		return value == null ? null : Arrays.asList(split(value, ',')).stream().map(x -> EntityTag.of(x)).collect(toList());
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicEntityTagHeader.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicEntityTagHeader.java
index c7bf40f..c41034c 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicEntityTagHeader.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicEntityTagHeader.java
@@ -43,44 +43,51 @@ public class BasicEntityTagHeader extends BasicHeader {
 	 * @param name The header name.
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - A comma-delimited list of entity validator values (e.g. <js>"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""</js>).
-	 * 		<li>A collection or array of {@link EntityTag} objects.
-	 * 		<li>A collection or array of anything else - Converted to Strings.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new {@link BasicEntityTagHeader} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
+	 * 	<br>Must be an entity tag value (e.g. <js>"\"xyzzy\""</js>).
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static BasicEntityTagHeader of(String name, Object value) {
+	public static BasicEntityTagHeader of(String name, String value) {
 		if (isEmpty(name) || value == null)
 			return null;
 		return new BasicEntityTagHeader(name, value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
+	 * Convenience creator.
+	 *
+	 * @param name The header name.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
+	 */
+	public static BasicEntityTagHeader of(String name, EntityTag value) {
+		if (isEmpty(name) || value == null)
+			return null;
+		return new BasicEntityTagHeader(name, value);
+	}
+
+	/**
+	 * Convenience creator with delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param name The header name.
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - A raw entity validator values (e.g. <js>"\"xyzzy\""</js>).
-	 * 		<li>An {@link EntityTag} object.
-	 * 	</ul>
-	 * @return A new {@link BasicEntityTagHeader} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static BasicEntityTagHeader of(String name, Supplier<?> value) {
+	public static BasicEntityTagHeader of(String name, Supplier<EntityTag> value) {
 		if (isEmpty(name) || value == null)
 			return null;
 		return new BasicEntityTagHeader(name, value);
 	}
 
-	private EntityTag parsed;
+	private final EntityTag value;
+	private final Supplier<EntityTag> supplier;
 
 	/**
 	 * Constructor.
@@ -88,24 +95,51 @@ public class BasicEntityTagHeader extends BasicHeader {
 	 * @param name The header name.
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - A raw entity validator values (e.g. <js>"\"xyzzy\""</js>).
-	 * 		<li>An {@link EntityTag} object.
-	 * 	</ul>
+	 * 	<br>Must be an entity tag value (e.g. <js>"\"xyzzy\""</js>).
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public BasicEntityTagHeader(String name, Object value) {
+	public BasicEntityTagHeader(String name, String value) {
 		super(name, value);
-		if (! isSupplier(value))
-			parsed = getParsedValue();
+		this.value = parse(value);
+		this.supplier = null;
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param name The header name.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public BasicEntityTagHeader(String name, EntityTag value) {
+		super(name, serialize(value));
+		this.value = value;
+		this.supplier = null;
+	}
+
+	/**
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
+	 *
+	 * @param name The header name.
+	 * @param value
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public BasicEntityTagHeader(String name, Supplier<EntityTag> value) {
+		super(name, null);
+		this.value = null;
+		this.supplier = value;
 	}
 
 	@Override /* Header */
 	public String getValue() {
-		Object o = getRawValue();
-		if (o instanceof String)
-			return (String)o;
-		return stringify(getParsedValue());
+		if (supplier != null)
+			return serialize(supplier.get());
+		return super.getValue();
 	}
 
 	/**
@@ -114,12 +148,16 @@ public class BasicEntityTagHeader extends BasicHeader {
 	 * @return This header as an {@link EntityTag}, or {@link Optional#empty()} if the value is <jk>null</jk>.
 	 */
 	public Optional<EntityTag> asEntityTag() {
-		return ofNullable(getParsedValue());
+		if (supplier != null)
+			return ofNullable(supplier.get());
+		return ofNullable(value);
+	}
+
+	private static String serialize(EntityTag value) {
+		return stringify(value);
 	}
 
-	private EntityTag getParsedValue() {
-		if (parsed != null)
-			return parsed;
-		return EntityTag.of(getRawValue());
+	private EntityTag parse(String value) {
+		return EntityTag.of(value);
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicHeader.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicHeader.java
index 8f2bd40..3834230 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicHeader.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicHeader.java
@@ -13,20 +13,17 @@
 package org.apache.juneau.http.header;
 
 import static org.apache.juneau.internal.StringUtils.*;
+import static org.apache.juneau.internal.StringUtils.isEmpty;
 import static org.apache.juneau.internal.ObjectUtils.*;
-
 import java.io.*;
 import java.util.*;
 import java.util.function.*;
 
 import org.apache.http.*;
 import org.apache.http.message.*;
-import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.assertions.*;
-import org.apache.juneau.http.part.*;
 import org.apache.juneau.internal.*;
-import org.apache.juneau.reflect.*;
 
 /**
  * Superclass of all headers defined in this package.
@@ -52,38 +49,19 @@ public class BasicHeader implements Header, Cloneable, Serializable {
 
 	private static final HeaderElement[] EMPTY_HEADER_ELEMENTS = new HeaderElement[] {};
 
-	private final String name;
-	private final Object value;
-	private HeaderElement[] elements;
-
 	/**
 	 * Convenience creator.
 	 *
 	 * @param name The parameter name.
 	 * @param value
 	 * 	The parameter value.
-	 * 	<br>Any non-String value will be converted to a String using {@link Object#toString()}.
-	 * @return A new {@link BasicHeader} object.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
 	public static BasicHeader of(String name, Object value) {
-		return new BasicHeader(name, value);
-	}
-
-	/**
-	 * Creates a {@link Header} from a name/value pair string (e.g. <js>"Foo: bar"</js>)
-	 *
-	 * @param pair The pair string.
-	 * @return A new {@link Header} object.
-	 */
-	public static BasicHeader ofPair(String pair) {
-		if (pair == null)
+		if (isEmpty(name) || value == null)
 			return null;
-		int i = pair.indexOf(':');
-		if (i == -1)
-			i = pair.indexOf('=');
-		if (i == -1)
-			return of(pair, "");
-		return of(pair.substring(0,i).trim(), pair.substring(i+1).trim());
+		return new BasicHeader(name, value);
 	}
 
 	/**
@@ -92,62 +70,19 @@ public class BasicHeader implements Header, Cloneable, Serializable {
 	 * @param o The name value pair that makes up the header name and value.
 	 * 	The parameter value.
 	 * 	<br>Any non-String value will be converted to a String using {@link Object#toString()}.
-	 * @return A new {@link BasicHeader} object.
+	 * @return A new header bean.
 	 */
-	public static Header of(NameValuePair o) {
+	public static BasicHeader of(NameValuePair o) {
 		return new BasicHeader(o.getName(), o.getValue());
 	}
 
-	/**
-	 * Convenience creator using supplier.
-	 *
-	 * <p>
-	 * Header value is re-evaluated on each call to {@link #getValue()}.
-	 *
-	 * @param name The parameter name.
-	 * @param value
-	 * 	The parameter value supplier.
-	 * 	<br>Any non-String value will be converted to a String using {@link Object#toString()}.
-	 * @return A new {@link BasicHeader} object.
-	 */
-	public static BasicHeader of(String name, Supplier<?> value) {
-		return new BasicHeader(name, value);
-	}
+	private final String name;
+	private final String stringValue;
 
-	/**
-	 * Utility method for converting an arbitrary object to a {@link Header}.
-	 *
-	 * @param o
-	 * 	The object to cast or convert to a {@link Header}.
-	 * @return Either the same object cast as a {@link Header} or converted to a {@link Header}.
-	 */
-	@SuppressWarnings("rawtypes")
-	public static Header cast(Object o) {
-		if (o instanceof Header)
-			return (Header)o;
-		if (o instanceof Headerable)
-			return ((Headerable)o).asHeader();
-		if (o instanceof NameValuePair)
-			return BasicHeader.of((NameValuePair)o);
-		if (o instanceof Partable)
-			return BasicHeader.of(((Partable)o).asPart());
-		if (o instanceof Map.Entry) {
-			Map.Entry e = (Map.Entry)o;
-			return BasicHeader.of(stringify(e.getKey()), e.getValue());
-		}
-		throw new BasicRuntimeException("Object of type {0} could not be converted to a Header.", o == null ? null : o.getClass().getName());
-	}
+	private final Object value;
+	private final Supplier<Object> supplier;
 
-	/**
-	 * Returns <jk>true</jk> if the {@link #cast(Object)} method can be used on the specified object.
-	 *
-	 * @param o The object to check.
-	 * @return <jk>true</jk> if the {@link #cast(Object)} method can be used on the specified object.
-	 */
-	public static boolean canCast(Object o) {
-		ClassInfo ci = ClassInfo.of(o);
-		return ci != null && ci.isChildOfAny(Header.class, Headerable.class, NameValuePair.class, Partable.class, Map.Entry.class);
-	}
+	private HeaderElement[] elements;
 
 	/**
 	 * Constructor.
@@ -160,7 +95,27 @@ public class BasicHeader implements Header, Cloneable, Serializable {
 	 */
 	public BasicHeader(String name, Object value) {
 		this.name = name;
-		this.value = value;
+		this.value = value instanceof Supplier ? null : value;
+		this.stringValue = stringify(value);
+		this.supplier = cast(Supplier.class, value);
+	}
+
+	/**
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
+	 *
+	 * @param name The header name.
+	 * @param value
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public BasicHeader(String name, Supplier<Object> value) {
+		this.name = name;
+		this.value = null;
+		this.stringValue = null;
+		this.supplier = value;
 	}
 
 	/**
@@ -171,6 +126,8 @@ public class BasicHeader implements Header, Cloneable, Serializable {
 	protected BasicHeader(BasicHeader copyFrom) {
 		this.name = copyFrom.name;
 		this.value = copyFrom.value;
+		this.stringValue = copyFrom.stringValue;
+		this.supplier = copyFrom.supplier;
 	}
 
 	@Override /* Header */
@@ -180,16 +137,9 @@ public class BasicHeader implements Header, Cloneable, Serializable {
 
 	@Override /* Header */
 	public String getValue() {
-		return stringify(getRawValue());
-	}
-
-	/**
-	 * Returns the raw value of the header.
-	 *
-	 * @return The raw value of the header.
-	 */
-	public Object getRawValue() {
-		return unwrap(value);
+		if (supplier != null)
+			return stringify(supplier.get());
+		return stringValue;
 	}
 
 	@Override
@@ -197,9 +147,9 @@ public class BasicHeader implements Header, Cloneable, Serializable {
 		if (elements == null) {
 			String s = getValue();
 			HeaderElement[] x = s == null ? EMPTY_HEADER_ELEMENTS : BasicHeaderValueParser.parseElements(s, null);
-			if (value instanceof Supplier)
-				return x;
-			elements = x;
+			if (supplier == null)
+				elements = x;
+			return x;
 		}
 		return elements;
 	}
@@ -290,26 +240,6 @@ public class BasicHeader implements Header, Cloneable, Serializable {
 		return asString().orElse(other);
 	}
 
-	/**
-	 * Returns <jk>true</jk> if the specified object is a {@link Supplier}.
-	 *
-	 * @param o The object to check.
-	 * @return <jk>true</jk> if the specified object is a {@link Supplier}.
-	 */
-	protected boolean isSupplier(Object o) {
-		return o instanceof Supplier;
-	}
-
-	/**
-	 * If the specified object is a {@link Supplier}, returns the supplied value, otherwise the same value.
-	 *
-	 * @param o The object to unwrap.
-	 * @return The unwrapped object.
-	 */
-	protected static Object unwrap(Object o) {
-		return ObjectUtils.unwrap(o);
-	}
-
 	@Override /* Object */
 	public boolean equals(Object o) {
 		// Functionality provided for HttpRequest.removeHeader().
@@ -327,7 +257,7 @@ public class BasicHeader implements Header, Cloneable, Serializable {
 
 	@Override /* Object */
 	public String toString() {
-		return name + ": " + getValue();
+		return getName() + ": " + getValue();
 	}
 
 	// <FluentSetters>
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicIntegerHeader.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicIntegerHeader.java
index d67adca..d063850 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicIntegerHeader.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicIntegerHeader.java
@@ -13,12 +13,12 @@
 package org.apache.juneau.http.header;
 
 import static org.apache.juneau.internal.StringUtils.*;
+import static org.apache.juneau.internal.ExceptionUtils.*;
 import static java.util.Optional.*;
 
 import java.util.*;
 import java.util.function.*;
 
-import org.apache.juneau.*;
 import org.apache.juneau.assertions.*;
 import org.apache.juneau.http.annotation.*;
 
@@ -46,44 +46,51 @@ public class BasicIntegerHeader extends BasicHeader {
 	 * @param name The header name.
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link Number} - Converted to an integer using {@link Number#intValue()}.
-	 * 		<li>{@link String} - Parsed using {@link Integer#parseInt(String)}.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new {@link BasicIntegerHeader} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
+	 * 	<br>Must be parsable using {@link Integer#parseInt(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static BasicIntegerHeader of(String name, Object value) {
+	public static BasicIntegerHeader of(String name, String value) {
 		if (isEmpty(name) || value == null)
 			return null;
 		return new BasicIntegerHeader(name, value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
+	 * Convenience creator.
+	 *
+	 * @param name The header name.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
+	 */
+	public static BasicIntegerHeader of(String name, Integer value) {
+		if (isEmpty(name) || value == null)
+			return null;
+		return new BasicIntegerHeader(name, value);
+	}
+
+	/**
+	 * Convenience creator with delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param name The header name.
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link Number} - Converted to an integer using {@link Number#intValue()}.
-	 * 		<li>{@link String} - Parsed using {@link Integer#parseInt(String)}.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new {@link BasicIntegerHeader} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static BasicIntegerHeader of(String name, Supplier<?> value) {
+	public static BasicIntegerHeader of(String name, Supplier<Integer> value) {
 		if (isEmpty(name) || value == null)
 			return null;
 		return new BasicIntegerHeader(name, value);
 	}
 
-	private Integer parsed;
+	private final Integer value;
+	private final Supplier<Integer> supplier;
 
 	/**
 	 * Constructor.
@@ -91,23 +98,51 @@ public class BasicIntegerHeader extends BasicHeader {
 	 * @param name The header name.
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link Number} - Converted to an integer using {@link Number#intValue()}.
-	 * 		<li>{@link String} - Parsed using {@link Integer#parseInt(String)}.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * 	<br>Must be parsable using {@link Integer#parseInt(String)}.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public BasicIntegerHeader(String name, Object value) {
+	public BasicIntegerHeader(String name, String value) {
 		super(name, value);
-		if (! isSupplier(value))
-			parsed = getParsedValue();
+		this.value = parse(value);
+		this.supplier = null;
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param name The header name.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public BasicIntegerHeader(String name, Integer value) {
+		super(name, serialize(value));
+		this.value = value;
+		this.supplier = null;
+	}
+
+	/**
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
+	 *
+	 * @param name The header name.
+	 * @param value
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public BasicIntegerHeader(String name, Supplier<Integer> value) {
+		super(name, null);
+		this.value = null;
+		this.supplier = value;
 	}
 
 	@Override /* Header */
 	public String getValue() {
-		return stringify(getParsedValue());
+		if (supplier != null)
+			return serialize(supplier.get());
+		return super.getValue();
 	}
 
 	/**
@@ -116,7 +151,9 @@ public class BasicIntegerHeader extends BasicHeader {
 	 * @return The header value as an integer, or {@link Optional#empty()} if the value is <jk>null</jk>.
 	 */
 	public Optional<Integer> asInteger() {
-		return ofNullable(getParsedValue());
+		if (supplier != null)
+			return ofNullable(supplier.get());
+		return ofNullable(value);
 	}
 
 	/**
@@ -135,29 +172,18 @@ public class BasicIntegerHeader extends BasicHeader {
 	 * @throws AssertionError If assertion failed.
 	 */
 	public FluentIntegerAssertion<BasicIntegerHeader> assertInteger() {
-		return new FluentIntegerAssertion<>(getParsedValue(), this);
+		return new FluentIntegerAssertion<>(asInteger().orElse(null), this);
 	}
 
-	private Integer getParsedValue() {
-		if (parsed != null)
-			return parsed;
-		Object o = getRawValue();
-		if (o == null)
-			return null;
-		if (o instanceof Integer)
-			return (Integer)o;
-		if (o instanceof Number)
-			return ((Number)o).intValue();
-		String s = o.toString();
+	private static String serialize(Integer value) {
+		return stringify(value);
+	}
+
+	private Integer parse(String value) {
 		try {
-			return Integer.parseInt(s);
+			return value == null ? null : Integer.parseInt(value);
 		} catch (NumberFormatException e) {
-			try {
-				Long.parseLong(s);
-				return Integer.MAX_VALUE;
-			} catch (NumberFormatException e2) {
-				throw new BasicIllegalArgumentException("Value could not be parsed as an int: {0}", o);
-			}
+			throw runtimeException("Value ''{0}'' could not be parsed as an integer.", value);
 		}
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicLongHeader.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicLongHeader.java
index 174c995..9f7c0da 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicLongHeader.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicLongHeader.java
@@ -12,13 +12,13 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.http.header;
 
+import static org.apache.juneau.internal.ExceptionUtils.*;
 import static org.apache.juneau.internal.StringUtils.*;
 import static java.util.Optional.*;
 
 import java.util.*;
 import java.util.function.*;
 
-import org.apache.juneau.*;
 import org.apache.juneau.assertions.*;
 import org.apache.juneau.http.annotation.*;
 
@@ -46,44 +46,52 @@ public class BasicLongHeader extends BasicHeader {
 	 * @param name The header name.
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link Number} - Converted to a long using {@link Number#longValue()}.
-	 * 		<li>{@link String} - Parsed using {@link Long#parseLong(String)}.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new {@link BasicLongHeader} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
+	 * 	<br>Must be parsable by {@link Long#parseLong(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static BasicLongHeader of(String name, Object value) {
+	public static BasicLongHeader of(String name, String value) {
 		if (isEmpty(name) || value == null)
 			return null;
 		return new BasicLongHeader(name, value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
+	 * Convenience creator.
+	 *
+	 * @param name The header name.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be parsable by {@link Long#parseLong(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
+	 */
+	public static BasicLongHeader of(String name, Long value) {
+		if (isEmpty(name) || value == null)
+			return null;
+		return new BasicLongHeader(name, value);
+	}
+
+	/**
+	 * Convenience creator with delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param name The header name.
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link Number} - Converted to a long using {@link Number#longValue()}.
-	 * 		<li>{@link String} - Parsed using {@link Long#parseLong(String)}.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new {@link BasicLongHeader} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static BasicLongHeader of(String name, Supplier<?> value) {
+	public static BasicLongHeader of(String name, Supplier<Long> value) {
 		if (isEmpty(name) || value == null)
 			return null;
 		return new BasicLongHeader(name, value);
 	}
 
-	private Long parsed;
+	private final Long value;
+	private final Supplier<Long> supplier;
 
 	/**
 	 * Constructor.
@@ -91,23 +99,51 @@ public class BasicLongHeader extends BasicHeader {
 	 * @param name The header name.
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link Number} - Converted to a long using {@link Number#longValue()}.
-	 * 		<li>{@link String} - Parsed using {@link Long#parseLong(String)}.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * 	<br>Must be parsable by {@link Long#parseLong(String)}.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public BasicLongHeader(String name, Object value) {
+	public BasicLongHeader(String name, String value) {
 		super(name, value);
-		if (! isSupplier(value))
-			parsed = getParsedValue();
+		this.value = parse(value);
+		this.supplier = null;
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param name The header name.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public BasicLongHeader(String name, Long value) {
+		super(name, serialize(value));
+		this.value = value;
+		this.supplier = null;
+	}
+
+	/**
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
+	 *
+	 * @param name The header name.
+	 * @param value
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public BasicLongHeader(String name, Supplier<Long> value) {
+		super(name, null);
+		this.value = null;
+		this.supplier = value;
 	}
 
 	@Override /* Header */
 	public String getValue() {
-		return stringify(getParsedValue());
+		if (supplier != null)
+			return serialize(supplier.get());
+		return super.getValue();
 	}
 
 	/**
@@ -116,7 +152,9 @@ public class BasicLongHeader extends BasicHeader {
 	 * @return The header value as a long, or {@link Optional#empty()} if the value is <jk>null</jk>
 	 */
 	public Optional<Long> asLong() {
-		return ofNullable(getParsedValue());
+		if (supplier != null)
+			return ofNullable(supplier.get());
+		return ofNullable(value);
 	}
 
 	/**
@@ -135,22 +173,18 @@ public class BasicLongHeader extends BasicHeader {
 	 * @throws AssertionError If assertion failed.
 	 */
 	public FluentLongAssertion<BasicLongHeader> assertLong() {
-		return new FluentLongAssertion<>(getParsedValue(), this);
+		return new FluentLongAssertion<>(asLong().orElse(null), this);
 	}
 
-	private Long getParsedValue() {
-		if (parsed != null)
-			return parsed;
-		Object o = getRawValue();
-		if (o == null)
-			return null;
-		if (o instanceof Number)
-			return ((Number)o).longValue();
-		String s = o.toString();
+	private static String serialize(Long value) {
+		return stringify(value);
+	}
+
+	private Long parse(String value) {
 		try {
-			return Long.parseLong(s);
+			return value == null ? null : Long.parseLong(value);
 		} catch (NumberFormatException e) {
-			throw new BasicIllegalArgumentException("Value could not be parsed as a long: {0}", o);
+			throw runtimeException("Value ''{0}'' could not be parsed as a long.", value);
 		}
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicMediaRangeArrayHeader.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicMediaRangeArrayHeader.java
index 63c9963..d9b41c4 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicMediaRangeArrayHeader.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicMediaRangeArrayHeader.java
@@ -41,59 +41,78 @@ public class BasicMediaRangeArrayHeader extends BasicStringHeader {
 	 * @param name The header name.
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link BasicMediaRangeArrayHeader} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
+	 * 	<br>Must be parsable by {@link MediaRanges#of(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static BasicMediaRangeArrayHeader of(String name, Object value) {
+	public static BasicMediaRangeArrayHeader of(String name, String value) {
 		if (isEmpty(name) || value == null)
 			return null;
 		return new BasicMediaRangeArrayHeader(name, value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
-	 *
-	 * <p>
-	 * Header value is re-evaluated on each call to {@link #getValue()}.
+	 * Convenience creator.
 	 *
 	 * @param name The header name.
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link BasicMediaRangeArrayHeader} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static BasicMediaRangeArrayHeader of(String name, Supplier<?> value) {
+	public static BasicMediaRangeArrayHeader of(String name, MediaRanges value) {
 		if (isEmpty(name) || value == null)
 			return null;
 		return new BasicMediaRangeArrayHeader(name, value);
 	}
 
-	private MediaRanges parsed;
+	private final MediaRanges value;
+	private final Supplier<MediaRanges> supplier;
 
 	/**
-	 * Constructor
+	 * Constructor.
 	 *
 	 * @param name The header name.
 	 * @param value
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * 	The header value.
+	 * 	<br>Must be parsable by {@link MediaRanges#of(String)}.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public BasicMediaRangeArrayHeader(String name, Object value) {
+	public BasicMediaRangeArrayHeader(String name, String value) {
 		super(name, value);
-		if (! isSupplier(value))
-			parsed = parse();
+		this.value = parse(value);
+		this.supplier = null;
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param name The header name.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public BasicMediaRangeArrayHeader(String name, MediaRanges value) {
+		super(name, serialize(value));
+		this.value = value;
+		this.supplier = null;
+	}
+
+	/**
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
+	 *
+	 * @param name The header name.
+	 * @param value
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public BasicMediaRangeArrayHeader(String name, Supplier<MediaRanges> value) {
+		super(name, (String)null);
+		this.value = null;
+		this.supplier = value;
 	}
 
 	/**
@@ -102,7 +121,9 @@ public class BasicMediaRangeArrayHeader extends BasicStringHeader {
 	 * @return This header as a {@link MediaRanges} object, or {@link Optional#empty()} if the value is <jk>null</jk>
 	 */
 	public Optional<MediaRanges> asMediaRanges() {
-		return ofNullable(parse());
+		if (supplier != null)
+			return ofNullable(supplier.get());
+		return ofNullable(value);
 	}
 
 	/**
@@ -163,20 +184,16 @@ public class BasicMediaRangeArrayHeader extends BasicStringHeader {
 
 	@Override /* Header */
 	public String getValue() {
-		Object o = getRawValue();
-		if (o == null)
-			return null;
-		return stringify(asMediaRanges().orElse(MediaRanges.EMPTY));
+		if (supplier != null)
+			return serialize(supplier.get());
+		return super.getValue();
 	}
 
-	private MediaRanges parse() {
-		if (parsed != null)
-			return parsed;
-		Object o = getRawValue();
-		if (o == null)
-			return null;
-		if (o instanceof MediaRanges)
-			return (MediaRanges)o;
-		return MediaRanges.of(o.toString());
+	private static String serialize(MediaRanges value) {
+		return stringify(value);
+	}
+
+	private MediaRanges parse(String value) {
+		return value == null ? null : MediaRanges.of(value);
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicMediaTypeHeader.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicMediaTypeHeader.java
index 82eced3..77f467c 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicMediaTypeHeader.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicMediaTypeHeader.java
@@ -44,59 +44,107 @@ public class BasicMediaTypeHeader extends BasicStringHeader {
 	 * @param name The header name.
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link BasicMediaTypeHeader} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
+	 * 	<br>Must be parsable by {@link MediaType#of(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static BasicMediaTypeHeader of(String name, Object value) {
+	public static BasicMediaTypeHeader of(String name, String value) {
 		if (isEmpty(name) || value == null)
 			return null;
 		return new BasicMediaTypeHeader(name, value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
-	 *
-	 * <p>
-	 * Header value is re-evaluated on each call to {@link #getValue()}.
+	 * Convenience creator.
 	 *
 	 * @param name The header name.
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link BasicMediaTypeHeader} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static BasicMediaTypeHeader of(String name, Supplier<?> value) {
+	public static BasicMediaTypeHeader of(String name, MediaType value) {
 		if (isEmpty(name) || value == null)
 			return null;
 		return new BasicMediaTypeHeader(name, value);
 	}
 
-	private MediaType parsed;
+//	/**
+//	 * Convenience creator using supplier.
+//	 *
+//	 * <p>
+//	 * Header value is re-evaluated on each call to {@link #getValue()}.
+//	 *
+//	 * @param name The header name.
+//	 * @param value
+//	 * 	The header value supplier.
+//	 * 	<br>Can be any of the following:
+//	 * 	<ul>
+//	 * 		<li>{@link String}
+//	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
+//	 * 	</ul>
+//	 * @return A new header bean, or <jk>null</jk> if the name or value is <jk>null</jk>.
+//	 */
+//	public static BasicMediaTypeHeader of(String name, Supplier<MediaType> value) {
+//		if (isEmpty(name) || value == null)
+//			return null;
+//		return new BasicMediaTypeHeader(name, value);
+//	}
+
+	private final MediaType value;
+	private final Supplier<MediaType> supplier;
 
 	/**
-	 * Constructor
+	 * Constructor.
 	 *
 	 * @param name The header name.
 	 * @param value
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * 	The header value.
+	 * 	<br>Must be parsable by {@link MediaType#of(String)}.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public BasicMediaTypeHeader(String name, Object value) {
+	public BasicMediaTypeHeader(String name, String value) {
 		super(name, value);
-		if (! isSupplier(value))
-			parsed = parse();
+		this.value = parse(value);
+		this.supplier = null;
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param name The header name.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public BasicMediaTypeHeader(String name, MediaType value) {
+		super(name, serialize(value));
+		this.value = value;
+		this.supplier = null;
+	}
+
+	/**
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
+	 *
+	 * @param name The header name.
+	 * @param value
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public BasicMediaTypeHeader(String name, Supplier<MediaType> value) {
+		super(name, (String)null);
+		this.value = null;
+		this.supplier = value;
+	}
+
+	@Override /* Header */
+	public String getValue() {
+		if (supplier != null)
+			return serialize(supplier.get());
+		return super.getValue();
 	}
 
 	/**
@@ -105,7 +153,9 @@ public class BasicMediaTypeHeader extends BasicStringHeader {
 	 * @return This header as a {@link MediaType} object, or {@link Optional#empty()} if the value is <jk>null</jk>
 	 */
 	public Optional<MediaType> asMediaType() {
-		return ofNullable(parse());
+		if (supplier != null)
+			return ofNullable(supplier.get());
+		return ofNullable(value);
 	}
 
 	/**
@@ -262,22 +312,11 @@ public class BasicMediaTypeHeader extends BasicStringHeader {
 		return asMediaType().orElse(MediaType.EMPTY).getParameter(name);
 	}
 
-	@Override /* Header */
-	public String getValue() {
-		Object o = getRawValue();
-		if (o == null)
-			return null;
-		return stringify(parse());
+	private static String serialize(MediaType value) {
+		return stringify(value);
 	}
 
-	private MediaType parse() {
-		if (parsed != null)
-			return parsed;
-		Object o = getRawValue();
-		if (o == null)
-			return null;
-		if (o instanceof MediaType)
-			return (MediaType)o;
-		return new MediaType(o.toString());
+	private MediaType parse(String value) {
+		return MediaType.of(value);
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicStringHeader.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicStringHeader.java
index bccc3cb..1c171bc 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicStringHeader.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicStringHeader.java
@@ -13,10 +13,12 @@
 package org.apache.juneau.http.header;
 
 import static org.apache.juneau.internal.StringUtils.*;
+import static java.util.Optional.*;
 
 import java.util.*;
 import java.util.function.*;
 
+import org.apache.http.*;
 import org.apache.juneau.assertions.*;
 
 /**
@@ -42,59 +44,91 @@ public class BasicStringHeader extends BasicHeader {
 	 * @param name The header name.
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()}.
-	 * 	</ul>
-	 * @return A new {@link BasicStringHeader} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static BasicStringHeader of(String name, Object value) {
+	public static BasicStringHeader of(String name, String value) {
 		if (isEmpty(name) || value == null)
 			return null;
 		return new BasicStringHeader(name, value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
+	 * Convenience creator with delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param name The header name.
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()}.
-	 * 	</ul>
-	 * @return A new {@link BasicStringHeader} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static BasicStringHeader of(String name, Supplier<?> value) {
+	public static BasicStringHeader of(String name, Supplier<String> value) {
 		if (isEmpty(name) || value == null)
 			return null;
 		return new BasicStringHeader(name, value);
 	}
 
-	private String parsed;
+	/**
+	 * Creates a {@link Header} from a name/value pair string (e.g. <js>"Foo: bar"</js>)
+	 *
+	 * @param pair The pair string.
+	 * @return A new header bean.
+	 */
+	public static BasicStringHeader ofPair(String pair) {
+		if (pair == null)
+			return null;
+		int i = pair.indexOf(':');
+		if (i == -1)
+			i = pair.indexOf('=');
+		if (i == -1)
+			return of(pair, "");
+		return of(pair.substring(0,i).trim(), pair.substring(i+1).trim());
+	}
+
+	private final Supplier<String> supplier;
 
 	/**
-	 * Constructor
+	 * Constructor.
 	 *
 	 * @param name The header name.
 	 * @param value
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public BasicStringHeader(String name, Object value) {
+	public BasicStringHeader(String name, String value) {
 		super(name, value);
-		if (! isSupplier(value))
-			parsed = getParsedValue();
+		this.supplier = null;
+	}
+
+	/**
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
+	 *
+	 * @param name The header name.
+	 * @param value
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public BasicStringHeader(String name, Supplier<String> value) {
+		super(name, null);
+		this.supplier = value;
+	}
+
+	@Override /* Header */
+	public String getValue() {
+		if (supplier != null)
+			return supplier.get();
+		return super.getValue();
+	}
+
+	@Override /* BasicHeader */
+	public Optional<String> asString() {
+		return ofNullable(getValue());
 	}
 
 	/**
@@ -115,20 +149,4 @@ public class BasicStringHeader extends BasicHeader {
 	public FluentStringAssertion<BasicStringHeader> assertString() {
 		return new FluentStringAssertion<>(getValue(), this);
 	}
-
-	@Override /* Header */
-	public String getValue() {
-		return getParsedValue();
-	}
-
-	@Override /* BasicHeader */
-	public Optional<String> asString() {
-		return Optional.ofNullable(getParsedValue());
-	}
-
-	private String getParsedValue() {
-		if (parsed != null)
-			return parsed;
-		return stringify(getRawValue());
-	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicStringRangeArrayHeader.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicStringRangeArrayHeader.java
index 99532cc..133715e 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicStringRangeArrayHeader.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicStringRangeArrayHeader.java
@@ -38,71 +38,106 @@ public class BasicStringRangeArrayHeader extends BasicHeader {
 	/**
 	 * Convenience creator.
 	 *
+	 * @param name The header name.
 	 * @param value
-	 * 	The parameter value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String} - Converted using {@link StringRanges#of(String)}.
-	 * 		<li>{@link StringRanges} - Left as-is.
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link BasicLongHeader} object.
+	 * 	The header value.
+	 * 	<br>Must be parsable by {@link StringRanges#of(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static BasicStringRangeArrayHeader of(String name, Object value) {
+	public static BasicStringRangeArrayHeader of(String name, String value) {
 		if (isEmpty(name) || value == null)
 			return null;
 		return new BasicStringRangeArrayHeader(name, value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
+	 * Convenience creator.
+	 *
+	 * @param name The header name.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
+	 */
+	public static BasicStringRangeArrayHeader of(String name, StringRanges value) {
+		if (isEmpty(name) || value == null)
+			return null;
+		return new BasicStringRangeArrayHeader(name, value);
+	}
+
+	/**
+	 * Convenience creator with delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
+	 * @param name The header name.
 	 * @param value
-	 * 	The parameter value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String} - Converted using {@link StringRanges#of(String)}.
-	 * 		<li>{@link StringRanges} - Left as-is.
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link BasicLongHeader} object.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static BasicStringRangeArrayHeader of(String name, Supplier<?> value) {
+	public static BasicStringRangeArrayHeader of(String name, Supplier<StringRanges> value) {
 		if (isEmpty(name) || value == null)
 			return null;
 		return new BasicStringRangeArrayHeader(name, value);
 	}
 
-	private StringRanges parsed;
+	private final StringRanges value;
+	private final Supplier<StringRanges> supplier;
 
 	/**
 	 * Constructor.
 	 *
-	 * @param name The parameter name.
+	 * @param name The header name.
 	 * @param value
-	 * 	The parameter value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String} - Converted using {@link StringRanges#of(String)}.
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * 	The header value.
+	 * 	<br>Must be parsable by {@link StringRanges#of(String)}.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public BasicStringRangeArrayHeader(String name, Object value) {
+	public BasicStringRangeArrayHeader(String name, String value) {
 		super(name, value);
-		if (! isSupplier(value))
-			parsed = parse();
+		this.value = parse(value);
+		this.supplier = null;
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param name The header name.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public BasicStringRangeArrayHeader(String name, StringRanges value) {
+		super(name, serialize(value));
+		this.value = value;
+		this.supplier = null;
+	}
+
+	/**
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
+	 *
+	 * @param name The header name.
+	 * @param value
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public BasicStringRangeArrayHeader(String name, Supplier<StringRanges> value) {
+		super(name, null);
+		this.value = null;
+		this.supplier = value;
 	}
 
 	@Override /* Header */
 	public String getValue() {
-		Object o = getRawValue();
-		if (o == null)
-			return null;
-		return stringify(asRanges().orElse(StringRanges.EMPTY));
+		if (supplier != null)
+			return serialize(supplier.get());
+		return super.getValue();
 	}
 
 	/**
@@ -114,7 +149,9 @@ public class BasicStringRangeArrayHeader extends BasicHeader {
 	 * @return An unmodifiable list of type ranges, or {@link Optional#empty()} if the value is <jk>null</jk>
 	 */
 	public Optional<StringRanges> asRanges() {
-		return ofNullable(parse());
+		if (supplier != null)
+			return ofNullable(supplier.get());
+		return ofNullable(value);
 	}
 
 	/**
@@ -158,12 +195,11 @@ public class BasicStringRangeArrayHeader extends BasicHeader {
 		return asRanges().orElse(StringRanges.EMPTY).getRanges();
 	}
 
-	private StringRanges parse() {
-		if (parsed != null)
-			return parsed;
-		Object o = getRawValue();
-		if (o == null)
-			return null;
-		return StringRanges.of(o.toString());
+	private static String serialize(StringRanges value) {
+		return stringify(value);
+	}
+
+	private StringRanges parse(String value) {
+		return StringRanges.of(value);
 	}
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicUriHeader.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicUriHeader.java
index d583557..a3447d6 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicUriHeader.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicUriHeader.java
@@ -12,6 +12,7 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.http.header;
 
+import static org.apache.juneau.internal.ExceptionUtils.*;
 import static org.apache.juneau.internal.StringUtils.*;
 import static java.util.Optional.*;
 
@@ -42,59 +43,103 @@ public class BasicUriHeader extends BasicHeader {
 	 * @param name The header name.
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link BasicUriHeader} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
+	 * 	<br>Must be parsable by {@link URI#create(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static BasicUriHeader of(String name, Object value) {
+	public static BasicUriHeader of(String name, String value) {
 		if (isEmpty(name) || value == null)
 			return null;
 		return new BasicUriHeader(name, value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
+	 * Convenience creator.
+	 *
+	 * @param name The header name.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
+	 */
+	public static BasicUriHeader of(String name, URI value) {
+		if (isEmpty(name) || value == null)
+			return null;
+		return new BasicUriHeader(name, value);
+	}
+
+	/**
+	 * Convenience creator with delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param name The header name.
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link BasicUriHeader} object, or <jk>null</jk> if the name or value is <jk>null</jk>.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static BasicUriHeader of(String name, Supplier<?> value) {
+	public static BasicUriHeader of(String name, Supplier<URI> value) {
 		if (isEmpty(name) || value == null)
 			return null;
 		return new BasicUriHeader(name, value);
 	}
 
-	private URI parsed;
+	private final URI value;
+	private final Supplier<URI> supplier;
 
 	/**
-	 * Constructor
+	 * Constructor.
 	 *
 	 * @param name The header name.
 	 * @param value
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * 	The header value.
+	 * 	<br>Must be parsable by {@link URI#create(String)}.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public BasicUriHeader(String name, Object value) {
+	public BasicUriHeader(String name, String value) {
 		super(name, value);
-		if (! isSupplier(value))
-			parsed = getParsedValue();
+		this.value = parse(value);
+		this.supplier = null;
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param name The header name.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public BasicUriHeader(String name, URI value) {
+		super(name, serialize(value));
+		this.value = value;
+		this.supplier = null;
+	}
+
+	/**
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
+	 *
+	 * @param name The header name.
+	 * @param value
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public BasicUriHeader(String name, Supplier<URI> value) {
+		super(name, null);
+		this.value = null;
+		this.supplier = value;
+	}
+
+	@Override /* Header */
+	public String getValue() {
+		if (supplier != null)
+			return serialize(supplier.get());
+		return super.getValue();
 	}
 
 	/**
@@ -103,15 +148,20 @@ public class BasicUriHeader extends BasicHeader {
 	 * @return This header as a {@link URI}, or {@link Optional#empty()} if the value is <jk>null</jk>
 	 */
 	public Optional<URI> asURI() {
-		return ofNullable(getParsedValue());
+		if (supplier != null)
+			return ofNullable(supplier.get());
+		return ofNullable(value);
 	}
 
-	private URI getParsedValue() {
-		if (parsed != null)
-			return parsed;
-		Object o = getRawValue();
-		if (o == null)
-			return null;
-		return URI.create(o.toString());
+	private static String serialize(URI value) {
+		return stringify(value);
+	}
+
+	private URI parse(String value) {
+		try {
+			return URI.create(value);
+		} catch (IllegalArgumentException e) {
+			throw runtimeException("Value ''{0}'' could not be parsed as a URI.", value);
+		}
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/CacheControl.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/CacheControl.java
index 627ae73..c873cfe 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/CacheControl.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/CacheControl.java
@@ -99,41 +99,34 @@ import org.apache.juneau.http.annotation.*;
 public class CacheControl extends BasicStringHeader {
 
 	private static final long serialVersionUID = 1L;
+	private static final String NAME = "Cache-Control";
 
 	/**
 	 * Convenience creator.
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link CacheControl} object.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static CacheControl of(Object value) {
+	public static CacheControl of(String value) {
 		if (value == null)
 			return null;
 		return new CacheControl(value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
+	 * Convenience creator with delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link CacheControl} object.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static CacheControl of(Supplier<?> value) {
+	public static CacheControl of(Supplier<String> value) {
 		if (value == null)
 			return null;
 		return new CacheControl(value);
@@ -144,24 +137,23 @@ public class CacheControl extends BasicStringHeader {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public CacheControl(Object value) {
-		super("Cache-Control", value);
+	public CacheControl(String value) {
+		super(NAME, value);
 	}
 
 	/**
-	 * Constructor
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param value
-	 * 	The header value.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public CacheControl(String value) {
-		this((Object)value);
+	public CacheControl(Supplier<String> value) {
+		super(NAME, value);
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ClientVersion.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ClientVersion.java
index 6407a85..19ffab7 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ClientVersion.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ClientVersion.java
@@ -12,10 +12,14 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.http.header;
 
+import static java.util.Optional.*;
 import static org.apache.juneau.http.header.Constants.*;
+import static org.apache.juneau.internal.StringUtils.*;
 
+import java.util.*;
 import java.util.function.*;
 
+import org.apache.juneau.assertions.*;
 import org.apache.juneau.http.annotation.*;
 import org.apache.juneau.internal.*;
 
@@ -38,15 +42,18 @@ import org.apache.juneau.internal.*;
 public class ClientVersion extends BasicStringHeader {
 
 	private static final long serialVersionUID = 1L;
+	private static final String NAME = "Client-Version";
 
 	private static final Cache<String,ClientVersion> CACHE = new Cache<>(NOCACHE, CACHE_MAX_SIZE);
 
 	/**
-	 * Returns a parsed and cached header.
+	 * Convenience creator.
 	 *
 	 * @param value
 	 * 	The header value.
-	 * @return A cached {@link ClientVersion} object.
+	 * 	<br>Must be parsable by {@link Version#of(String)}
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
 	public static ClientVersion of(String value) {
 		if (value == null)
@@ -54,7 +61,7 @@ public class ClientVersion extends BasicStringHeader {
 		ClientVersion x = CACHE.get(value);
 		if (x == null)
 			x = CACHE.put(value, new ClientVersion(value));
-		return x;
+		return new ClientVersion(value);
 	}
 
 	/**
@@ -62,63 +69,110 @@ public class ClientVersion extends BasicStringHeader {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link ClientVersion} object.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static ClientVersion of(Object value) {
+	public static ClientVersion of(Version value) {
 		if (value == null)
 			return null;
 		return new ClientVersion(value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
+	 * Convenience creator with delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link ClientVersion} object.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static ClientVersion of(Supplier<?> value) {
+	public static ClientVersion of(Supplier<Version> value) {
 		if (value == null)
 			return null;
 		return new ClientVersion(value);
 	}
 
+	private final Version value;
+	private final Supplier<Version> supplier;
+
 	/**
 	 * Constructor.
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * 	<br>Must be parsable by {@link Version#of(String)}
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public ClientVersion(Object value) {
-		super("Client-Version", value);
+	public ClientVersion(String value) {
+		super(NAME, value);
+		this.value = Version.of(value);
+		this.supplier = null;
 	}
 
 	/**
-	 * Constructor
+	 * Constructor.
 	 *
 	 * @param value
 	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public ClientVersion(String value) {
-		this((Object)value);
+	public ClientVersion(Version value) {
+		super(NAME, stringify(value));
+		this.value = value;
+		this.supplier = null;
+	}
+
+	/**
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
+	 *
+	 * @param value
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public ClientVersion(Supplier<Version> value) {
+		super(NAME, (String)null);
+		this.value = null;
+		this.supplier = value;
+	}
+
+	@Override /* Header */
+	public String getValue() {
+		if (supplier != null)
+			return stringify(supplier.get());
+		return super.getValue();
+	}
+
+	/**
+	 * Returns the header value as a {@link Version} object.
+	 *
+	 * @return The header value as a {@link Version} object, or {@link Optional#empty()} if the value is <jk>null</jk>.
+	 */
+	public Optional<Version> asVersion() {
+		return ofNullable(value);
+	}
+
+	/**
+	 * Provides the ability to perform fluent-style assertions on this header.
+	 *
+	 * <h5 class='section'>Examples:</h5>
+	 * <p class='bcode w800'>
+	 * 	<jc>// Validates the response content is older than 1.</jc>
+	 * 	client
+	 * 		.get(<jsf>URL</jsf>)
+	 * 		.run()
+	 * 		.getHeader(ClientVersion.<jk>class</jk>).assertVersion().major().isGreaterThan(1);
+	 * </p>
+	 *
+	 * @return A new fluent assertion object.
+	 * @throws AssertionError If assertion failed.
+	 */
+	public FluentVersionAssertion<ClientVersion> assertVersion() {
+		return new FluentVersionAssertion<>(asVersion().orElse(null), this);
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Connection.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Connection.java
index 75ad002..8a6467e 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Connection.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Connection.java
@@ -83,15 +83,17 @@ import org.apache.juneau.internal.*;
 public class Connection extends BasicStringHeader {
 
 	private static final long serialVersionUID = 1L;
+	private static final String NAME = "Connection";
 
 	private static final Cache<String,Connection> CACHE = new Cache<>(NOCACHE, CACHE_MAX_SIZE);
 
 	/**
-	 * Returns a parsed and cached header.
+	 * Convenience creator.
 	 *
 	 * @param value
 	 * 	The header value.
-	 * @return A cached {@link Connection} object.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
 	public static Connection of(String value) {
 		if (value == null)
@@ -99,43 +101,21 @@ public class Connection extends BasicStringHeader {
 		Connection x = CACHE.get(value);
 		if (x == null)
 			x = CACHE.put(value, new Connection(value));
-		return x;
-	}
-
-	/**
-	 * Convenience creator.
-	 *
-	 * @param value
-	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link Connection} object.
-	 */
-	public static Connection of(Object value) {
-		if (value == null)
-			return null;
 		return new Connection(value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
+	 * Convenience creator with delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link Connection} object.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static Connection of(Supplier<?> value) {
+	public static Connection of(Supplier<String> value) {
 		if (value == null)
 			return null;
 		return new Connection(value);
@@ -146,25 +126,24 @@ public class Connection extends BasicStringHeader {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public Connection(Object value) {
-		super("Connection", value);
+	public Connection(String value) {
+		super(NAME, value);
 	}
 
 	/**
-	 * Constructor
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param value
-	 * 	The header value.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public Connection(String value) {
-		this((Object)value);
+	public Connection(Supplier<String> value) {
+		super(NAME, value);
 	}
 
 	/**
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentDisposition.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentDisposition.java
index 40b8e7f..9d1bfb9 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentDisposition.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentDisposition.java
@@ -53,15 +53,18 @@ import org.apache.juneau.internal.*;
 public class ContentDisposition extends BasicStringRangeArrayHeader {
 
 	private static final long serialVersionUID = 1L;
+	private static final String NAME = "Content-Disposition";
 
 	private static final Cache<String,ContentDisposition> CACHE = new Cache<>(NOCACHE, CACHE_MAX_SIZE);
 
 	/**
-	 * Returns a parsed and cached header.
+	 * Convenience creator.
 	 *
 	 * @param value
 	 * 	The header value.
-	 * @return A cached {@link ContentDisposition} object.
+	 * 	<br>Must be parsable by {@link StringRanges#of(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
 	public static ContentDisposition of(String value) {
 		if (value == null)
@@ -69,7 +72,7 @@ public class ContentDisposition extends BasicStringRangeArrayHeader {
 		ContentDisposition x = CACHE.get(value);
 		if (x == null)
 			x = CACHE.put(value, new ContentDisposition(value));
-		return x;
+		return new ContentDisposition(value);
 	}
 
 	/**
@@ -77,63 +80,67 @@ public class ContentDisposition extends BasicStringRangeArrayHeader {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link ContentDisposition} object.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static ContentDisposition of(Object value) {
+	public static ContentDisposition of(StringRanges value) {
 		if (value == null)
 			return null;
 		return new ContentDisposition(value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
+	 * Convenience creator with delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link ContentDisposition} object.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static ContentDisposition of(Supplier<?> value) {
+	public static ContentDisposition of(Supplier<StringRanges> value) {
 		if (value == null)
 			return null;
 		return new ContentDisposition(value);
 	}
 
+
 	/**
 	 * Constructor.
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * 	<br>Must be parsable by {@link StringRanges#of(String)}.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public ContentDisposition(Object value) {
-		super("Content-Disposition", value);
+	public ContentDisposition(String value) {
+		super(NAME, value);
 	}
 
 	/**
-	 * Constructor
+	 * Constructor.
 	 *
 	 * @param value
 	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public ContentDisposition(String value) {
-		this((Object)value);
+	public ContentDisposition(StringRanges value) {
+		super(NAME, value);
+	}
+
+	/**
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
+	 *
+	 * @param value
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public ContentDisposition(Supplier<StringRanges> value) {
+		super(NAME, value);
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentEncoding.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentEncoding.java
index 64c4eb5..36ec1fa 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentEncoding.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentEncoding.java
@@ -72,41 +72,34 @@ import org.apache.juneau.http.annotation.*;
 public class ContentEncoding extends BasicStringHeader {
 
 	private static final long serialVersionUID = 1L;
+	private static final String NAME = "Content-Encoding";
 
 	/**
 	 * Convenience creator.
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link ContentEncoding} object.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static ContentEncoding of(Object value) {
+	public static ContentEncoding of(String value) {
 		if (value == null)
 			return null;
 		return new ContentEncoding(value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
+	 * Convenience creator with delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link ContentEncoding} object.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static ContentEncoding of(Supplier<?> value) {
+	public static ContentEncoding of(Supplier<String> value) {
 		if (value == null)
 			return null;
 		return new ContentEncoding(value);
@@ -117,24 +110,23 @@ public class ContentEncoding extends BasicStringHeader {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public ContentEncoding(Object value) {
-		super("Content-Encoding", value);
+	public ContentEncoding(String value) {
+		super(NAME, value);
 	}
 
 	/**
-	 * Constructor
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param value
-	 * 	The header value.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public ContentEncoding(String value) {
-		this((Object)value);
+	public ContentEncoding(Supplier<String> value) {
+		super(NAME, value);
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentLanguage.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentLanguage.java
index 6a937e4..428c61c 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentLanguage.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentLanguage.java
@@ -77,47 +77,48 @@ import org.apache.juneau.http.annotation.*;
 public class ContentLanguage extends BasicCsvArrayHeader {
 
 	private static final long serialVersionUID = 1L;
+	private static final String NAME = "Content-Language";
 
 	/**
 	 * Convenience creator.
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - A comma-delimited string.
-	 * 		<li><c>String[]</c> - A pre-parsed value.
-	 * 		<li>Any other array type - Converted to <c>String[]</c>.
-	 * 		<li>Any {@link Collection} - Converted to <c>String[]</c>.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return The parsed <c>Content-Language</c> header, or <jk>null</jk> if the value was null.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static ContentLanguage of(Object value) {
+	public static ContentLanguage of(String value) {
 		if (value == null)
 			return null;
 		return new ContentLanguage(value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
+	 * Convenience creator.
+	 *
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
+	 */
+	public static ContentLanguage of(List<String> value) {
+		if (value == null)
+			return null;
+		return new ContentLanguage(value);
+	}
+
+	/**
+	 * Convenience creator with delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - A comma-delimited string.
-	 * 		<li><c>String[]</c> - A pre-parsed value.
-	 * 		<li>Any other array type - Converted to <c>String[]</c>.
-	 * 		<li>Any {@link Collection} - Converted to <c>String[]</c>.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return The parsed <c>Content-Language</c> header, or <jk>null</jk> if the value was null.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static ContentLanguage of(Supplier<?> value) {
+	public static ContentLanguage of(Supplier<List<String>> value) {
 		if (value == null)
 			return null;
 		return new ContentLanguage(value);
@@ -128,27 +129,34 @@ public class ContentLanguage extends BasicCsvArrayHeader {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - A comma-delimited string.
-	 * 		<li><c>String[]</c> - A pre-parsed value.
-	 * 		<li>Any other array type - Converted to <c>String[]</c>.
-	 * 		<li>Any {@link Collection} - Converted to <c>String[]</c>.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public ContentLanguage(Object value) {
-		super("Content-Language", value);
+	public ContentLanguage(String value) {
+		super(NAME, value);
 	}
 
 	/**
-	 * Constructor
+	 * Constructor.
 	 *
 	 * @param value
 	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public ContentLanguage(String value) {
-		this((Object)value);
+	public ContentLanguage(List<String> value) {
+		super(NAME, value);
+	}
+
+	/**
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
+	 *
+	 * @param value
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public ContentLanguage(Supplier<List<String>> value) {
+		super(NAME, value);
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentLength.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentLength.java
index 6c9c6fe..eabc4b2 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentLength.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentLength.java
@@ -64,43 +64,49 @@ import org.apache.juneau.http.annotation.*;
 public class ContentLength extends BasicLongHeader {
 
 	private static final long serialVersionUID = 1L;
+	private static final String NAME = "Content-Length";
 
 	/**
 	 * Convenience creator.
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link Number} - Converted to a long using {@link Number#longValue()}.
-	 * 		<li>{@link String} - Parsed using {@link Long#parseLong(String)}.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new {@link ContentLength} object.
+	 * 	<br>Must be parsable using {@link Long#parseLong(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static ContentLength of(Object value) {
+	public static ContentLength of(String value) {
 		if (value == null)
 			return null;
 		return new ContentLength(value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
+	 * Convenience creator.
+	 *
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
+	 */
+	public static ContentLength of(Long value) {
+		if (value == null)
+			return null;
+		return new ContentLength(value);
+	}
+
+	/**
+	 * Convenience creator with delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link Number} - Converted to a long using {@link Number#longValue()}.
-	 * 		<li>{@link String} - Parsed using {@link Long#parseLong(String)}.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new {@link ContentLength} object.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static ContentLength of(Supplier<?> value) {
+	public static ContentLength of(Supplier<Long> value) {
 		if (value == null)
 			return null;
 		return new ContentLength(value);
@@ -111,25 +117,35 @@ public class ContentLength extends BasicLongHeader {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link Number} - Converted to a long using {@link Number#longValue()}.
-	 * 		<li>{@link String} - Parsed using {@link Long#parseLong(String)}.
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * 	<br>Must be parsable using {@link Long#parseLong(String)}.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public ContentLength(Object value) {
-		super("Content-Length", value);
+	public ContentLength(String value) {
+		super(NAME, value);
 	}
 
 	/**
-	 * Constructor
+	 * Constructor.
 	 *
 	 * @param value
 	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public ContentLength(String value) {
-		this((Object)value);
+	public ContentLength(Long value) {
+		super(NAME, value);
+	}
+
+	/**
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
+	 *
+	 * @param value
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public ContentLength(Supplier<Long> value) {
+		super(NAME, value);
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentLocation.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentLocation.java
index dea5c6d..78a403a 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentLocation.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentLocation.java
@@ -12,6 +12,7 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.http.header;
 
+import java.net.*;
 import java.util.function.*;
 
 import org.apache.juneau.http.annotation.*;
@@ -70,69 +71,88 @@ import org.apache.juneau.http.annotation.*;
 public class ContentLocation extends BasicUriHeader {
 
 	private static final long serialVersionUID = 1L;
+	private static final String NAME = "Content-Location";
 
 	/**
 	 * Convenience creator.
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link ContentLocation} object.
+	 * 	<br>Must be parsable by {@link URI#create(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static ContentLocation of(Object value) {
+	public static ContentLocation of(String value) {
 		if (value == null)
 			return null;
 		return new ContentLocation(value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
+	 * Convenience creator.
+	 *
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
+	 */
+	public static ContentLocation of(URI value) {
+		if (value == null)
+			return null;
+		return new ContentLocation(value);
+	}
+
+	/**
+	 * Convenience creator with delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link ContentLocation} object.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static ContentLocation of(Supplier<?> value) {
+	public static ContentLocation of(Supplier<URI> value) {
 		if (value == null)
 			return null;
 		return new ContentLocation(value);
 	}
 
 	/**
-	 * Constructor
+	 * Constructor.
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * 	<br>Must be parsable by {@link URI#create(String)}.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public ContentLocation(Object value) {
-		super("Content-Location", value);
+	public ContentLocation(String value) {
+		super(NAME, value);
 	}
 
 	/**
-	 * Constructor
+	 * Constructor.
 	 *
 	 * @param value
 	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public ContentLocation(String value) {
-		this((Object)value);
+	public ContentLocation(URI value) {
+		super(NAME, value);
+	}
+
+	/**
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
+	 *
+	 * @param value
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public ContentLocation(Supplier<URI> value) {
+		super(NAME, value);
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentRange.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentRange.java
index 213c060..10d528c 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentRange.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentRange.java
@@ -132,41 +132,34 @@ import org.apache.juneau.http.annotation.*;
 public class ContentRange extends BasicStringHeader {
 
 	private static final long serialVersionUID = 1L;
+	private static final String NAME = "Content-Range";
 
 	/**
 	 * Convenience creator.
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link ContentRange} object.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static ContentRange of(Object value) {
+	public static ContentRange of(String value) {
 		if (value == null)
 			return null;
 		return new ContentRange(value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
+	 * Convenience creator with delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link ContentRange} object.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static ContentRange of(Supplier<?> value) {
+	public static ContentRange of(Supplier<String> value) {
 		if (value == null)
 			return null;
 		return new ContentRange(value);
@@ -177,24 +170,23 @@ public class ContentRange extends BasicStringHeader {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public ContentRange(Object value) {
-		super("Content-Range", value);
+	public ContentRange(String value) {
+		super(NAME, value);
 	}
 
 	/**
-	 * Constructor
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param value
-	 * 	The header value.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public ContentRange(String value) {
-		this((Object)value);
+	public ContentRange(Supplier<String> value) {
+		super(NAME, value);
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentType.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentType.java
index e93342c..95ab25e 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentType.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ContentType.java
@@ -13,7 +13,6 @@
 package org.apache.juneau.http.header;
 
 import static org.apache.juneau.http.header.Constants.*;
-import static org.apache.juneau.internal.StringUtils.*;
 
 import java.util.function.*;
 
@@ -54,6 +53,7 @@ import org.apache.juneau.internal.*;
 public class ContentType extends BasicMediaTypeHeader {
 
 	private static final long serialVersionUID = 1L;
+	private static final String NAME = "Content-Type";
 
 	private static Cache<String,ContentType> CACHE = new Cache<>(NOCACHE, CACHE_MAX_SIZE);
 
@@ -82,86 +82,88 @@ public class ContentType extends BasicMediaTypeHeader {
 		WILDCARD = of("*/*");
 
 	/**
-	 * Returns a parsed and cached <c>Content-Type</c> header.
+	 * Convenience creator.
 	 *
-	 * @param value The <c>Content-Type</c> header string.
-	 * @return The parsed <c>Content-Type</c> header, or <jk>null</jk> if the string was null.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be parsable by {@link MediaType#of(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
 	public static ContentType of(String value) {
-		if (isEmpty(value))
+		if (value == null)
 			return null;
-		ContentType ct = CACHE.get(value);
-		if (ct == null)
-			ct = CACHE.put(value, new ContentType(value));
-		return ct;
+		ContentType x = CACHE.get(value);
+		if (x == null)
+			x = CACHE.put(value, new ContentType(value));
+		return new ContentType(value);
 	}
 
 	/**
-	 * Returns a parsed and cached <c>Content-Type</c> header.
+	 * Convenience creator.
 	 *
-	 * @param value The <c>Content-Type</c> header value.
-	 * @return The parsed <c>Content-Type</c> header, or <jk>null</jk> if the string was null.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
 	public static ContentType of(MediaType value) {
-		if (isEmpty(value))
+		if (value == null)
 			return null;
-		return of(value.toString());
+		return new ContentType(value);
 	}
 
 	/**
-	 * Convenience creator.
+	 * Convenience creator with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String} - Converted using {@link MediaType#of(String)}.
-	 * 		<li>{@link MediaType}.
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link AcceptEncoding} object.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static ContentType of(Object value) {
-		if (isEmpty(value))
+	public static ContentType of(Supplier<MediaType> value) {
+		if (value == null)
 			return null;
 		return new ContentType(value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
-	 *
-	 * <p>
-	 * Header value is re-evaluated on each call to {@link #getValue()}.
+	 * Constructor.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String} - Converted using {@link MediaType#of(String)}.
-	 * 		<li>{@link MediaType}.
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link AcceptEncoding} object.
+	 * 	The header value.
+	 * 	<br>Must be parsable by {@link MediaType#of(String)}.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public static ContentType of(Supplier<?> value) {
-		return new ContentType(value);
+	public ContentType(String value) {
+		super(NAME, value);
 	}
 
 	/**
 	 * Constructor.
 	 *
-	 * @param value The value for this header.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public ContentType(Object value) {
-		super("Content-Type", value);
+	public ContentType(MediaType value) {
+		super(NAME, value);
 	}
 
 	/**
-	 * Constructor.
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
-	 * @param value The value for this header.
+	 * @param value
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public ContentType(String value) {
-		this((Object)value);
+	public ContentType(Supplier<MediaType> value) {
+		super(NAME, value);
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Date.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Date.java
index 999e74a..56e0047 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Date.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Date.java
@@ -13,7 +13,6 @@
 package org.apache.juneau.http.header;
 
 import java.time.*;
-import java.util.*;
 import java.util.function.*;
 
 import org.apache.juneau.http.annotation.*;
@@ -84,45 +83,49 @@ import org.apache.juneau.http.annotation.*;
 public class Date extends BasicDateHeader {
 
 	private static final long serialVersionUID = 1L;
+	private static final String NAME = "Date";
 
 	/**
 	 * Convenience creator.
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - An RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>).
-	 * 		<li>{@link ZonedDateTime}
-	 * 		<li>{@link Calendar}
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new {@link Date} object, or <jk>null</jk> if the value was null.
+	 * 	<br>Must be an RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>).
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static Date of(Object value) {
+	public static Date of(String value) {
 		if (value == null)
 			return null;
 		return new Date(value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
+	 * Convenience creator.
+	 *
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
+	 */
+	public static Date of(ZonedDateTime value) {
+		if (value == null)
+			return null;
+		return new Date(value);
+	}
+
+	/**
+	 * Convenience creator with delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - An RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>).
-	 * 		<li>{@link ZonedDateTime}
-	 * 		<li>{@link Calendar}
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new {@link Date} object, or <jk>null</jk> if the value was null.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static Date of(Supplier<?> value) {
+	public static Date of(Supplier<ZonedDateTime> value) {
 		if (value == null)
 			return null;
 		return new Date(value);
@@ -133,26 +136,35 @@ public class Date extends BasicDateHeader {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - An RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>).
-	 * 		<li>{@link ZonedDateTime}
-	 * 		<li>{@link Calendar}
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * 	<br>Must be an RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>).
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public Date(Object value) {
-		super("Date", value);
+	public Date(String value) {
+		super(NAME, value);
 	}
 
 	/**
-	 * Constructor
+	 * Constructor.
 	 *
 	 * @param value
 	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public Date(String value) {
-		this((Object)value);
+	public Date(ZonedDateTime value) {
+		super(NAME, value);
+	}
+
+	/**
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
+	 *
+	 * @param value
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public Date(Supplier<ZonedDateTime> value) {
+		super(NAME, value);
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Debug.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Debug.java
index 14c6524..8ede307 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Debug.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Debug.java
@@ -35,41 +35,52 @@ import org.apache.juneau.http.annotation.*;
 public class Debug extends BasicBooleanHeader {
 
 	private static final long serialVersionUID = 1L;
+	private static final String NAME = "Debug";
+
+	@SuppressWarnings("javadoc")
+	public static final Debug TRUE = of(true), FALSE = of(false);
+
+	/**
+	 * Convenience creator.
+	 *
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Must be parsable by {@link Boolean#parseBoolean(String)}.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
+	 */
+	public static Debug of(String value) {
+		if (value == null)
+			return null;
+		return new Debug(value);
+	}
 
 	/**
 	 * Convenience creator.
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link Boolean}
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new {@link Debug} object, or <jk>null</jk> if the value was null.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
 	 */
-	public static Debug of(Object value) {
+	public static Debug of(Boolean value) {
 		if (value == null)
 			return null;
 		return new Debug(value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
+	 * Convenience creator with delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param value
 	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link Boolean}
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new {@link Debug} object, or <jk>null</jk> if the value was null.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value was <jk>null</jk>.
 	 */
-	public static Debug of(Supplier<?> value) {
+	public static Debug of(Supplier<Boolean> value) {
 		if (value == null)
 			return null;
 		return new Debug(value);
@@ -80,24 +91,35 @@ public class Debug extends BasicBooleanHeader {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link Boolean}
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * 	<br>Must be parsable by {@link Boolean#parseBoolean(String)}.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public Debug(Object value) {
-		super("Debug", value);
+	public Debug(String value) {
+		super(NAME, value);
 	}
 
 	/**
-	 * Constructor
+	 * Constructor.
 	 *
 	 * @param value
 	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public Debug(String value) {
-		this((Object)value);
+	public Debug(Boolean value) {
+		super(NAME, value);
+	}
+
+	/**
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
+	 *
+	 * @param value
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public Debug(Supplier<Boolean> value) {
+		super(NAME, value);
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ETag.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ETag.java
index 1bff2b9..b3eb738 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ETag.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/ETag.java
@@ -53,41 +53,49 @@ import org.apache.juneau.http.annotation.*;
 public class ETag extends BasicEntityTagHeader {
 
 	private static final long serialVersionUID = 1L;
+	private static final String NAME = "ETag";
 
 	/**
 	 * Convenience creator.
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link ETag} object.
+	 * 	<br>Must be an entity tag value (e.g. <js>"\"xyzzy\""</js>).
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static ETag of(Object value) {
+	public static ETag of(String value) {
 		if (value == null)
 			return null;
 		return new ETag(value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
+	 * Convenience creator.
+	 *
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
+	 */
+	public static ETag of(EntityTag value) {
+		if (value == null)
+			return null;
+		return new ETag(value);
+	}
+
+	/**
+	 * Convenience creator with delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link ETag} object.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static ETag of(Supplier<?> value) {
+	public static ETag of(Supplier<EntityTag> value) {
 		if (value == null)
 			return null;
 		return new ETag(value);
@@ -98,24 +106,35 @@ public class ETag extends BasicEntityTagHeader {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * 	<br>Must be an entity tag value (e.g. <js>"\"xyzzy\""</js>).
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public ETag(Object value) {
-		super("ETag", value);
+	public ETag(String value) {
+		super(NAME, value);
 	}
 
 	/**
-	 * Constructor
+	 * Constructor.
 	 *
 	 * @param value
 	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public ETag(String value) {
-		this((Object)value);
+	public ETag(EntityTag value) {
+		super(NAME, value);
+	}
+
+	/**
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
+	 *
+	 * @param value
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public ETag(Supplier<EntityTag> value) {
+		super(NAME, value);
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/EntityTag.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/EntityTag.java
index 9cb6261..f386a36 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/EntityTag.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/EntityTag.java
@@ -40,7 +40,7 @@ public class EntityTag {
 	 * Creator.
 	 *
 	 * @param value The validator string value.
-	 * @return A new {@link EntityTag} object or <jk>null</jk> if the value was <jk>null</jk>.
+	 * @return A new header bean or <jk>null</jk> if the value was <jk>null</jk>.
 	 * @throws IllegalArgumentException If attempting to set an invalid entity tag value.
 	 */
 	public static EntityTag of(Object value) {
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Expect.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Expect.java
index ecd6b6e..093993d 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Expect.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Expect.java
@@ -72,41 +72,34 @@ import org.apache.juneau.http.annotation.*;
 public class Expect extends BasicStringHeader {
 
 	private static final long serialVersionUID = 1L;
+	private static final String NAME = "Expect";
 
 	/**
 	 * Convenience creator.
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link Expect} object.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static Expect of(Object value) {
+	public static Expect of(String value) {
 		if (value == null)
 			return null;
 		return new Expect(value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
+	 * Convenience creator with delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link Expect} object.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static Expect of(Supplier<?> value) {
+	public static Expect of(Supplier<String> value) {
 		if (value == null)
 			return null;
 		return new Expect(value);
@@ -117,24 +110,23 @@ public class Expect extends BasicStringHeader {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public Expect(Object value) {
-		super("Expect", value);
+	public Expect(String value) {
+		super(NAME, value);
 	}
 
 	/**
-	 * Constructor
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param value
-	 * 	The header value.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public Expect(String value) {
-		this((Object)value);
+	public Expect(Supplier<String> value) {
+		super(NAME, value);
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Expires.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Expires.java
index cf46d58..12727d5 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Expires.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Expires.java
@@ -13,7 +13,6 @@
 package org.apache.juneau.http.header;
 
 import java.time.*;
-import java.util.*;
 import java.util.function.*;
 
 import org.apache.juneau.http.annotation.*;
@@ -85,45 +84,49 @@ import org.apache.juneau.http.annotation.*;
 public class Expires extends BasicDateHeader {
 
 	private static final long serialVersionUID = 1L;
+	private static final String NAME = "Expires";
 
 	/**
 	 * Convenience creator.
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - An RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>).
-	 * 		<li>{@link ZonedDateTime}
-	 * 		<li>{@link Calendar}
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new {@link Expires} object, or <jk>null</jk> if the value was null.
+	 * 	<br>Must be an RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>).
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static Expires of(Object value) {
+	public static Expires of(String value) {
 		if (value == null)
 			return null;
 		return new Expires(value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
+	 * Convenience creator.
+	 *
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
+	 */
+	public static Expires of(ZonedDateTime value) {
+		if (value == null)
+			return null;
+		return new Expires(value);
+	}
+
+	/**
+	 * Convenience creator with delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - An RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>).
-	 * 		<li>{@link ZonedDateTime}
-	 * 		<li>{@link Calendar}
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 	</ul>
-	 * @return A new {@link Expires} object, or <jk>null</jk> if the value was null.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the name is <jk>null</jk> or empty or the value is <jk>null</jk>.
 	 */
-	public static Expires of(Supplier<?> value) {
+	public static Expires of(Supplier<ZonedDateTime> value) {
 		if (value == null)
 			return null;
 		return new Expires(value);
@@ -134,26 +137,35 @@ public class Expires extends BasicDateHeader {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li><c>String</c> - An RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>).
-	 * 		<li>{@link ZonedDateTime}
-	 * 		<li>{@link Calendar}
-	 * 		<li>Anything else - Converted to <c>String</c>.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * 	<br>Must be an RFC-1123 formated string (e.g. <js>"Sat, 29 Oct 1994 19:43:31 GMT"</js>).
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public Expires(Object value) {
-		super("Expires", value);
+	public Expires(String value) {
+		super(NAME, value);
 	}
 
 	/**
-	 * Constructor
+	 * Constructor.
 	 *
 	 * @param value
 	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public Expires(String value) {
-		this((Object)value);
+	public Expires(ZonedDateTime value) {
+		super(NAME, value);
+	}
+
+	/**
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
+	 *
+	 * @param value
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 */
+	public Expires(Supplier<ZonedDateTime> value) {
+		super(NAME, value);
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Forwarded.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Forwarded.java
index ba9729f..a5330b0 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Forwarded.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/Forwarded.java
@@ -23,41 +23,34 @@ import org.apache.juneau.http.annotation.*;
 public class Forwarded extends BasicStringHeader {
 
 	private static final long serialVersionUID = 1L;
+	private static final String NAME = "Forwarded";
 
 	/**
 	 * Convenience creator.
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link Forwarded} object.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static Forwarded of(Object value) {
+	public static Forwarded of(String value) {
 		if (value == null)
 			return null;
 		return new Forwarded(value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
+	 * Convenience creator with delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link Forwarded} object.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static Forwarded of(Supplier<?> value) {
+	public static Forwarded of(Supplier<String> value) {
 		if (value == null)
 			return null;
 		return new Forwarded(value);
@@ -68,24 +61,23 @@ public class Forwarded extends BasicStringHeader {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public Forwarded(Object value) {
-		super("Forwarded", value);
+	public Forwarded(String value) {
+		super(NAME, value);
 	}
 
 	/**
-	 * Constructor
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param value
-	 * 	The header value.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public Forwarded(String value) {
-		this((Object)value);
+	public Forwarded(Supplier<String> value) {
+		super(NAME, value);
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/From.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/From.java
index 035935c..f7f85ae 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/From.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/From.java
@@ -70,41 +70,34 @@ import org.apache.juneau.http.annotation.*;
 public class From extends BasicStringHeader {
 
 	private static final long serialVersionUID = 1L;
+	private static final String NAME = "From";
 
 	/**
 	 * Convenience creator.
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link From} object.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static From of(Object value) {
+	public static From of(String value) {
 		if (value == null)
 			return null;
 		return new From(value);
 	}
 
 	/**
-	 * Convenience creator using supplier.
+	 * Convenience creator with delayed value.
 	 *
 	 * <p>
 	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param value
-	 * 	The header value supplier.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 	</ul>
-	 * @return A new {@link From} object.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new header bean, or <jk>null</jk> if the value is <jk>null</jk>.
 	 */
-	public static From of(Supplier<?> value) {
+	public static From of(Supplier<String> value) {
 		if (value == null)
 			return null;
 		return new From(value);
@@ -115,24 +108,23 @@ public class From extends BasicStringHeader {
 	 *
 	 * @param value
 	 * 	The header value.
-	 * 	<br>Can be any of the following:
-	 * 	<ul>
-	 * 		<li>{@link String}
-	 * 		<li>Anything else - Converted to <c>String</c> using {@link Object#toString()} and then parsed.
-	 * 		<li>A {@link Supplier} of anything on this list.
-	 * 	</ul>
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public From(Object value) {
-		super("From", value);
+	public From(String value) {
+		super(NAME, value);
 	}
 
 	/**
-	 * Constructor
+	 * Constructor with delayed value.
+	 *
+	 * <p>
+	 * Header value is re-evaluated on each call to {@link #getValue()}.
 	 *
 	 * @param value
-	 * 	The header value.
+	 * 	The supplier of the header value.
+	 * 	<br>Can be <jk>null</jk>.
 	 */
-	public From(String value) {
-		this((Object)value);
+	public From(Supplier<String> value) {
+		super(NAME, value);
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/HeaderList.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/HeaderList.java
index 51b4194..328a60d 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/HeaderList.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/HeaderList.java
@@ -13,7 +13,6 @@
 package org.apache.juneau.http.header;
 
 import static org.apache.juneau.assertions.Assertions.*;
-import static org.apache.juneau.internal.StringUtils.*;
 
 import java.util.*;
 import java.util.function.*;
@@ -220,14 +219,14 @@ public class HeaderList {
 	 * @throws RuntimeException If odd number of parameters were specified.
 	 * @return A new instance.
 	 */
-	public static HeaderList ofPairs(Object...pairs) {
+	public static HeaderList ofPairs(String...pairs) {
 		if (pairs == null || pairs.length == 0)
 			return EMPTY;
 		if (pairs.length % 2 != 0)
 			throw new BasicRuntimeException("Odd number of parameters passed into HeaderList.ofPairs()");
 		ArrayBuilder<Header> b = ArrayBuilder.create(Header.class, pairs.length / 2, true);
 		for (int i = 0; i < pairs.length; i+=2)
-			b.add(BasicHeader.of(stringify(pairs[i]), pairs[i+1]));
+			b.add(BasicHeader.of(pairs[i], pairs[i+1]));
 		return new HeaderList(b.toArray());
 	}
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/HeaderListBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/HeaderListBuilder.java
index af8390c..0622e8e 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/HeaderListBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/HeaderListBuilder.java
@@ -12,12 +12,14 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.http.header;
 
+import static org.apache.juneau.internal.ExceptionUtils.*;
 import static org.apache.juneau.internal.StringUtils.*;
 
 import java.util.*;
 import java.util.function.*;
 
 import org.apache.http.*;
+import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.svl.*;
@@ -50,7 +52,7 @@ public class HeaderListBuilder {
 	 *
 	 * @param copyFrom The bean to copy from.
 	 */
-	public HeaderListBuilder(HeaderList copyFrom) {
+	protected HeaderListBuilder(HeaderList copyFrom) {
 		entries = new ArrayList<>(copyFrom.entries.length);
 		for (int i = 0; i < copyFrom.entries.length; i++)
 			entries.add(copyFrom.entries[i]);
@@ -58,6 +60,27 @@ public class HeaderListBuilder {
 	}
 
 	/**
+	 * Copy constructor.
+	 *
+	 * @param copyFrom The bean to copy from.
+	 */
+	protected HeaderListBuilder(HeaderListBuilder copyFrom) {
+		entries = new ArrayList<>(copyFrom.entries);
+		defaultEntries = copyFrom.defaultEntries == null ? null : new ArrayList<>(copyFrom.defaultEntries);
+		varResolver = copyFrom.varResolver;
+		caseSensitive = copyFrom.caseSensitive;
+	}
+
+	/**
+	 * Creates a modifiable copy of this builder.
+	 *
+	 * @return A shallow copy of this builder.
+	 */
+	public HeaderListBuilder copy() {
+		return new HeaderListBuilder(this);
+	}
+
+	/**
 	 * Creates a new {@link HeaderList} bean based on the contents of this builder.
 	 *
 	 * @return A new {@link HeaderList} bean.
@@ -177,7 +200,7 @@ public class HeaderListBuilder {
 	 * @return This object (for method chaining).
 	 */
 	public HeaderListBuilder append(String name, Object value) {
-		return append(header(name, value));
+		return append(createHeader(name, value));
 	}
 
 	/**
@@ -194,7 +217,7 @@ public class HeaderListBuilder {
 	 * @return This object (for method chaining).
 	 */
 	public HeaderListBuilder append(String name, Supplier<?> value) {
-		return append(header(name, value));
+		return append(createHeader(name, value));
 	}
 
 	/**
@@ -262,7 +285,7 @@ public class HeaderListBuilder {
 	 * @return This object (for method chaining).
 	 */
 	public HeaderListBuilder prepend(String name, Object value) {
-		return prepend(header(name, value));
+		return prepend(createHeader(name, value));
 	}
 
 	/**
@@ -279,7 +302,7 @@ public class HeaderListBuilder {
 	 * @return This object (for method chaining).
 	 */
 	public HeaderListBuilder prepend(String name, Supplier<?> value) {
-		return prepend(header(name, value));
+		return prepend(createHeader(name, value));
 	}
 
 	/**
@@ -446,7 +469,7 @@ public class HeaderListBuilder {
 	 * @return This object (for method chaining).
... 8831 lines suppressed ...