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/03/02 18:27:04 UTC

[juneau] branch master updated: HTTP exception classes should implement HttpResponse.

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 f43f541  HTTP exception classes should implement HttpResponse.
f43f541 is described below

commit f43f541dfc248f7dc5f506792215f08eedcbbde4
Author: JamesBognar <ja...@salesforce.com>
AuthorDate: Tue Mar 2 13:26:45 2021 -0500

    HTTP exception classes should implement HttpResponse.
---
 TODO.txt                                           |   2 +
 .../main/ConfigurablePropertyCodeGenerator.java    |  39 +-
 .../org/apache/juneau/BasicRuntimeException.java   |  86 +++-
 ...tion.java => BasicRuntimeExceptionBuilder.java} |  70 +--
 .../java/org/apache/juneau/ConfigException.java    |   2 +-
 .../org/apache/juneau/ContextRuntimeException.java |   6 +-
 .../juneau/InvalidDataConversionException.java     |   2 +-
 .../org/apache/juneau/http/BasicHeaderGroup.java   | 228 ++++++++++
 .../juneau/http/BasicHeaderGroupBuilder.java       | 251 +++++++++++
 .../org/apache/juneau/http/BasicStatusLine.java    |  93 ++++
 .../apache/juneau/http/BasicStatusLineBuilder.java | 126 ++++++
 .../apache/juneau/http/exception/BadRequest.java   |  68 +--
 .../org/apache/juneau/http/exception/Conflict.java |  68 +--
 .../juneau/http/exception/ExpectationFailed.java   |  68 +--
 .../juneau/http/exception/FailedDependency.java    |  68 +--
 .../apache/juneau/http/exception/Forbidden.java    |  68 +--
 .../org/apache/juneau/http/exception/Gone.java     |  68 +--
 .../juneau/http/exception/HttpException.java       | 307 +++++++++----
 .../http/exception/HttpExceptionBuilder.java       | 399 +++++++++++++++++
 .../http/exception/HttpVersionNotSupported.java    |  68 +--
 .../juneau/http/exception/InsufficientStorage.java |  68 +--
 .../juneau/http/exception/InternalServerError.java |  68 +--
 .../juneau/http/exception/LengthRequired.java      |  68 +--
 .../org/apache/juneau/http/exception/Locked.java   |  68 +--
 .../apache/juneau/http/exception/LoopDetected.java |  68 +--
 .../juneau/http/exception/MethodNotAllowed.java    |  68 +--
 .../juneau/http/exception/MisdirectedRequest.java  |  68 +--
 .../exception/NetworkAuthenticationRequired.java   |  68 +--
 .../juneau/http/exception/NotAcceptable.java       |  68 +--
 .../apache/juneau/http/exception/NotExtended.java  |  69 +--
 .../org/apache/juneau/http/exception/NotFound.java |  68 +--
 .../juneau/http/exception/NotImplemented.java      |  68 +--
 .../juneau/http/exception/PayloadTooLarge.java     |  68 +--
 .../juneau/http/exception/PreconditionFailed.java  |  62 +--
 .../http/exception/PreconditionRequired.java       |  68 +--
 .../juneau/http/exception/RangeNotSatisfiable.java |  68 +--
 .../exception/RequestHeaderFieldsTooLarge.java     |  68 +--
 .../juneau/http/exception/ServiceUnavailable.java  |  68 +--
 .../juneau/http/exception/StandardExceptions.java  | 491 +++++++++++++++++++++
 .../juneau/http/exception/TooManyRequests.java     |  68 +--
 .../apache/juneau/http/exception/Unauthorized.java |  68 +--
 .../http/exception/UnavailableForLegalReasons.java |  68 +--
 .../juneau/http/exception/UnprocessableEntity.java |  68 +--
 .../http/exception/UnsupportedMediaType.java       |  68 +--
 .../juneau/http/exception/UpgradeRequired.java     |  68 +--
 .../apache/juneau/http/exception/UriTooLong.java   |  68 +--
 .../http/exception/VariantAlsoNegotiates.java      |  68 +--
 .../apache/juneau/svl/VarResolverException.java    |   2 +-
 .../org/apache/juneau/utils/PojoRestException.java |   2 +-
 .../client/remote/RemoteMetadataException.java     |   2 +-
 .../java/org/apache/juneau/rest/RestContext.java   |   8 +-
 .../apache/juneau/rest/converters/Traversable.java |   2 +-
 .../juneau/assertions/ArrayAssertion_Test.java     |  54 +--
 .../juneau/assertions/BeanAssertion_Test.java      |  24 +-
 .../juneau/assertions/BooleanAssertion_Test.java   |  46 +-
 .../juneau/assertions/ByteArrayAssertion_Test.java | 113 ++---
 .../assertions/CollectionAssertion_Test.java       |  46 +-
 .../assertions/ComparableAssertion_Test.java       |  12 +-
 .../juneau/assertions/DateAssertion_Test.java      |  98 ++--
 .../juneau/assertions/IntegerAssertion_Test.java   | 160 +++----
 .../juneau/assertions/ListAssertion_Test.java      |  44 +-
 .../juneau/assertions/LongAssertion_Test.java      | 167 +++----
 .../juneau/assertions/MapAssertion_Test.java       |  54 +--
 .../juneau/assertions/ObjectAssertion_Test.java    | 134 +++---
 .../juneau/assertions/StringAssertion_Test.java    | 231 +++++-----
 .../juneau/assertions/ThrowableAssertion_Test.java |  84 ++--
 .../org/apache/juneau/assertions/Verify_Test.java  |  58 +--
 .../assertions/ZonedDateTimeAssertion_Test.java    |  99 +++--
 .../juneau/http/exception/BadRequest_Test.java     |   3 +-
 .../juneau/http/exception/Conflict_Test.java       |   3 +-
 .../http/exception/ExpectationFailed_Test.java     |   3 +-
 .../http/exception/FailedDependency_Test.java      |   3 +-
 .../juneau/http/exception/Forbidden_Test.java      |   3 +-
 .../apache/juneau/http/exception/Gone_Test.java    |   3 +-
 .../juneau/http/exception/HttpException_Test.java  |  31 +-
 .../exception/HttpVersionNotSupported_Test.java    |   3 +-
 .../http/exception/InsufficentStorage_Test.java    |   3 +-
 .../http/exception/InternalServerError_Test.java   |   3 +-
 .../juneau/http/exception/LengthRequired_Test.java |   3 +-
 .../apache/juneau/http/exception/Locked_Test.java  |   3 +-
 .../juneau/http/exception/LoopDetected_Test.java   |   3 +-
 .../http/exception/MethodNotAllowed_Test.java      |   3 +-
 .../http/exception/MisdirectedRequest_Test.java    |   3 +-
 .../NetworkAuthenticationRequired_Test.java        |   3 +-
 .../juneau/http/exception/NotAcceptable_Test.java  |   3 +-
 .../juneau/http/exception/NotExtended_Test.java    |   3 +-
 .../juneau/http/exception/NotFound_Test.java       |   3 +-
 .../juneau/http/exception/NotImplemented_Test.java |   3 +-
 .../http/exception/PayloadTooLarge_Test.java       |   3 +-
 .../http/exception/PreconditionFailed_Test.java    |   3 +-
 .../http/exception/PreconditionRequired_Test.java  |   3 +-
 .../http/exception/RangeNotSatisfiable_Test.java   |   3 +-
 .../RequestHeaderFieldsTooLarge_Test.java          |   3 +-
 .../http/exception/ServiceUnavailable_Test.java    |   3 +-
 .../http/exception/TooManyRequests_Test.java       |   3 +-
 .../juneau/http/exception/Unauthorized_Test.java   |   3 +-
 .../exception/UnavailableForLegalReasons_Test.java |   3 +-
 .../http/exception/UnprocessableEntity_Test.java   |   3 +-
 .../http/exception/UnsupportedMediaType_Test.java  |   3 +-
 .../http/exception/UpgradeRequired_Test.java       |   3 +-
 .../juneau/http/exception/UriTooLong_Test.java     |   3 +-
 .../http/exception/VariantAlsoNegotiates_Test.java |   3 +-
 .../http/remote/Remote_CommonInterfaces_Test.java  |  67 +--
 .../org/apache/juneau/rest/RestOp_Throws_Test.java |   2 +-
 .../apache/juneau/rest/client/RestClient_Test.java |   4 +-
 105 files changed, 4077 insertions(+), 1907 deletions(-)

diff --git a/TODO.txt b/TODO.txt
index 998379f..d6bafa4 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -9,4 +9,6 @@ HttpException should use list of Headers and have a headers(Header...) method.
 
 JsonSchema should have fluent getters and setters.
 Break out @Response bean handling into it's own handler.
+Can HeaderGroup be used universally?
 
+@ResponseBody and @ResponseHeaders shouldn't be required on HttpResponse objects.
diff --git a/juneau-all/src/java/main/ConfigurablePropertyCodeGenerator.java b/juneau-all/src/java/main/ConfigurablePropertyCodeGenerator.java
index a99746a..2b9030c 100644
--- a/juneau-all/src/java/main/ConfigurablePropertyCodeGenerator.java
+++ b/juneau-all/src/java/main/ConfigurablePropertyCodeGenerator.java
@@ -59,13 +59,14 @@ public class ConfigurablePropertyCodeGenerator {
 		AnnotationBuilder.class,
 		ArrayAssertion.class,
 		Assertion.class,
-		BadRequest.class,
 		BasicHeader.class,
+		BasicHeaderGroupBuilder.class,
 		BasicHttpEntity.class,
 		BasicHttpResource.class,
 		BasicLocationHttpResponse.class,
 		BasicNameValuePair.class,
-		BasicRuntimeException.class,
+		BasicRuntimeExceptionBuilder.class,
+		BasicStatusLineBuilder.class,
 		BeanAssertion.class,
 		BeanContextBuilder.class,
 		BeanStoreBuilder.class,
@@ -80,7 +81,6 @@ public class ConfigurablePropertyCodeGenerator {
 		ConfigFileStoreBuilder.class,
 		ConfigMemoryStoreBuilder.class,
 		ConfigStoreBuilder.class,
-		Conflict.class,
 		ConstructorInfo.class,
 		ContextBuilder.class,
 		Continue.class,
@@ -90,8 +90,6 @@ public class ConfigurablePropertyCodeGenerator {
 		DateAssertion.class,
 		EarlyHints.class,
 		ExecutableInfo.class,
-		ExpectationFailed.class,
-		FailedDependency.class,
 		FileFinderBuilder.class,
 		FluentArrayAssertion.class,
 		FluentAssertion.class,
@@ -118,52 +116,37 @@ public class ConfigurablePropertyCodeGenerator {
 		FluentStringAssertion.class,
 		FluentThrowableAssertion.class,
 		FluentZonedDateTimeAssertion.class,
-		Forbidden.class,
 		Found.class,
-		Gone.class,
 		HtmlDocSerializerBuilder.class,
 		HtmlParserBuilder.class,
 		HtmlSchemaSerializerBuilder.class,
 		HtmlSerializerBuilder.class,
 		HtmlStrippedDocSerializerBuilder.class,
-		HttpException.class,
+		HttpExceptionBuilder.class,
 		BasicHttpResponse.class,
-		HttpVersionNotSupported.class,
 		IMUsed.class,
 		InputStreamParserBuilder.class,
-		InsufficientStorage.class,
 		IntegerAssertion.class,
-		InternalServerError.class,
 		JsonParserBuilder.class,
 		JsonSchemaGeneratorBuilder.class,
 		JsonSchemaSerializerBuilder.class,
 		JsonSerializerBuilder.class,
 		JsoParserBuilder.class,
 		JsoSerializerBuilder.class,
-		LengthRequired.class,
 		ListAssertion.class,
-		Locked.class,
 		LongAssertion.class,
-		LoopDetected.class,
 		MapAssertion.class,
 		MethodExecStatsBuilder.class,
 		MethodExecStoreBuilder.class,
 		MethodInfo.class,
-		MethodNotAllowed.class,
-		MisdirectedRequest.class,
 		MockRestClientBuilder.class,
 		MovedPermanently.class,
 		MsgPackParserBuilder.class,
 		MsgPackSerializerBuilder.class,
 		MultipleChoices.class,
 		MultiStatus.class,
-		NetworkAuthenticationRequired.class,
 		NoContent.class,
 		NonAuthoritiveInformation.class,
-		NotAcceptable.class,
-		NotExtended.class,
-		NotFound.class,
-		NotImplemented.class,
 		NotModified.class,
 		ObjectAssertion.class,
 		Ok.class,
@@ -174,18 +157,13 @@ public class ConfigurablePropertyCodeGenerator {
 		ParserGroupBuilder.class,
 		ParserSessionArgs.class,
 		PartialContent.class,
-		PayloadTooLarge.class,
 		PermanentRedirect.class,
 		PlainTextParserBuilder.class,
 		PlainTextSerializerBuilder.class,
-		PreconditionFailed.class,
-		PreconditionRequired.class,
 		Processing.class,
-		RangeNotSatisfiable.class,
 		RdfParserBuilder.class,
 		RdfSerializerBuilder.class,
 		ReaderParserBuilder.class,
-		RequestHeaderFieldsTooLarge.class,
 		RequestHttpPart.class,
 		ResetContent.class,
 		RestClientBuilder.class,
@@ -198,7 +176,6 @@ public class ConfigurablePropertyCodeGenerator {
 		SerializerBuilder.class,
 		SerializerGroupBuilder.class,
 		SerializerSessionArgs.class,
-		ServiceUnavailable.class,
 		SessionArgs.class,
 		SimpleJsonParserBuilder.class,
 		SimpleJsonSerializerBuilder.class,
@@ -219,19 +196,11 @@ public class ConfigurablePropertyCodeGenerator {
 		ThrowableAssertion.class,
 		ThrownStatsBuilder.class,
 		ThrownStoreBuilder.class,
-		TooManyRequests.class,
-		Unauthorized.class,
-		UnavailableForLegalReasons.class,
-		UnprocessableEntity.class,
-		UnsupportedMediaType.class,
 		UonParserBuilder.class,
 		UonSerializerBuilder.class,
-		UpgradeRequired.class,
-		UriTooLong.class,
 		UrlEncodingParserBuilder.class,
 		UrlEncodingSerializerBuilder.class,
 		UseProxy.class,
-		VariantAlsoNegotiates.class,
 		WriterSerializerBuilder.class,
 		XmlParserBuilder.class,
 		XmlSerializerBuilder.class,
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BasicRuntimeException.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BasicRuntimeException.java
index 6e070b0..9ac7477 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BasicRuntimeException.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BasicRuntimeException.java
@@ -12,8 +12,6 @@
 // ***************************************************************************************************************************
 package org.apache.juneau;
 
-import static org.apache.juneau.internal.StringUtils.*;
-
 import java.text.*;
 
 import org.apache.juneau.internal.*;
@@ -21,19 +19,29 @@ import org.apache.juneau.internal.*;
 /**
  * Subclass of runtime exceptions that take in a message and zero or more arguments.
  */
-@FluentSetters
 public class BasicRuntimeException extends RuntimeException {
 
 	private static final long serialVersionUID = 1L;
 
+	final boolean unmodifiable;
+
+	/**
+	 * Creates a new builder for this bean.
+	 *
+	 * @return A new builder for this bean.
+	 */
+	public static BasicRuntimeExceptionBuilder create() {
+		return new BasicRuntimeExceptionBuilder();
+	}
+
 	/**
 	 * Constructor.
 	 *
-	 * @param message The {@link MessageFormat}-style message.
-	 * @param args Optional {@link MessageFormat}-style arguments.
+	 * @param builder The builder containing the settings for this exception.
 	 */
-	public BasicRuntimeException(String message, Object...args) {
-		super(format(message, args));
+	public BasicRuntimeException(BasicRuntimeExceptionBuilder builder) {
+		super(builder.message, builder.causedBy);
+		this.unmodifiable = builder.unmodifiable;
 	}
 
 	/**
@@ -44,24 +52,26 @@ public class BasicRuntimeException extends RuntimeException {
 	 * @param args Optional {@link MessageFormat}-style arguments.
 	 */
 	public BasicRuntimeException(Throwable cause, String message, Object...args) {
-		this(getMessage(cause, message, null), args);
-		initCause(cause);
+		this(create().causedBy(cause).message(message, args));
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param message The {@link MessageFormat}-style message.
+	 * @param args Optional {@link MessageFormat}-style arguments.
+	 */
+	public BasicRuntimeException(String message, Object...args) {
+		this(create().message(message, args));
 	}
 
 	/**
-	 * Finds the message.
+	 * Constructor.
 	 *
-	 * @param cause The cause.
-	 * @param msg The message.
-	 * @param def The default value if both above are <jk>null</jk>.
-	 * @return The resolved message.
+	 * @param cause The cause of this exception.
 	 */
-	protected static final String getMessage(Throwable cause, String msg, String def) {
-		if (msg != null)
-			return msg;
-		if (cause != null)
-			return cause.getMessage();
-		return def;
+	public BasicRuntimeException(Throwable cause) {
+		this(create().causedBy(cause));
 	}
 
 	/**
@@ -75,7 +85,37 @@ public class BasicRuntimeException extends RuntimeException {
 		return ThrowableUtils.getCause(c, this);
 	}
 
-	// <FluentSetters>
-
-	// </FluentSetters>
+	@Override /* Throwable */
+	public String getMessage() {
+		String m = super.getMessage();
+		if (m == null && getCause() != null)
+			m = getCause().getMessage();
+		return m;
+	}
+
+	@Override /* Throwable */
+	public synchronized Throwable fillInStackTrace() {
+		assertModifiable();
+		return super.fillInStackTrace();
+	}
+
+	@Override /* Throwable */
+	public synchronized Throwable initCause(Throwable cause) {
+		assertModifiable();
+		return super.initCause(cause);
+	}
+
+	@Override /* Throwable */
+	public void setStackTrace(StackTraceElement[] stackTrace) {
+		assertModifiable();
+		super.setStackTrace(stackTrace);
+	}
+
+	/**
+	 * Throws an {@link UnsupportedOperationException} if the unmodifiable flag is set on this bean.
+	 */
+	protected final void assertModifiable() {
+		if (unmodifiable)
+			throw new UnsupportedOperationException("Bean is read-only");
+	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BasicRuntimeException.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BasicRuntimeExceptionBuilder.java
similarity index 52%
copy from juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BasicRuntimeException.java
copy to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BasicRuntimeExceptionBuilder.java
index 6e070b0..cc807de 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BasicRuntimeException.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BasicRuntimeExceptionBuilder.java
@@ -14,65 +14,67 @@ package org.apache.juneau;
 
 import static org.apache.juneau.internal.StringUtils.*;
 
-import java.text.*;
-
 import org.apache.juneau.internal.*;
 
 /**
- * Subclass of runtime exceptions that take in a message and zero or more arguments.
+ * Builder for {@link BasicRuntimeException} beans.
  */
 @FluentSetters
-public class BasicRuntimeException extends RuntimeException {
+public class BasicRuntimeExceptionBuilder {
 
-	private static final long serialVersionUID = 1L;
+	String message;
+	Throwable causedBy;
+	boolean unmodifiable;
 
 	/**
-	 * Constructor.
+	 * Copies the values from the specified exception.
 	 *
-	 * @param message The {@link MessageFormat}-style message.
-	 * @param args Optional {@link MessageFormat}-style arguments.
+	 * @param value The exception to copy from.
+	 * @return This object (for method chaining).
 	 */
-	public BasicRuntimeException(String message, Object...args) {
-		super(format(message, args));
+	public BasicRuntimeExceptionBuilder copyFrom(BasicRuntimeException value) {
+		message = value.getMessage();
+		causedBy = value.getCause();
+		unmodifiable = value.unmodifiable;
+		return this;
 	}
 
 	/**
-	 * Constructor.
+	 * Specifies the exception message.
 	 *
-	 * @param cause The cause of this exception.
-	 * @param message The {@link MessageFormat}-style message.
-	 * @param args Optional {@link MessageFormat}-style arguments.
+	 * @param msg The exception message.  Can be <jk>null</jk>.
+	 * 	<br>If <jk>null</jk>, then the caused-by message is used if available.
+	 * @param args The exception message arguments.
+	 * @return This object (for method chaining).
 	 */
-	public BasicRuntimeException(Throwable cause, String message, Object...args) {
-		this(getMessage(cause, message, null), args);
-		initCause(cause);
+	@FluentSetter
+	public BasicRuntimeExceptionBuilder message(String msg, Object...args) {
+		message = format(msg, args);
+		return this;
 	}
 
 	/**
-	 * Finds the message.
+	 * Specifies the caused-by exception.
 	 *
-	 * @param cause The cause.
-	 * @param msg The message.
-	 * @param def The default value if both above are <jk>null</jk>.
-	 * @return The resolved message.
+	 * @param value The caused-by exception.  Can be <jk>null</jk>.
+	 * @return This object (for method chaining).
 	 */
-	protected static final String getMessage(Throwable cause, String msg, String def) {
-		if (msg != null)
-			return msg;
-		if (cause != null)
-			return cause.getMessage();
-		return def;
+	@FluentSetter
+	public BasicRuntimeExceptionBuilder causedBy(Throwable value) {
+		causedBy = value;
+		return this;
 	}
 
 	/**
-	 * Same as {@link #getCause()} but searches the throwable chain for an exception of the specified type.
+	 * Specifies whether this exception should be unmodifiable after creation.
 	 *
-	 * @param c The throwable type to search for.
-	 * @param <T> The throwable type to search for.
-	 * @return The exception, or <jk>null</jk> if not found.
+	 * @param value The new value for this flag.
+	 * @return This object (for method chaining).
 	 */
-	public <T extends Throwable> T getCause(Class<T> c) {
-		return ThrowableUtils.getCause(c, this);
+	@FluentSetter
+	public BasicRuntimeExceptionBuilder unmodifiable(boolean value) {
+		unmodifiable = value;
+		return this;
 	}
 
 	// <FluentSetters>
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ConfigException.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ConfigException.java
index f6e52bb..4c981a3 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ConfigException.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ConfigException.java
@@ -28,7 +28,7 @@ public class ConfigException extends BasicRuntimeException {
 	 * @param args Optional {@link MessageFormat}-style arguments.
 	 */
 	public ConfigException(Throwable cause, String message, Object... args) {
-		super(cause, getMessage(cause, message, null), args);
+		super(cause, message, args);
 	}
 
 	/**
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextRuntimeException.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextRuntimeException.java
index b4ac4f9..c910452 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextRuntimeException.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextRuntimeException.java
@@ -29,7 +29,7 @@ public final class ContextRuntimeException extends BasicRuntimeException {
 	 * @param args Optional {@link MessageFormat}-style arguments.
 	 */
 	public ContextRuntimeException(Throwable cause, String message, Object... args) {
-		super(cause, getMessage(cause, message, null), args);
+		super(cause, message, args);
 	}
 
 	/**
@@ -39,7 +39,7 @@ public final class ContextRuntimeException extends BasicRuntimeException {
 	 * @param args Arguments passed in to the {@code String.format()} method.
 	 */
 	public ContextRuntimeException(String message, Object...args) {
-		this(null, message, args);
+		super(message, args);
 	}
 
 	/**
@@ -48,6 +48,6 @@ public final class ContextRuntimeException extends BasicRuntimeException {
 	 * @param cause The initial cause of the exception.
 	 */
 	public ContextRuntimeException(Throwable cause) {
-		this(cause, null);
+		super(cause);
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/InvalidDataConversionException.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/InvalidDataConversionException.java
index 5957339..9e314e7 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/InvalidDataConversionException.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/InvalidDataConversionException.java
@@ -38,7 +38,7 @@ public final class InvalidDataConversionException extends BasicRuntimeException
 	 * @param args Optional {@link MessageFormat}-style arguments.
 	 */
 	public InvalidDataConversionException(Throwable cause, String message, Object... args) {
-		super(cause, getMessage(cause, message, null), args);
+		super(cause, message, args);
 	}
 
 	/**
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicHeaderGroup.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicHeaderGroup.java
new file mode 100644
index 0000000..f87e36b
--- /dev/null
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicHeaderGroup.java
@@ -0,0 +1,228 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.http;
+
+import static java.util.Optional.*;
+
+import java.util.*;
+
+import org.apache.http.*;
+import org.apache.http.message.*;
+import org.apache.http.message.BasicHeader;
+import org.apache.http.util.*;
+
+/**
+ * An unmodifiable group of HTTP headers.
+ *
+ * <p>
+ * Similar to {@link HeaderGroup} but uses a builder-based approach for building header groups.
+ */
+public class BasicHeaderGroup {
+
+	private static final Header[] EMPTY = new Header[] {};
+
+	private final List<Header> headers;
+
+	/**
+	 * Instantiates a new builder for this bean.
+	 *
+	 * @return A new builder.
+	 */
+	public static BasicHeaderGroupBuilder create() {
+		return new BasicHeaderGroupBuilder();
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param builder The builder containing the settings for this bean.
+	 */
+	public BasicHeaderGroup(BasicHeaderGroupBuilder builder) {
+		this.headers = new ArrayList<>(builder.headers);
+	}
+
+	/**
+	 * Returns a builder initialized with the contents of this bean.
+	 *
+	 * @return A new builder object.
+	 */
+	public BasicHeaderGroupBuilder builder() {
+		return create().add(headers);
+	}
+
+	/**
+	 * Gets a header representing all of the header values with the given name.
+	 *
+	 * <p>
+	 * If more that one header with the given name exists the values will be
+	 * combined with a "," as per RFC 2616.
+	 *
+	 * <p>Header name comparison is case insensitive.
+	 *
+	 * @param name The header name.
+	 * @return A header with a condensed value or <jk>null</jk> if no headers by the given name are present
+	 */
+	public Optional<Header> getCondensedHeader(final String name) {
+		Header[] hdrs = getHeaders(name);
+
+		if (hdrs.length == 0)
+			return empty();
+
+		if (hdrs.length == 1)
+			return of(hdrs[0]);
+
+		CharArrayBuffer valueBuffer = new CharArrayBuffer(128);
+		valueBuffer.append(hdrs[0].getValue());
+		for (int i = 1; i < hdrs.length; i++) {
+			valueBuffer.append(", ");
+			valueBuffer.append(hdrs[i].getValue());
+		}
+
+		return of(new BasicHeader(name.toLowerCase(Locale.ROOT), valueBuffer.toString()));
+	}
+
+	/**
+	 * Gets all of the headers with the given name.
+	 *
+	 * <p>
+	 * The returned array maintains the relative order in which the headers were added.
+	 *
+	 * <p>
+	 * Header name comparison is case insensitive.
+	 *
+	 * @param name The header name.
+	 *
+	 * @return An array containing all matching headers, or an empty array if none are found.
+	 */
+	public Header[] getHeaders(final String name) {
+		// HTTPCORE-361 : we don't use the for-each syntax, i.e.
+		//	 for (Header header : headers)
+		// as that creates an Iterator that needs to be garbage-collected
+		List<Header> l = null;
+		for (int i = 0; i < headers.size(); i++) {
+			Header x = headers.get(i);
+			if (x.getName().equalsIgnoreCase(name)) {
+				if (l == null)
+					l = new ArrayList<>();
+				l.add(x);
+			}
+		}
+		return l != null ? l.toArray(new Header[l.size()]) : EMPTY;
+	}
+
+	/**
+	 * Gets the first header with the given name.
+	 *
+	 * <p>
+	 * Header name comparison is case insensitive.
+	 *
+	 * @param name The header name.
+	 * @return The first matching header, never <jk>null</jk>.
+	 */
+	public Optional<Header> getFirstHeader(String name) {
+		// HTTPCORE-361 : we don't use the for-each syntax, i.e.
+		//	 for (Header header : headers)
+		// as that creates an Iterator that needs to be garbage-collected
+		for (int i = 0; i < headers.size(); i++) {
+			Header x = headers.get(i);
+			if (x.getName().equalsIgnoreCase(name))
+				return of(x);
+		}
+		return empty();
+	}
+
+	/**
+	 * Gets the last header with the given name.
+	 *
+	 * <p>
+	 * Header name comparison is case insensitive.
+	 *
+	 * @param name The header name.
+	 * @return The last matching header, never <jk>null</jk>.
+	 */
+	public Optional<Header> getLastHeader(String name) {
+		for (int i = headers.size() - 1; i >= 0; i--) {
+			Header x = headers.get(i);
+			if (x.getName().equalsIgnoreCase(name))
+				return of(x);
+		}
+		return empty();
+	}
+
+	/**
+	 * Gets all of the headers contained within this group.
+	 *
+	 * @return An array containing all the headers within this group, or an empty array if no headers are present.
+	 */
+	public Header[] getAllHeaders() {
+		return headers.toArray(new Header[headers.size()]);
+	}
+
+	/**
+	 * Tests if headers with the given name are contained within this group.
+	 *
+	 * <p>
+	 * Header name comparison is case insensitive.
+	 *
+	 * @param name The header name.
+	 * @return <jk>true</jk> if at least one header with the name is present.
+	 */
+	public boolean containsHeader(String name) {
+		// HTTPCORE-361 : we don't use the for-each syntax, i.e.
+		//	 for (Header header : headers)
+		// as that creates an Iterator that needs to be garbage-collected
+		for (int i = 0; i < headers.size(); i++) {
+			Header x = headers.get(i);
+			if (x.getName().equalsIgnoreCase(name))
+				return true;
+		}
+		return false;
+	}
+
+	/**
+	 * Returns an iterator over this group of headers.
+	 *
+	 * @return A new iterator over this group of headers.
+	 */
+	public HeaderIterator iterator() {
+		return new BasicListHeaderIterator(this.headers, null);
+	}
+
+	/**
+	 * Returns an iterator over the headers with a given name in this group.
+	 *
+	 * @param name The name of the headers over which to iterate, or <jk>null</jk> for all headers
+	 *
+	 * @return A new iterator over the matching headers in this group.
+	 */
+	public HeaderIterator iterator(String name) {
+		return new BasicListHeaderIterator(headers, name);
+	}
+
+	/**
+	 * Returns a copy of this object.
+	 *
+	 * <p>
+	 * Individual header values are not cloned.
+	 *
+	 * @return A copy of this object.
+	 */
+	public BasicHeaderGroup copy() {
+		return builder().build();
+	}
+
+	@Override /* Object */
+	public String toString() {
+		return headers.toString();
+	}
+}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicHeaderGroupBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicHeaderGroupBuilder.java
new file mode 100644
index 0000000..ddb1c9c
--- /dev/null
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicHeaderGroupBuilder.java
@@ -0,0 +1,251 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.http;
+
+import java.util.*;
+
+import org.apache.http.*;
+import org.apache.juneau.internal.*;
+
+/**
+ * Builder for {@link BasicHeaderGroup} objects.
+ */
+@FluentSetters
+public class BasicHeaderGroupBuilder {
+
+	final List<Header> headers = new ArrayList<>();
+
+	/**
+	 * Constructor.
+	 */
+	public BasicHeaderGroupBuilder() {}
+
+	/**
+	 * Creates a new {@link BasicHeaderGroup} bean based on the contents of this builder.
+	 *
+	 * @return A new {@link BasicHeaderGroup} bean.
+	 */
+	public BasicHeaderGroup build() {
+		return new BasicHeaderGroup(this);
+	}
+
+	/**
+	 * Removes any headers already in this builder.
+	 *
+	 * @return This object (for method chaining).
+	 */
+	@FluentSetter
+	public BasicHeaderGroupBuilder clear() {
+		headers.clear();
+		return this;
+	}
+
+	/**
+	 * Adds the specified header to the end of the headers in this builder.
+	 *
+	 * @param value The header to add.  <jk>null</jk> values are ignored.
+	 * @return This object (for method chaining).
+	 */
+	@FluentSetter
+	public BasicHeaderGroupBuilder add(Header value) {
+		if (value != null)
+			headers.add(value);
+		return this;
+	}
+
+	/**
+	 * Adds the specified header to the end of the headers in this builder.
+	 *
+	 * @param name The header name.
+	 * @param value The header value.
+	 * @return This object (for method chaining).
+	 */
+	@FluentSetter
+	public BasicHeaderGroupBuilder add(String name, String value) {
+		headers.add(new BasicHeader(name, value));
+		return this;
+	}
+
+	/**
+	 * Adds the specified headers to the end of the headers in this builder.
+	 *
+	 * @param values The headers to add.  <jk>null</jk> values are ignored.
+	 * @return This object (for method chaining).
+	 */
+	@FluentSetter
+	public BasicHeaderGroupBuilder add(Header...values) {
+		for (int i = 0; i < values.length; i++) /* See HTTPCORE-361 */
+			add(values[i]);
+		return this;
+	}
+
+	/**
+	 * Adds the specified headers to the end of the headers in this builder.
+	 *
+	 * @param values The headers to add.  <jk>null</jk> values are ignored.
+	 * @return This object (for method chaining).
+	 */
+	@FluentSetter
+	public BasicHeaderGroupBuilder add(List<Header> values) {
+		for (int i = 0; i < values.size(); i++) /* See HTTPCORE-361 */
+			add(values.get(i));
+		return this;
+	}
+
+	/**
+	 * Removes the specified header from this builder.
+	 *
+	 * @param value The header to remove.  <jk>null</jk> values are ignored.
+	 * @return This object (for method chaining).
+	 */
+	@FluentSetter
+	public BasicHeaderGroupBuilder remove(Header value) {
+		if (value != null)
+			headers.remove(value);
+		return this;
+	}
+
+	/**
+	 * Removes the specified headers from this builder.
+	 *
+	 * @param values The headers to remove.  <jk>null</jk> values are ignored.
+	 * @return This object (for method chaining).
+	 */
+	@FluentSetter
+	public BasicHeaderGroupBuilder remove(Header...values) {
+		for (int i = 0; i < values.length; i++) /* See HTTPCORE-361 */
+			remove(values[i]);
+		return this;
+	}
+
+	/**
+	 * Removes the specified headers from this builder.
+	 *
+	 * @param values The headers to remove.  <jk>null</jk> values are ignored.
+	 * @return This object (for method chaining).
+	 */
+	@FluentSetter
+	public BasicHeaderGroupBuilder remove(List<Header> values) {
+		for (int i = 0; i < values.size(); i++) /* See HTTPCORE-361 */
+			remove(values.get(i));
+		return this;
+	}
+
+	/**
+	 * Removes the header with the specified name from this builder.
+	 *
+	 * @param name The header name.
+	 * @return This object (for method chaining).
+	 */
+	@FluentSetter
+	public BasicHeaderGroupBuilder remove(String name) {
+		for (int i = 0; i < headers.size(); i++) /* See HTTPCORE-361 */
+			if (headers.get(i).getName().equalsIgnoreCase(name))
+				headers.remove(i--);
+		return null;
+	}
+
+	/**
+	 * Replaces the first occurrence of the header with the same name.
+	 *
+	 * <p>
+	 * If no header with the same name is found the given header is added to the end of the list.
+	 *
+	 * @param value The headers to replace.  <jk>null</jk> values are ignored.
+	 * @return This object (for method chaining).
+	 */
+	@FluentSetter
+	public BasicHeaderGroupBuilder update(Header value) {
+		if (value == null)
+			return this;
+
+		for (int i = 0; i < headers.size(); i++) {
+			Header x = headers.get(i);
+			if (x.getName().equalsIgnoreCase(value.getName())) {
+				headers.set(i, value);
+				return this;
+			}
+		}
+
+		headers.add(value);
+		return this;
+	}
+
+	/**
+	 * Replaces the first occurrence of the headers with the same name.
+	 *
+	 * <p>
+	 * If no header with the same name is found the given header is added to the end of the list.
+	 *
+	 * @param values The headers to replace.  <jk>null</jk> values are ignored.
+	 * @return This object (for method chaining).
+	 */
+	@FluentSetter
+	public BasicHeaderGroupBuilder update(Header...values) {
+		for (int i = 0; i < values.length; i++) /* See HTTPCORE-361 */
+			update(values[i]);
+		return this;
+	}
+
+	/**
+	 * Replaces the first occurrence of the headers with the same name.
+	 *
+	 * <p>
+	 * If no header with the same name is found the given header is added to the end of the list.
+	 *
+	 * @param values The headers to replace.  <jk>null</jk> values are ignored.
+	 * @return This object (for method chaining).
+	 */
+	@FluentSetter
+	public BasicHeaderGroupBuilder update(List<Header> values) {
+		for (int i = 0; i < values.size(); i++) /* See HTTPCORE-361 */
+			update(values.get(i));
+		return this;
+	}
+
+	/**
+	 * Sets all of the headers contained within this group overriding any existing headers.
+	 *
+	 * <p>
+	 * The headers are added in the order in which they appear in the array.
+	 *
+	 * @param values The headers to set
+	 * @return This object (for method chaining).
+	 */
+	@FluentSetter
+	public BasicHeaderGroupBuilder set(Header...values) {
+		clear();
+		Collections.addAll(headers, values);
+		return this;
+	}
+
+	/**
+	 * Sets all of the headers contained within this group overriding any existing headers.
+	 *
+	 * <p>
+	 * The headers are added in the order in which they appear in the list.
+	 *
+	 * @param values The headers to set
+	 * @return This object (for method chaining).
+	 */
+	@FluentSetter
+	public BasicHeaderGroupBuilder set(List<Header> values) {
+		clear();
+		headers.addAll(values);
+		return this;
+	}
+
+	// <FluentSetters>
+
+	// </FluentSetters>
+}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicStatusLine.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicStatusLine.java
new file mode 100644
index 0000000..6e7f1cd
--- /dev/null
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicStatusLine.java
@@ -0,0 +1,93 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.http;
+
+import static org.apache.juneau.internal.ObjectUtils.*;
+
+import java.util.*;
+
+import org.apache.http.*;
+import org.apache.http.impl.*;
+
+/**
+ * A basic implementation of the {@link StatusLine} interface.
+ */
+public class BasicStatusLine implements StatusLine {
+
+	private ProtocolVersion DEFAULT_PROTOCOL_VERSION = new ProtocolVersion("HTTP", 1, 1);
+
+	private final ProtocolVersion protocolVersion;
+	private final int statusCode;
+	private final String reasonPhrase;
+	private final Locale locale;
+
+	/**
+	 * Instantiates a new builder for this bean.
+	 *
+	 * @return A new builder.
+	 */
+	public static BasicStatusLineBuilder create() {
+		return new BasicStatusLineBuilder();
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param builder The builder containing the settings for this bean.
+	 */
+	public BasicStatusLine(BasicStatusLineBuilder builder) {
+		this.protocolVersion = firstNonNull(builder.protocolVersion, DEFAULT_PROTOCOL_VERSION);
+		this.statusCode = firstNonNull(builder.statusCode, 0);
+		this.locale = firstNonNull(builder.locale, Locale.getDefault());
+
+		String reasonPhrase = builder.reasonPhrase;
+		if (reasonPhrase == null) {
+			ReasonPhraseCatalog rfc = firstNonNull(builder.reasonPhraseCatalog, EnglishReasonPhraseCatalog.INSTANCE);
+			reasonPhrase = rfc.getReason(statusCode, locale);
+		}
+		this.reasonPhrase = reasonPhrase;
+	}
+
+	/**
+	 * Returns a builder initialized with the contents of this bean.
+	 *
+	 * @return A new builder object.
+	 */
+	public BasicStatusLineBuilder builder() {
+		return create().protocolVersion(protocolVersion).statusCode(statusCode).reasonPhrase(reasonPhrase);
+	}
+
+	@Override /* StatusLine */
+	public ProtocolVersion getProtocolVersion() {
+		return protocolVersion;
+	}
+
+	@Override /* StatusLine */
+	public int getStatusCode() {
+		return statusCode;
+	}
+
+	@Override /* StatusLine */
+	public String getReasonPhrase() {
+		return reasonPhrase;
+	}
+
+	/**
+	 * Returns the locale of this status line.
+	 *
+	 * @return The locale of this status line.
+	 */
+	public Locale getLocale() {
+		return locale;
+	}
+}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicStatusLineBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicStatusLineBuilder.java
new file mode 100644
index 0000000..702178e
--- /dev/null
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicStatusLineBuilder.java
@@ -0,0 +1,126 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.http;
+
+import java.util.*;
+
+import org.apache.http.*;
+import org.apache.http.impl.*;
+import org.apache.juneau.internal.*;
+
+/**
+ * Builder class for {@link BasicStatusLine} beans.
+ */
+@FluentSetters
+public class BasicStatusLineBuilder {
+
+	ProtocolVersion protocolVersion;
+	Integer statusCode;
+	String reasonPhrase;
+	Locale locale;
+	ReasonPhraseCatalog reasonPhraseCatalog;
+
+	/**
+	 * Constructor.
+	 */
+	public BasicStatusLineBuilder() {}
+
+	/**
+	 * Creates a new {@link BasicStatusLine} bean based on the contents of this builder.
+	 *
+	 * @return A new {@link BasicStatusLine} bean.
+	 */
+	public BasicStatusLine build() {
+		return new BasicStatusLine(this);
+	}
+
+	/**
+	 * Sets the protocol version on the status line.
+	 *
+	 * <p>
+	 * If not specified, <js>"HTTP/1.1"</js> will be used.
+	 *
+	 * @param value The new value.
+	 * @return This object (for method chaining).
+	 */
+	@FluentSetter
+	public BasicStatusLineBuilder protocolVersion(ProtocolVersion value) {
+		this.protocolVersion = value;
+		return this;
+	}
+
+	/**
+	 * Sets the status code on the status line.
+	 *
+	 * <p>
+	 * If not specified, <c>0</c> will be used.
+	 *
+	 * @param value The new value.
+	 * @return This object (for method chaining).
+	 */
+	@FluentSetter
+	public BasicStatusLineBuilder statusCode(int value) {
+		this.statusCode = value;
+		return this;
+	}
+
+	/**
+	 * Sets the reason phrase on the status line.
+	 *
+	 * <p>
+	 * If not specified, the reason phrase will be retrieved from the reason phrase catalog
+	 * using the locale on this builder.
+	 *
+	 * @param value The new value.
+	 * @return This object (for method chaining).
+	 */
+	@FluentSetter
+	public BasicStatusLineBuilder reasonPhrase(String value) {
+		this.reasonPhrase = value;
+		return this;
+	}
+
+	/**
+	 * Sets the reason phrase catalog used to retrieve reason phrases.
+	 *
+	 * <p>
+	 * If not specified, uses {@link EnglishReasonPhraseCatalog}.
+	 *
+	 * @param value The new value.
+	 * @return This object (for method chaining).
+	 */
+	@FluentSetter
+	public BasicStatusLineBuilder reasonPhraseCatalog(ReasonPhraseCatalog value) {
+		this.reasonPhraseCatalog = value;
+		return this;
+	}
+
+	/**
+	 * Sets the locale used to retrieve reason phrases.
+	 *
+	 * <p>
+	 * If not specified, uses {@link Locale#getDefault()}.
+	 *
+	 * @param value The new value.
+	 * @return This object (for method chaining).
+	 */
+	@FluentSetter
+	public BasicStatusLineBuilder locale(Locale value) {
+		this.locale = value;
+		return this;
+	}
+
+	// <FluentSetters>
+
+	// </FluentSetters>
+}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/BadRequest.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/BadRequest.java
index f87cdea..e11b756 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/BadRequest.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/BadRequest.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.http.exception.BadRequest.*;
 import java.text.*;
 
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Exception representing an HTTP 400 (Bad Request).
@@ -26,7 +25,6 @@ import org.apache.juneau.internal.*;
  * The server cannot or will not process the request due to an apparent client error (e.g., malformed request syntax, size too large, invalid request message framing, or deceptive request routing).
  */
 @Response(code=STATUS_CODE, description=REASON_PHRASE)
-@FluentSetters
 public class BadRequest extends HttpException {
 	private static final long serialVersionUID = 1L;
 
@@ -36,31 +34,52 @@ public class BadRequest extends HttpException {
 	/** Reason phrase */
 	public static final String REASON_PHRASE = "Bad Request";
 
+	/** Reusable unmodifiable instance. */
+	public static final BadRequest INSTANCE = create().unmodifiable(true).build();
+
+	/**
+	 * Creates a builder for this class.
+	 *
+	 * @return A new builder bean.
+	 */
+	public static HttpExceptionBuilder<BadRequest> create() {
+		return new HttpExceptionBuilder<>(BadRequest.class).statusCode(STATUS_CODE).reasonPhrase(REASON_PHRASE);
+	}
+
 	/**
 	 * Constructor.
 	 *
-	 * @param cause The cause.  Can be <jk>null</jk>.
-	 * @param msg The message.  Can be <jk>null</jk>.
-	 * @param args Optional {@link MessageFormat}-style arguments in the message.
+	 * @param builder The builder containing the settings for this exception.
 	 */
-	public BadRequest(Throwable cause, String msg, Object...args) {
-		super(cause, STATUS_CODE, msg, args);
+	public BadRequest(HttpExceptionBuilder<?> builder) {
+		super(builder);
 	}
 
 	/**
 	 * Constructor.
 	 *
+	 * @param cause The caused-by exception.  Can be <jk>null</jk>.
 	 * @param msg The message.  Can be <jk>null</jk>.
+	 * @param args The message arguments.
 	 */
-	public BadRequest(String msg) {
-		this((Throwable)null, msg);
+	public BadRequest(Throwable cause, String msg, Object...args) {
+		this(create().causedBy(cause).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 */
 	public BadRequest() {
-		this((Throwable)null, REASON_PHRASE);
+		this(create().build());
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param msg The message.  Can be <jk>null</jk>.
+	 */
+	public BadRequest(String msg) {
+		this(create().message(msg));
 	}
 
 	/**
@@ -70,7 +89,7 @@ public class BadRequest extends HttpException {
 	 * @param args Optional {@link MessageFormat}-style arguments in the message.
 	 */
 	public BadRequest(String msg, Object...args) {
-		this(null, msg, args);
+		this(create().message(msg, args));
 	}
 
 	/**
@@ -79,26 +98,15 @@ public class BadRequest extends HttpException {
 	 * @param cause The cause.  Can be <jk>null</jk>.
 	 */
 	public BadRequest(Throwable cause) {
-		this(cause, null);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Fluent setters.
-	//------------------------------------------------------------------------------------------------------------------
-
-	// <FluentSetters>
-
-	@Override /* GENERATED - HttpException */
-	public BadRequest header(String name, Object val) {
-		super.header(name, val);
-		return this;
+		this(create().causedBy(cause));
 	}
 
-	@Override /* GENERATED - HttpException */
-	public BadRequest status(int value) {
-		super.status(value);
-		return this;
+	/**
+	 * Creates a builder for this class initialized with the contents of this bean.
+	 *
+	 * @return A new builder bean.
+	 */
+	public HttpExceptionBuilder<BadRequest> builder() {
+		return super.builder(BadRequest.class).copyFrom(this);
 	}
-
-	// </FluentSetters>
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/Conflict.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/Conflict.java
index b86b11d..d280ced 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/Conflict.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/Conflict.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.http.exception.Conflict.*;
 import java.text.*;
 
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Exception representing an HTTP 409 (Conflict).
@@ -26,7 +25,6 @@ import org.apache.juneau.internal.*;
  * Indicates that the request could not be processed because of conflict in the request, such as an edit conflict between multiple simultaneous updates.
  */
 @Response(code=STATUS_CODE, description=REASON_PHRASE)
-@FluentSetters
 public class Conflict extends HttpException {
 	private static final long serialVersionUID = 1L;
 
@@ -36,31 +34,52 @@ public class Conflict extends HttpException {
 	/** Reason phrase */
 	public static final String REASON_PHRASE = "Conflict";
 
+	/** Reusable unmodifiable instance. */
+	public static final Conflict INSTANCE = create().unmodifiable(true).build();
+
+	/**
+	 * Creates a builder for this class.
+	 *
+	 * @return A new builder bean.
+	 */
+	public static HttpExceptionBuilder<Conflict> create() {
+		return new HttpExceptionBuilder<>(Conflict.class).statusCode(STATUS_CODE).reasonPhrase(REASON_PHRASE);
+	}
+
 	/**
 	 * Constructor.
 	 *
-	 * @param cause The cause.  Can be <jk>null</jk>.
-	 * @param msg The message.  Can be <jk>null</jk>.
-	 * @param args Optional {@link MessageFormat}-style arguments in the message.
+	 * @param builder The builder containing the settings for this exception.
 	 */
-	public Conflict(Throwable cause, String msg, Object...args) {
-		super(cause, STATUS_CODE, msg, args);
+	public Conflict(HttpExceptionBuilder<?> builder) {
+		super(builder);
 	}
 
 	/**
 	 * Constructor.
 	 *
+	 * @param cause The caused-by exception.  Can be <jk>null</jk>.
 	 * @param msg The message.  Can be <jk>null</jk>.
+	 * @param args The message arguments.
 	 */
-	public Conflict(String msg) {
-		this((Throwable)null, msg);
+	public Conflict(Throwable cause, String msg, Object...args) {
+		this(create().causedBy(cause).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 */
 	public Conflict() {
-		this((Throwable)null, REASON_PHRASE);
+		this(create().build());
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param msg The message.  Can be <jk>null</jk>.
+	 */
+	public Conflict(String msg) {
+		this(create().message(msg));
 	}
 
 	/**
@@ -70,7 +89,7 @@ public class Conflict extends HttpException {
 	 * @param args Optional {@link MessageFormat}-style arguments in the message.
 	 */
 	public Conflict(String msg, Object...args) {
-		this(null, msg, args);
+		this(create().message(msg, args));
 	}
 
 	/**
@@ -79,26 +98,15 @@ public class Conflict extends HttpException {
 	 * @param cause The cause.  Can be <jk>null</jk>.
 	 */
 	public Conflict(Throwable cause) {
-		this(cause, null);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Fluent setters.
-	//------------------------------------------------------------------------------------------------------------------
-
-	// <FluentSetters>
-
-	@Override /* GENERATED - HttpException */
-	public Conflict header(String name, Object val) {
-		super.header(name, val);
-		return this;
+		this(create().causedBy(cause));
 	}
 
-	@Override /* GENERATED - HttpException */
-	public Conflict status(int value) {
-		super.status(value);
-		return this;
+	/**
+	 * Creates a builder for this class initialized with the contents of this bean.
+	 *
+	 * @return A new builder bean.
+	 */
+	public HttpExceptionBuilder<Conflict> builder() {
+		return super.builder(Conflict.class).copyFrom(this);
 	}
-
-	// </FluentSetters>
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/ExpectationFailed.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/ExpectationFailed.java
index 1bc7ea2..332d492 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/ExpectationFailed.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/ExpectationFailed.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.http.exception.ExpectationFailed.*;
 import java.text.*;
 
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Exception representing an HTTP 417 (Expectation Failed).
@@ -26,7 +25,6 @@ import org.apache.juneau.internal.*;
  * The server cannot meet the requirements of the Expect request-header field.
  */
 @Response(code=STATUS_CODE, description=REASON_PHRASE)
-@FluentSetters
 public class ExpectationFailed extends HttpException {
 	private static final long serialVersionUID = 1L;
 
@@ -36,31 +34,52 @@ public class ExpectationFailed extends HttpException {
 	/** Reason phrase */
 	public static final String REASON_PHRASE = "Expectation Failed";
 
+	/** Reusable unmodifiable instance. */
+	public static final ExpectationFailed INSTANCE = create().unmodifiable(true).build();
+
+	/**
+	 * Creates a builder for this class.
+	 *
+	 * @return A new builder bean.
+	 */
+	public static HttpExceptionBuilder<ExpectationFailed> create() {
+		return new HttpExceptionBuilder<>(ExpectationFailed.class).statusCode(STATUS_CODE).reasonPhrase(REASON_PHRASE);
+	}
+
 	/**
 	 * Constructor.
 	 *
-	 * @param cause The cause.  Can be <jk>null</jk>.
-	 * @param msg The message.  Can be <jk>null</jk>.
-	 * @param args Optional {@link MessageFormat}-style arguments in the message.
+	 * @param builder The builder containing the settings for this exception.
 	 */
-	public ExpectationFailed(Throwable cause, String msg, Object...args) {
-		super(cause, STATUS_CODE, msg, args);
+	public ExpectationFailed(HttpExceptionBuilder<?> builder) {
+		super(builder);
 	}
 
 	/**
 	 * Constructor.
 	 *
+	 * @param cause The caused-by exception.  Can be <jk>null</jk>.
 	 * @param msg The message.  Can be <jk>null</jk>.
+	 * @param args The message arguments.
 	 */
-	public ExpectationFailed(String msg) {
-		this((Throwable)null, msg);
+	public ExpectationFailed(Throwable cause, String msg, Object...args) {
+		this(create().causedBy(cause).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 */
 	public ExpectationFailed() {
-		this((Throwable)null, REASON_PHRASE);
+		this(create().build());
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param msg The message.  Can be <jk>null</jk>.
+	 */
+	public ExpectationFailed(String msg) {
+		this(create().message(msg));
 	}
 
 	/**
@@ -70,7 +89,7 @@ public class ExpectationFailed extends HttpException {
 	 * @param args Optional {@link MessageFormat}-style arguments in the message.
 	 */
 	public ExpectationFailed(String msg, Object...args) {
-		this(null, msg, args);
+		this(create().message(msg, args));
 	}
 
 	/**
@@ -79,26 +98,15 @@ public class ExpectationFailed extends HttpException {
 	 * @param cause The cause.  Can be <jk>null</jk>.
 	 */
 	public ExpectationFailed(Throwable cause) {
-		this(cause, null);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Fluent setters.
-	//------------------------------------------------------------------------------------------------------------------
-
-	// <FluentSetters>
-
-	@Override /* GENERATED - HttpException */
-	public ExpectationFailed header(String name, Object val) {
-		super.header(name, val);
-		return this;
+		this(create().causedBy(cause));
 	}
 
-	@Override /* GENERATED - HttpException */
-	public ExpectationFailed status(int value) {
-		super.status(value);
-		return this;
+	/**
+	 * Creates a builder for this class initialized with the contents of this bean.
+	 *
+	 * @return A new builder bean.
+	 */
+	public HttpExceptionBuilder<ExpectationFailed> builder() {
+		return super.builder(ExpectationFailed.class).copyFrom(this);
 	}
-
-	// </FluentSetters>
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/FailedDependency.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/FailedDependency.java
index 565f7aa..036c34b 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/FailedDependency.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/FailedDependency.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.http.exception.FailedDependency.*;
 import java.text.*;
 
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Exception representing an HTTP 424 (Failed Dependency).
@@ -26,7 +25,6 @@ import org.apache.juneau.internal.*;
  * The request failed because it depended on another request and that request failed (e.g., a PROPPATCH).
  */
 @Response(code=STATUS_CODE, description=REASON_PHRASE)
-@FluentSetters
 public class FailedDependency extends HttpException {
 	private static final long serialVersionUID = 1L;
 
@@ -36,31 +34,52 @@ public class FailedDependency extends HttpException {
 	/** Reason phrase */
 	public static final String REASON_PHRASE = "Failed Dependency";
 
+	/** Reusable unmodifiable instance. */
+	public static final FailedDependency INSTANCE = create().unmodifiable(true).build();
+
+	/**
+	 * Creates a builder for this class.
+	 *
+	 * @return A new builder bean.
+	 */
+	public static HttpExceptionBuilder<FailedDependency> create() {
+		return new HttpExceptionBuilder<>(FailedDependency.class).statusCode(STATUS_CODE).reasonPhrase(REASON_PHRASE);
+	}
+
 	/**
 	 * Constructor.
 	 *
-	 * @param cause The cause.  Can be <jk>null</jk>.
-	 * @param msg The message.  Can be <jk>null</jk>.
-	 * @param args Optional {@link MessageFormat}-style arguments in the message.
+	 * @param builder The builder containing the settings for this exception.
 	 */
-	public FailedDependency(Throwable cause, String msg, Object...args) {
-		super(cause, STATUS_CODE, msg, args);
+	public FailedDependency(HttpExceptionBuilder<?> builder) {
+		super(builder);
 	}
 
 	/**
 	 * Constructor.
 	 *
+	 * @param cause The caused-by exception.  Can be <jk>null</jk>.
 	 * @param msg The message.  Can be <jk>null</jk>.
+	 * @param args The message arguments.
 	 */
-	public FailedDependency(String msg) {
-		this((Throwable)null, msg);
+	public FailedDependency(Throwable cause, String msg, Object...args) {
+		this(create().causedBy(cause).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 */
 	public FailedDependency() {
-		this((Throwable)null, REASON_PHRASE);
+		this(create().build());
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param msg The message.  Can be <jk>null</jk>.
+	 */
+	public FailedDependency(String msg) {
+		this(create().message(msg));
 	}
 
 	/**
@@ -70,7 +89,7 @@ public class FailedDependency extends HttpException {
 	 * @param args Optional {@link MessageFormat}-style arguments in the message.
 	 */
 	public FailedDependency(String msg, Object...args) {
-		this(null, msg, args);
+		this(create().message(msg, args));
 	}
 
 	/**
@@ -79,26 +98,15 @@ public class FailedDependency extends HttpException {
 	 * @param cause The cause.  Can be <jk>null</jk>.
 	 */
 	public FailedDependency(Throwable cause) {
-		this(cause, null);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Fluent setters.
-	//------------------------------------------------------------------------------------------------------------------
-
-	// <FluentSetters>
-
-	@Override /* GENERATED - HttpException */
-	public FailedDependency header(String name, Object val) {
-		super.header(name, val);
-		return this;
+		this(create().causedBy(cause));
 	}
 
-	@Override /* GENERATED - HttpException */
-	public FailedDependency status(int value) {
-		super.status(value);
-		return this;
+	/**
+	 * Creates a builder for this class initialized with the contents of this bean.
+	 *
+	 * @return A new builder bean.
+	 */
+	public HttpExceptionBuilder<FailedDependency> builder() {
+		return super.builder(FailedDependency.class).copyFrom(this);
 	}
-
-	// </FluentSetters>
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/Forbidden.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/Forbidden.java
index 46c1167..70f249e 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/Forbidden.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/Forbidden.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.http.exception.Forbidden.*;
 import java.text.*;
 
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Exception representing an HTTP 403 (Forbidden).
@@ -27,7 +26,6 @@ import org.apache.juneau.internal.*;
  * <br>The user might not have the necessary permissions for a resource, or may need an account of some sort.
  */
 @Response(code=STATUS_CODE, description=REASON_PHRASE)
-@FluentSetters
 public class Forbidden extends HttpException {
 	private static final long serialVersionUID = 1L;
 
@@ -37,31 +35,52 @@ public class Forbidden extends HttpException {
 	/** Reason phrase */
 	public static final String REASON_PHRASE = "Forbidden";
 
+	/** Reusable unmodifiable instance. */
+	public static final Forbidden INSTANCE = create().unmodifiable(true).build();
+
+	/**
+	 * Creates a builder for this class.
+	 *
+	 * @return A new builder bean.
+	 */
+	public static HttpExceptionBuilder<Forbidden> create() {
+		return new HttpExceptionBuilder<>(Forbidden.class).statusCode(STATUS_CODE).reasonPhrase(REASON_PHRASE);
+	}
+
 	/**
 	 * Constructor.
 	 *
-	 * @param cause The cause.  Can be <jk>null</jk>.
-	 * @param msg The message.  Can be <jk>null</jk>.
-	 * @param args Optional {@link MessageFormat}-style arguments in the message.
+	 * @param builder The builder containing the settings for this exception.
 	 */
-	public Forbidden(Throwable cause, String msg, Object...args) {
-		super(cause, STATUS_CODE, msg, args);
+	public Forbidden(HttpExceptionBuilder<?> builder) {
+		super(builder);
 	}
 
 	/**
 	 * Constructor.
 	 *
+	 * @param cause The caused-by exception.  Can be <jk>null</jk>.
 	 * @param msg The message.  Can be <jk>null</jk>.
+	 * @param args The message arguments.
 	 */
-	public Forbidden(String msg) {
-		this((Throwable)null, msg);
+	public Forbidden(Throwable cause, String msg, Object...args) {
+		this(create().causedBy(cause).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 */
 	public Forbidden() {
-		this((Throwable)null, REASON_PHRASE);
+		this(create().build());
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param msg The message.  Can be <jk>null</jk>.
+	 */
+	public Forbidden(String msg) {
+		this(create().message(msg));
 	}
 
 	/**
@@ -71,7 +90,7 @@ public class Forbidden extends HttpException {
 	 * @param args Optional {@link MessageFormat}-style arguments in the message.
 	 */
 	public Forbidden(String msg, Object...args) {
-		this(null, msg, args);
+		this(create().message(msg, args));
 	}
 
 	/**
@@ -80,26 +99,15 @@ public class Forbidden extends HttpException {
 	 * @param cause The cause.  Can be <jk>null</jk>.
 	 */
 	public Forbidden(Throwable cause) {
-		this(cause, null);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Fluent setters.
-	//------------------------------------------------------------------------------------------------------------------
-
-	// <FluentSetters>
-
-	@Override /* GENERATED - HttpException */
-	public Forbidden header(String name, Object val) {
-		super.header(name, val);
-		return this;
+		this(create().causedBy(cause));
 	}
 
-	@Override /* GENERATED - HttpException */
-	public Forbidden status(int value) {
-		super.status(value);
-		return this;
+	/**
+	 * Creates a builder for this class initialized with the contents of this bean.
+	 *
+	 * @return A new builder bean.
+	 */
+	public HttpExceptionBuilder<Forbidden> builder() {
+		return super.builder(Forbidden.class).copyFrom(this);
 	}
-
-	// </FluentSetters>
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/Gone.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/Gone.java
index 01465fa..eecd2a0 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/Gone.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/Gone.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.http.exception.Gone.*;
 import java.text.*;
 
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Exception representing an HTTP 410 ().
@@ -30,7 +29,6 @@ import org.apache.juneau.internal.*;
  * <br>Most use cases do not require clients and search engines to purge the resource, and a <js>"404 Not Found"</js> may be used instead.
  */
 @Response(code=STATUS_CODE, description=REASON_PHRASE)
-@FluentSetters
 public class Gone extends HttpException {
 	private static final long serialVersionUID = 1L;
 
@@ -40,31 +38,52 @@ public class Gone extends HttpException {
 	/** Reason phrase */
 	public static final String REASON_PHRASE = "Gone";
 
+	/** Reusable unmodifiable instance. */
+	public static final Gone INSTANCE = create().unmodifiable(true).build();
+
+	/**
+	 * Creates a builder for this class.
+	 *
+	 * @return A new builder bean.
+	 */
+	public static HttpExceptionBuilder<Gone> create() {
+		return new HttpExceptionBuilder<>(Gone.class).statusCode(STATUS_CODE).reasonPhrase(REASON_PHRASE);
+	}
+
 	/**
 	 * Constructor.
 	 *
-	 * @param cause The cause.  Can be <jk>null</jk>.
-	 * @param msg The message.  Can be <jk>null</jk>.
-	 * @param args Optional {@link MessageFormat}-style arguments in the message.
+	 * @param builder The builder containing the settings for this exception.
 	 */
-	public Gone(Throwable cause, String msg, Object...args) {
-		super(cause, STATUS_CODE, msg, args);
+	public Gone(HttpExceptionBuilder<?> builder) {
+		super(builder);
 	}
 
 	/**
 	 * Constructor.
 	 *
+	 * @param cause The caused-by exception.  Can be <jk>null</jk>.
 	 * @param msg The message.  Can be <jk>null</jk>.
+	 * @param args The message arguments.
 	 */
-	public Gone(String msg) {
-		this((Throwable)null, msg);
+	public Gone(Throwable cause, String msg, Object...args) {
+		this(create().causedBy(cause).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 */
 	public Gone() {
-		this((Throwable)null, REASON_PHRASE);
+		this(create().build());
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param msg The message.  Can be <jk>null</jk>.
+	 */
+	public Gone(String msg) {
+		this(create().message(msg));
 	}
 
 	/**
@@ -74,7 +93,7 @@ public class Gone extends HttpException {
 	 * @param args Optional {@link MessageFormat}-style arguments in the message.
 	 */
 	public Gone(String msg, Object...args) {
-		this(null, msg, args);
+		this(create().message(msg, args));
 	}
 
 	/**
@@ -83,26 +102,15 @@ public class Gone extends HttpException {
 	 * @param cause The cause.  Can be <jk>null</jk>.
 	 */
 	public Gone(Throwable cause) {
-		this(cause, null);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Fluent setters.
-	//------------------------------------------------------------------------------------------------------------------
-
-	// <FluentSetters>
-
-	@Override /* GENERATED - HttpException */
-	public Gone header(String name, Object val) {
-		super.header(name, val);
-		return this;
+		this(create().causedBy(cause));
 	}
 
-	@Override /* GENERATED - HttpException */
-	public Gone status(int value) {
-		super.status(value);
-		return this;
+	/**
+	 * Creates a builder for this class initialized with the contents of this bean.
+	 *
+	 * @return A new builder bean.
+	 */
+	public HttpExceptionBuilder<Gone> builder() {
+		return super.builder(Gone.class).copyFrom(this);
 	}
-
-	// </FluentSetters>
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/HttpException.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/HttpException.java
index fe6a771..00c5496 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/HttpException.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/HttpException.java
@@ -14,73 +14,111 @@ package org.apache.juneau.http.exception;
 
 import static org.apache.juneau.internal.StringUtils.*;
 
+import java.io.*;
 import java.lang.reflect.*;
 import java.text.*;
 import java.util.*;
 
+import org.apache.http.*;
+import org.apache.http.Header;
+import org.apache.http.entity.*;
+import org.apache.http.params.*;
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
-import org.apache.juneau.collections.*;
+import org.apache.juneau.http.*;
+import org.apache.juneau.http.BasicHeader;
+import org.apache.juneau.http.BasicStatusLine;
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Exception thrown to trigger an error HTTP status.
  *
  * <p>
- * REST methods on subclasses of <c>RestServlet</c> can throw this exception to trigger an HTTP status other than the
- * automatically-generated <c>404</c>, <c>405</c>, and <c>500</c> statuses.
+ * Note that while the {@link HttpResponse} interface allows you to modify the headers and status line on this
+ * bean, it is more efficient to do so in the builder.
  */
 @Response
 @BeanIgnore
-@FluentSetters
-public class HttpException extends BasicRuntimeException {
+public class HttpException extends BasicRuntimeException implements HttpResponse {
 
 	private static final long serialVersionUID = 1L;
 
-	private int status;
-	private AMap<String,Object> headers = AMap.create();
+	BasicHeaderGroup headers;
+	BasicStatusLine statusLine;
+	HttpEntity body;
+
+	/**
+	 * Creates a builder for this class.
+	 *
+	 * @param implClass The subclass that the builder is going to create.
+	 * @return A new builder bean.
+	 */
+	public static <T extends HttpException> HttpExceptionBuilder<T> create(Class<T> implClass) {
+		return new HttpExceptionBuilder<>(implClass);
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param builder The builder containing the arguments for this exception.
+	 */
+	public HttpException(HttpExceptionBuilder<?> builder) {
+		super(builder);
+		headers = builder.headers.build();
+		statusLine = builder.statusLine.build();
+		body = builder.body;
+	}
 
 	/**
 	 * Constructor.
 	 *
-	 * @param cause The cause of this exception.
-	 * @param status The HTTP status code.
-	 * @param msg The status message.
-	 * @param args Optional {@link MessageFormat}-style arguments.
+	 * @param statusCode The HTTP status code.
+	 * @param cause The caused-by exception.  Can be <jk>null</jk>.
+	 * @param msg The message.  Can be <jk>null</jk>.
+	 * @param args The message arguments.
 	 */
-	public HttpException(Throwable cause, int status, String msg, Object...args) {
-		super(cause, message(cause, msg, args));
-		this.status = status;
+	public HttpException(int statusCode, Throwable cause, String msg, Object...args) {
+		this(create(null).statusCode(statusCode).causedBy(cause).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 *
-	 * @param msg The status message.
+	 * @param statusCode The HTTP status code.
 	 */
-	public HttpException(String msg) {
-		this((Throwable)null, 0, msg);
+	public HttpException(int statusCode) {
+		this(create(null).statusCode(statusCode));
 	}
 
 	/**
 	 * Constructor.
-	 * @param cause The root exception.
-	 * @param status The HTTP status code.
+	 *
+	 * @param statusCode The HTTP status code.
+	 * @param msg The message.  Can be <jk>null</jk>.
+	 * @param args Optional {@link MessageFormat}-style arguments in the message.
 	 */
-	public HttpException(Throwable cause, int status) {
-		this(cause, status, null);
+	public HttpException(int statusCode, String msg, Object...args) {
+		this(create(null).statusCode(statusCode).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 *
-	 * @param status The HTTP status code.
-	 * @param msg The status message.
-	 * @param args Optional {@link MessageFormat}-style arguments.
+	 * @param statusCode The HTTP status code.
+	 * @param causedBy The cause.  Can be <jk>null</jk>.
 	 */
-	public HttpException(int status, String msg, Object...args) {
-		this(null, status, msg, args);
+	public HttpException(int statusCode, Throwable causedBy) {
+		this(create(null).statusCode(statusCode).causedBy(causedBy));
+	}
+
+	/**
+	 * Creates a builder for this class initialized with the contents of this exception.
+	 *
+	 * @param implClass The subclass that the builder is going to create.
+	 * @return A new builder bean.
+	 */
+	public <T extends HttpException> HttpExceptionBuilder<T> builder(Class<T> implClass) {
+		return create(implClass).copyFrom(this);
 	}
 
 	/**
@@ -106,6 +144,16 @@ public class HttpException extends BasicRuntimeException {
 	}
 
 	/**
+	 * Returns the HTTP status code of this response.
+	 *
+	 * @return The HTTP status code of this response.
+	 */
+	@ResponseStatus
+	public int getStatusCode() {
+		return statusLine.getStatusCode();
+	}
+
+	/**
 	 * Returns all error messages from all errors in this stack.
 	 *
 	 * <p>
@@ -139,6 +187,16 @@ public class HttpException extends BasicRuntimeException {
 		return sb.toString();
 	}
 
+	@Override /* Throwable */
+	public String getMessage() {
+		String m = super.getMessage();
+		if (m == null && getCause() != null)
+			m = getCause().getMessage();
+		if (m == null)
+			m = statusLine.getReasonPhrase();
+		return m;
+	}
+
 	@Override /* Object */
 	public int hashCode() {
 		int i = 0;
@@ -151,64 +209,165 @@ public class HttpException extends BasicRuntimeException {
 		return i;
 	}
 
-	/**
-	 * Set the status code on this exception.
-	 *
-	 * @param value The status code.
-	 * @return This object (for method chaining).
-	 */
-	@FluentSetter
-	public HttpException status(int value) {
-		status = value;
-		return this;
+	@Override /* Object */
+	public String toString() {
+		return emptyIfNull(getLocalizedMessage());
 	}
 
-	/**
-	 * Returns the HTTP status code.
-	 *
-	 * @return The HTTP status code.
-	 */
-	@ResponseStatus
-	public int getStatus() {
-		return status;
+	@Override /* HttpMessage */
+	public ProtocolVersion getProtocolVersion() {
+		return statusLine.getProtocolVersion();
 	}
 
-	/**
-	 * Add an HTTP header to this exception.
-	 *
-	 * @param name The header name.
-	 * @param val The header value.
-	 * @return This object (for method chaining).
-	 */
-	@FluentSetter
-	public HttpException header(String name, Object val) {
-		headers.a(name, val);
-		return this;
+	@Override /* HttpMessage */
+	public boolean containsHeader(String name) {
+		return headers.containsHeader(name);
 	}
 
-	/**
-	 * Returns the headers associated with this exception.
-	 *
-	 * @return The headers associated with this exception.
-	 */
+	@Override /* HttpMessage */
+	public Header[] getHeaders(String name) {
+		return headers.getHeaders(name);
+	}
+
+	@Override /* HttpMessage */
+	public Header getFirstHeader(String name) {
+		return headers.getFirstHeader(name).orElse(null);
+	}
+
+	@Override /* HttpMessage */
+	public Header getLastHeader(String name) {
+		return headers.getLastHeader(name).orElse(null);
+	}
+
+	@Override /* HttpMessage */
 	@ResponseHeader("*")
-	public Map<String,Object> getHeaders() {
-		return headers;
+	public Header[] getAllHeaders() {
+		return headers.getAllHeaders();
 	}
 
-	private static String message(Throwable cause, String msg, Object...args) {
-		if (msg == null && cause != null)
-			return firstNonEmpty(cause.getLocalizedMessage(), cause.getClass().getName());
-		return format(msg, args);
+	@Override /* HttpMessage */
+	public void addHeader(Header value) {
+		headers = headersBuilder().add(value).build();
 	}
 
-	// When serialized, just serialize the message itself.
-	@Override /* Object */
-	public String toString() {
-		return emptyIfNull(getLocalizedMessage());
+	@Override /* HttpMessage */
+	public void addHeader(String name, String value) {
+		headers = headersBuilder().add(new BasicHeader(name, value)).build();
+	}
+
+	@Override /* HttpMessage */
+	public void setHeader(Header value) {
+		headers = headersBuilder().update(value).build();
+	}
+
+	@Override /* HttpMessage */
+	public void setHeader(String name, String value) {
+		headers = headersBuilder().update(new BasicHeader(name, value)).build();
+	}
+
+	@Override /* HttpMessage */
+	public void setHeaders(Header[] values) {
+		headers = headersBuilder().set(values).build();
+	}
+
+	@Override /* HttpMessage */
+	public void removeHeader(Header value) {
+		headers = headersBuilder().remove(value).build();
+	}
+
+	@Override /* HttpMessage */
+	public void removeHeaders(String name) {
+		headers = headersBuilder().remove(name).build();
+	}
+
+	@Override /* HttpMessage */
+	public HeaderIterator headerIterator() {
+		return headers.iterator();
+	}
+
+	@Override /* HttpMessage */
+	public HeaderIterator headerIterator(String name) {
+		return headers.iterator(name);
+	}
+
+	@SuppressWarnings("deprecation")
+	@Override /* HttpMessage */
+	public HttpParams getParams() {
+		return null;
+	}
+
+	@SuppressWarnings("deprecation")
+	@Override /* HttpMessage */
+	public void setParams(HttpParams params) {
+	}
+
+	@Override /* HttpMessage */
+	public StatusLine getStatusLine() {
+		return statusLine;
+	}
+
+	@Override /* HttpMessage */
+	public void setStatusLine(StatusLine value) {
+		setStatusLine(value.getProtocolVersion(), value.getStatusCode(), value.getReasonPhrase());
+	}
+
+	@Override /* HttpMessage */
+	public void setStatusLine(ProtocolVersion ver, int code) {
+		statusLine = statusLineBuilder().protocolVersion(ver).statusCode(code).build();
+	}
+
+	@Override /* HttpMessage */
+	public void setStatusLine(ProtocolVersion ver, int code, String reason) {
+		statusLine = statusLineBuilder().protocolVersion(ver).reasonPhrase(reason).statusCode(code).build();
+	}
+
+	@Override /* HttpMessage */
+	public void setStatusCode(int code) throws IllegalStateException {
+		statusLine = statusLineBuilder().statusCode(code).build();
 	}
 
-	// <FluentSetters>
-
-	// </FluentSetters>
+	@Override /* HttpMessage */
+	public void setReasonPhrase(String reason) throws IllegalStateException {
+		statusLine = statusLineBuilder().reasonPhrase(reason).build();
+	}
+
+	@ResponseBody
+	@Override /* HttpMessage */
+	public HttpEntity getEntity() {
+		// Constructing a StringEntity is somewhat expensive, so don't create it unless it's needed.
+		if (body == null) {
+			try {
+				String msg = getMessage();
+				if (msg != null)
+					body = new StringEntity(msg);
+			} catch (UnsupportedEncodingException e) {}
+		}
+		return body;
+	}
+
+	@Override /* HttpMessage */
+	public void setEntity(HttpEntity entity) {
+		assertModifiable();
+		this.body = entity;
+	}
+
+	@Override /* HttpMessage */
+	public Locale getLocale() {
+		return statusLine.getLocale();
+	}
+
+	@Override /* HttpMessage */
+	public void setLocale(Locale loc) {
+		statusLine = statusLineBuilder().locale(loc).build();
+	}
+
+	private BasicStatusLineBuilder statusLineBuilder() {
+		assertModifiable();
+		return statusLine.builder();
+	}
+
+	private BasicHeaderGroupBuilder headersBuilder() {
+		assertModifiable();
+		return headers.builder();
+	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/HttpExceptionBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/HttpExceptionBuilder.java
new file mode 100644
index 0000000..05fa629
--- /dev/null
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/HttpExceptionBuilder.java
@@ -0,0 +1,399 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.http.exception;
+
+import java.io.*;
+import java.util.*;
+
+import org.apache.http.*;
+import org.apache.http.entity.*;
+import org.apache.http.impl.*;
+import org.apache.juneau.*;
+import org.apache.juneau.http.*;
+import org.apache.juneau.internal.*;
+
+/**
+ * Builder for {@link HttpException} classes.
+ *
+ * @param <T> The bean type to create for this builder.
+ */
+@FluentSetters(returns="HttpExceptionBuilder<T>")
+public class HttpExceptionBuilder<T extends HttpException> extends BasicRuntimeExceptionBuilder {
+
+	BasicStatusLineBuilder statusLine = BasicStatusLine.create();
+	BasicHeaderGroupBuilder headers = BasicHeaderGroup.create();
+	HttpEntity body;
+	private final Class<? extends HttpException> implClass;
+
+	/**
+	 * Constructor.
+	 *
+	 * @param implClass
+	 * 	The subclass of {@link HttpException} to create.
+	 * 	<br>This must contain a public constructor that takes in an {@link HttpExceptionBuilder} object.
+	 */
+	public HttpExceptionBuilder(Class<T> implClass) {
+		this.implClass = implClass;
+	}
+
+	/**
+	 * Instantiates the exception bean from the settings in this builder.
+	 *
+	 * @return A new {@link HttpException} bean.
+	 */
+	@SuppressWarnings("unchecked")
+	public T build() {
+		try {
+			return (T) implClass.getConstructor(HttpExceptionBuilder.class).newInstance(this);
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// BasicStatusLine setters.
+	//-----------------------------------------------------------------------------------------------------------------
+
+	/**
+	 * Sets the protocol version on the status line.
+	 *
+	 * <p>
+	 * If not specified, <js>"HTTP/1.1"</js> will be used.
+	 *
+	 * @param value The new value.
+	 * @return This object (for method chaining).
+	 */
+	@FluentSetter
+	public HttpExceptionBuilder<T> protocolVersion(ProtocolVersion value) {
+		statusLine.protocolVersion(value);
+		return this;
+	}
+
+	/**
+	 * Sets the status code on the status line.
+	 *
+	 * <p>
+	 * If not specified, <c>0</c> will be used.
+	 *
+	 * @param value The new value.
+	 * @return This object (for method chaining).
+	 */
+	@FluentSetter
+	public HttpExceptionBuilder<T> statusCode(int value) {
+		statusLine.statusCode(value);
+		return this;
+	}
+
+	/**
+	 * Sets the reason phrase on the status line.
+	 *
+	 * <p>
+	 * If not specified, the reason phrase will be retrieved from the reason phrase catalog
+	 * using the locale on this builder.
+	 *
+	 * @param value The new value.
+	 * @return This object (for method chaining).
+	 */
+	@FluentSetter
+	public HttpExceptionBuilder<T> reasonPhrase(String value) {
+		statusLine.reasonPhrase(value);
+		return this;
+	}
+
+	/**
+	 * Sets the reason phrase catalog used to retrieve reason phrases.
+	 *
+	 * <p>
+	 * If not specified, uses {@link EnglishReasonPhraseCatalog}.
+	 *
+	 * @param value The new value.
+	 * @return This object (for method chaining).
+	 */
+	@FluentSetter
+	public HttpExceptionBuilder<T> reasonPhraseCatalog(ReasonPhraseCatalog value) {
+		statusLine.reasonPhraseCatalog(value);
+		return this;
+	}
+
+	/**
+	 * Sets the locale used to retrieve reason phrases.
+	 *
+	 * <p>
+	 * If not specified, uses {@link Locale#getDefault()}.
+	 *
+	 * @param value The new value.
+	 * @return This object (for method chaining).
+	 */
+	@FluentSetter
+	public HttpExceptionBuilder<T> locale(Locale value) {
+		statusLine.locale(value);
+		return this;
+	}
+
+	/**
+	 * Copies the values from the specified exception.
+	 *
+	 * @param value The exception to copy from.
+	 * @return This object (for method chaining).
+	 */
+	public HttpExceptionBuilder<T> copyFrom(HttpException value) {
+		super.copyFrom(value);
+		statusLine = value.statusLine.builder();
+		headers = value.headers.builder();
+		body = value.body;
+		return this;
+	}
+
+	/**
+	 * Sets the status line builder for this builder.
+	 *
+	 * @param value The new status line builder.
+	 * @return This object (for method chaining).
+	 */
+	@FluentSetter
+	public HttpExceptionBuilder<T> statusLineBuilder(BasicStatusLineBuilder value) {
+		statusLine = value;
+		return this;
+	}
+
+	/**
+	 * Sets the header group builder for this builder.
+	 *
+	 * @param value The new header group builder.
+	 * @return This object (for method chaining).
+	 */
+	@FluentSetter
+	public HttpExceptionBuilder<T> headerGroupBuilder(BasicHeaderGroupBuilder value) {
+		headers = value;
+		return this;
+	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// BasicHeaderGroup setters.
+	//-----------------------------------------------------------------------------------------------------------------
+
+	/**
+	 * Removes any headers already in this builder.
+	 *
+	 * @return This object (for method chaining).
+	 */
+	public HttpExceptionBuilder<T> clearHeaders() {
+		headers.clear();
+		return this;
+	}
+
+	/**
+	 * Adds the specified header to the end of the headers in this builder.
+	 *
+	 * @param value The header to add.  <jk>null</jk> values are ignored.
+	 * @return This object (for method chaining).
+	 */
+	public HttpExceptionBuilder<T> header(Header value) {
+		headers.add(value);
+		return this;
+	}
+
+	/**
+	 * Adds the specified header to the end of the headers in this builder.
+	 *
+	 * @param name The header name.
+	 * @param value The header value.
+	 * @return This object (for method chaining).
+	 */
+	public HttpExceptionBuilder<T> header(String name, String value) {
+		headers.add(name, value);
+		return this;
+	}
+
+	/**
+	 * Adds the specified headers to the end of the headers in this builder.
+	 *
+	 * @param values The headers to add.  <jk>null</jk> values are ignored.
+	 * @return This object (for method chaining).
+	 */
+	public HttpExceptionBuilder<T> headers(Header...values) {
+		headers.add(values);
+		return this;
+	}
+
+	/**
+	 * Adds the specified headers to the end of the headers in this builder.
+	 *
+	 * @param values The headers to add.  <jk>null</jk> values are ignored.
+	 * @return This object (for method chaining).
+	 */
+	public HttpExceptionBuilder<T> headers(List<Header> values) {
+		headers.add(values);
+		return this;
+	}
+
+	/**
+	 * Removes the specified header from this builder.
+	 *
+	 * @param value The header to remove.  <jk>null</jk> values are ignored.
+	 * @return This object (for method chaining).
+	 */
+	public HttpExceptionBuilder<T> removeHeader(Header value) {
+		headers.remove(value);
+		return this;
+	}
+
+	/**
+	 * Removes the specified headers from this builder.
+	 *
+	 * @param values The headers to remove.  <jk>null</jk> values are ignored.
+	 * @return This object (for method chaining).
+	 */
+	public HttpExceptionBuilder<T> removeHeaders(Header...values) {
+		headers.remove(values);
+		return this;
+	}
+
+	/**
+	 * Removes the specified headers from this builder.
+	 *
+	 * @param values The headers to remove.  <jk>null</jk> values are ignored.
+	 * @return This object (for method chaining).
+	 */
+	public HttpExceptionBuilder<T> removeHeaders(List<Header> values) {
+		headers.remove(values);
+		return this;
+	}
+
+	/**
+	 * Replaces the first occurrence of the header with the same name.
+	 *
+	 * <p>
+	 * If no header with the same name is found the given header is added to the end of the list.
+	 *
+	 * @param value The headers to replace.  <jk>null</jk> values are ignored.
+	 * @return This object (for method chaining).
+	 */
+	public HttpExceptionBuilder<T> updateHeader(Header value) {
+		headers.update(value);
+		return this;
+	}
+
+	/**
+	 * Replaces the first occurrence of the headers with the same name.
+	 *
+	 * <p>
+	 * If no header with the same name is found the given header is added to the end of the list.
+	 *
+	 * @param values The headers to replace.  <jk>null</jk> values are ignored.
+	 * @return This object (for method chaining).
+	 */
+	public HttpExceptionBuilder<T> updateHeaders(Header...values) {
+		headers.update(values);
+		return this;
+	}
+
+	/**
+	 * Replaces the first occurrence of the headers with the same name.
+	 *
+	 * <p>
+	 * If no header with the same name is found the given header is added to the end of the list.
+	 *
+	 * @param values The headers to replace.  <jk>null</jk> values are ignored.
+	 * @return This object (for method chaining).
+	 */
+	public HttpExceptionBuilder<T> updateHeaders(List<Header> values) {
+		headers.update(values);
+		return this;
+	}
+
+	/**
+	 * Sets all of the headers contained within this group overriding any existing headers.
+	 *
+	 * <p>
+	 * The headers are added in the order in which they appear in the array.
+	 *
+	 * @param values The headers to set
+	 * @return This object (for method chaining).
+	 */
+	public HttpExceptionBuilder<T> setHeaders(Header...values) {
+		headers.set(values);
+		return this;
+	}
+
+	/**
+	 * Sets all of the headers contained within this group overriding any existing headers.
+	 *
+	 * <p>
+	 * The headers are added in the order in which they appear in the list.
+	 *
+	 * @param values The headers to set
+	 * @return This object (for method chaining).
+	 */
+	public HttpExceptionBuilder<T> setHeaders(List<Header> values) {
+		headers.set(values);
+		return this;
+	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// Body setters.
+	//-----------------------------------------------------------------------------------------------------------------
+
+	/**
+	 * Sets the body on this response.
+	 *
+	 * @param value The body on this response.
+	 * @return This object (for method chaining).
+	 */
+	public HttpExceptionBuilder<T> body(String value) {
+		try {
+			body(new StringEntity(value));
+		} catch (UnsupportedEncodingException e) { /* Not possible */ }
+		return this;
+	}
+
+	/**
+	 * Sets the body on this response.
+	 *
+	 * @param value The body on this response.
+	 * @return This object (for method chaining).
+	 */
+	public HttpExceptionBuilder<T> body(HttpEntity value) {
+		this.body = value;
+		return this;
+	}
+
+	// <FluentSetters>
+
+	@Override /* GENERATED - BasicRuntimeExceptionBuilder */
+	public HttpExceptionBuilder<T> causedBy(Throwable value) {
+		super.causedBy(value);
+		return this;
+	}
+
+	@Override /* GENERATED - BasicRuntimeExceptionBuilder */
+	public HttpExceptionBuilder<T> copyFrom(BasicRuntimeException value) {
+		super.copyFrom(value);
+		return this;
+	}
+
+	@Override /* GENERATED - BasicRuntimeExceptionBuilder */
+	public HttpExceptionBuilder<T> message(String msg, Object...args) {
+		super.message(msg, args);
+		return this;
+	}
+
+	@Override /* GENERATED - BasicRuntimeExceptionBuilder */
+	public HttpExceptionBuilder<T> unmodifiable(boolean value) {
+		super.unmodifiable(value);
+		return this;
+	}
+
+	// </FluentSetters>
+
+}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/HttpVersionNotSupported.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/HttpVersionNotSupported.java
index 906d8e9..ba8a67b 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/HttpVersionNotSupported.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/HttpVersionNotSupported.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.http.exception.HttpVersionNotSupported.*;
 import java.text.*;
 
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Exception representing an HTTP 505 ().
@@ -26,7 +25,6 @@ import org.apache.juneau.internal.*;
  * The server does not support the HTTP protocol version used in the request.
  */
 @Response(code=STATUS_CODE, description=REASON_PHRASE)
-@FluentSetters
 public class HttpVersionNotSupported extends HttpException {
 	private static final long serialVersionUID = 1L;
 
@@ -36,31 +34,52 @@ public class HttpVersionNotSupported extends HttpException {
 	/** Reason phrase */
 	public static final String REASON_PHRASE = "HTTP Version Not Supported";
 
+	/** Reusable unmodifiable instance. */
+	public static final HttpVersionNotSupported INSTANCE = create().unmodifiable(true).build();
+
+	/**
+	 * Creates a builder for this class.
+	 *
+	 * @return A new builder bean.
+	 */
+	public static HttpExceptionBuilder<HttpVersionNotSupported> create() {
+		return new HttpExceptionBuilder<>(HttpVersionNotSupported.class).statusCode(STATUS_CODE).reasonPhrase(REASON_PHRASE);
+	}
+
 	/**
 	 * Constructor.
 	 *
-	 * @param cause The cause.  Can be <jk>null</jk>.
-	 * @param msg The message.  Can be <jk>null</jk>.
-	 * @param args Optional {@link MessageFormat}-style arguments in the message.
+	 * @param builder The builder containing the settings for this exception.
 	 */
-	public HttpVersionNotSupported(Throwable cause, String msg, Object...args) {
-		super(cause, STATUS_CODE, msg, args);
+	public HttpVersionNotSupported(HttpExceptionBuilder<?> builder) {
+		super(builder);
 	}
 
 	/**
 	 * Constructor.
 	 *
+	 * @param cause The caused-by exception.  Can be <jk>null</jk>.
 	 * @param msg The message.  Can be <jk>null</jk>.
+	 * @param args The message arguments.
 	 */
-	public HttpVersionNotSupported(String msg) {
-		this((Throwable)null, msg);
+	public HttpVersionNotSupported(Throwable cause, String msg, Object...args) {
+		this(create().causedBy(cause).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 */
 	public HttpVersionNotSupported() {
-		this((Throwable)null, REASON_PHRASE);
+		this(create().build());
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param msg The message.  Can be <jk>null</jk>.
+	 */
+	public HttpVersionNotSupported(String msg) {
+		this(create().message(msg));
 	}
 
 	/**
@@ -70,7 +89,7 @@ public class HttpVersionNotSupported extends HttpException {
 	 * @param args Optional {@link MessageFormat}-style arguments in the message.
 	 */
 	public HttpVersionNotSupported(String msg, Object...args) {
-		this(null, msg, args);
+		this(create().message(msg, args));
 	}
 
 	/**
@@ -79,26 +98,15 @@ public class HttpVersionNotSupported extends HttpException {
 	 * @param cause The cause.  Can be <jk>null</jk>.
 	 */
 	public HttpVersionNotSupported(Throwable cause) {
-		this(cause, null);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Fluent setters.
-	//------------------------------------------------------------------------------------------------------------------
-
-	// <FluentSetters>
-
-	@Override /* GENERATED - HttpException */
-	public HttpVersionNotSupported header(String name, Object val) {
-		super.header(name, val);
-		return this;
+		this(create().causedBy(cause));
 	}
 
-	@Override /* GENERATED - HttpException */
-	public HttpVersionNotSupported status(int value) {
-		super.status(value);
-		return this;
+	/**
+	 * Creates a builder for this class initialized with the contents of this bean.
+	 *
+	 * @return A new builder bean.
+	 */
+	public HttpExceptionBuilder<HttpVersionNotSupported> builder() {
+		return super.builder(HttpVersionNotSupported.class).copyFrom(this);
 	}
-
-	// </FluentSetters>
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/InsufficientStorage.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/InsufficientStorage.java
index 45cb8b5..9c326e3 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/InsufficientStorage.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/InsufficientStorage.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.http.exception.InsufficientStorage.*;
 import java.text.*;
 
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Exception representing an HTTP 507 ().
@@ -26,7 +25,6 @@ import org.apache.juneau.internal.*;
  * The server is unable to store the representation needed to complete the request.
  */
 @Response(code=STATUS_CODE, description=REASON_PHRASE)
-@FluentSetters
 public class InsufficientStorage extends HttpException {
 	private static final long serialVersionUID = 1L;
 
@@ -36,31 +34,52 @@ public class InsufficientStorage extends HttpException {
 	/** Reason phrase */
 	public static final String REASON_PHRASE = "Insufficient Storage";
 
+	/** Reusable unmodifiable instance. */
+	public static final InsufficientStorage INSTANCE = create().unmodifiable(true).build();
+
+	/**
+	 * Creates a builder for this class.
+	 *
+	 * @return A new builder bean.
+	 */
+	public static HttpExceptionBuilder<InsufficientStorage> create() {
+		return new HttpExceptionBuilder<>(InsufficientStorage.class).statusCode(STATUS_CODE).reasonPhrase(REASON_PHRASE);
+	}
+
 	/**
 	 * Constructor.
 	 *
-	 * @param cause The cause.  Can be <jk>null</jk>.
-	 * @param msg The message.  Can be <jk>null</jk>.
-	 * @param args Optional {@link MessageFormat}-style arguments in the message.
+	 * @param builder The builder containing the settings for this exception.
 	 */
-	public InsufficientStorage(Throwable cause, String msg, Object...args) {
-		super(cause, STATUS_CODE, msg, args);
+	public InsufficientStorage(HttpExceptionBuilder<?> builder) {
+		super(builder);
 	}
 
 	/**
 	 * Constructor.
 	 *
+	 * @param cause The caused-by exception.  Can be <jk>null</jk>.
 	 * @param msg The message.  Can be <jk>null</jk>.
+	 * @param args The message arguments.
 	 */
-	public InsufficientStorage(String msg) {
-		this((Throwable)null, msg);
+	public InsufficientStorage(Throwable cause, String msg, Object...args) {
+		this(create().causedBy(cause).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 */
 	public InsufficientStorage() {
-		this((Throwable)null, REASON_PHRASE);
+		this(create().build());
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param msg The message.  Can be <jk>null</jk>.
+	 */
+	public InsufficientStorage(String msg) {
+		this(create().message(msg));
 	}
 
 	/**
@@ -70,7 +89,7 @@ public class InsufficientStorage extends HttpException {
 	 * @param args Optional {@link MessageFormat}-style arguments in the message.
 	 */
 	public InsufficientStorage(String msg, Object...args) {
-		this(null, msg, args);
+		this(create().message(msg, args));
 	}
 
 	/**
@@ -79,26 +98,15 @@ public class InsufficientStorage extends HttpException {
 	 * @param cause The cause.  Can be <jk>null</jk>.
 	 */
 	public InsufficientStorage(Throwable cause) {
-		this(cause, null);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Fluent setters.
-	//------------------------------------------------------------------------------------------------------------------
-
-	// <FluentSetters>
-
-	@Override /* GENERATED - HttpException */
-	public InsufficientStorage header(String name, Object val) {
-		super.header(name, val);
-		return this;
+		this(create().causedBy(cause));
 	}
 
-	@Override /* GENERATED - HttpException */
-	public InsufficientStorage status(int value) {
-		super.status(value);
-		return this;
+	/**
+	 * Creates a builder for this class initialized with the contents of this bean.
+	 *
+	 * @return A new builder bean.
+	 */
+	public HttpExceptionBuilder<InsufficientStorage> builder() {
+		return super.builder(InsufficientStorage.class).copyFrom(this);
 	}
-
-	// </FluentSetters>
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/InternalServerError.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/InternalServerError.java
index c3bf1ef..112d0b9 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/InternalServerError.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/InternalServerError.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.http.exception.InternalServerError.*;
 import java.text.*;
 
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Exception representing an HTTP 500 (Internal Server Error).
@@ -26,7 +25,6 @@ import org.apache.juneau.internal.*;
  * A generic error message, given when an unexpected condition was encountered and no more specific message is suitable.
  */
 @Response(code=STATUS_CODE, description=REASON_PHRASE)
-@FluentSetters
 public class InternalServerError extends HttpException {
 	private static final long serialVersionUID = 1L;
 
@@ -36,31 +34,52 @@ public class InternalServerError extends HttpException {
 	/** Reason phrase */
 	public static final String REASON_PHRASE = "Internal Server Error";
 
+	/** Reusable unmodifiable instance. */
+	public static final InternalServerError INSTANCE = create().unmodifiable(true).build();
+
+	/**
+	 * Creates a builder for this class.
+	 *
+	 * @return A new builder bean.
+	 */
+	public static HttpExceptionBuilder<InternalServerError> create() {
+		return new HttpExceptionBuilder<>(InternalServerError.class).statusCode(STATUS_CODE).reasonPhrase(REASON_PHRASE);
+	}
+
 	/**
 	 * Constructor.
 	 *
-	 * @param cause The cause.  Can be <jk>null</jk>.
-	 * @param msg The message.  Can be <jk>null</jk>.
-	 * @param args Optional {@link MessageFormat}-style arguments in the message.
+	 * @param builder The builder containing the settings for this exception.
 	 */
-	public InternalServerError(Throwable cause, String msg, Object...args) {
-		super(cause, STATUS_CODE, msg, args);
+	public InternalServerError(HttpExceptionBuilder<?> builder) {
+		super(builder);
 	}
 
 	/**
 	 * Constructor.
 	 *
+	 * @param cause The caused-by exception.  Can be <jk>null</jk>.
 	 * @param msg The message.  Can be <jk>null</jk>.
+	 * @param args The message arguments.
 	 */
-	public InternalServerError(String msg) {
-		this((Throwable)null, msg);
+	public InternalServerError(Throwable cause, String msg, Object...args) {
+		this(create().causedBy(cause).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 */
 	public InternalServerError() {
-		this((Throwable)null, REASON_PHRASE);
+		this(create().build());
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param msg The message.  Can be <jk>null</jk>.
+	 */
+	public InternalServerError(String msg) {
+		this(create().message(msg));
 	}
 
 	/**
@@ -70,7 +89,7 @@ public class InternalServerError extends HttpException {
 	 * @param args Optional {@link MessageFormat}-style arguments in the message.
 	 */
 	public InternalServerError(String msg, Object...args) {
-		this(null, msg, args);
+		this(create().message(msg, args));
 	}
 
 	/**
@@ -79,26 +98,15 @@ public class InternalServerError extends HttpException {
 	 * @param cause The cause.  Can be <jk>null</jk>.
 	 */
 	public InternalServerError(Throwable cause) {
-		this(cause, null);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Fluent setters.
-	//------------------------------------------------------------------------------------------------------------------
-
-	// <FluentSetters>
-
-	@Override /* GENERATED - HttpException */
-	public InternalServerError header(String name, Object val) {
-		super.header(name, val);
-		return this;
+		this(create().causedBy(cause));
 	}
 
-	@Override /* GENERATED - HttpException */
-	public InternalServerError status(int value) {
-		super.status(value);
-		return this;
+	/**
+	 * Creates a builder for this class initialized with the contents of this bean.
+	 *
+	 * @return A new builder bean.
+	 */
+	public HttpExceptionBuilder<InternalServerError> builder() {
+		return super.builder(InternalServerError.class).copyFrom(this);
 	}
-
-	// </FluentSetters>
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/LengthRequired.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/LengthRequired.java
index e768d10..af590a4 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/LengthRequired.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/LengthRequired.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.http.exception.LengthRequired.*;
 import java.text.*;
 
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Exception representing an HTTP 411 ().
@@ -26,7 +25,6 @@ import org.apache.juneau.internal.*;
  * The request did not specify the length of its content, which is required by the requested resource.
  */
 @Response(code=STATUS_CODE, description=REASON_PHRASE)
-@FluentSetters
 public class LengthRequired extends HttpException {
 	private static final long serialVersionUID = 1L;
 
@@ -36,31 +34,52 @@ public class LengthRequired extends HttpException {
 	/** Reason phrase */
 	public static final String REASON_PHRASE = "Length Required";
 
+	/** Reusable unmodifiable instance. */
+	public static final LengthRequired INSTANCE = create().unmodifiable(true).build();
+
+	/**
+	 * Creates a builder for this class.
+	 *
+	 * @return A new builder bean.
+	 */
+	public static HttpExceptionBuilder<LengthRequired> create() {
+		return new HttpExceptionBuilder<>(LengthRequired.class).statusCode(STATUS_CODE).reasonPhrase(REASON_PHRASE);
+	}
+
 	/**
 	 * Constructor.
 	 *
-	 * @param cause The cause.  Can be <jk>null</jk>.
-	 * @param msg The message.  Can be <jk>null</jk>.
-	 * @param args Optional {@link MessageFormat}-style arguments in the message.
+	 * @param builder The builder containing the settings for this exception.
 	 */
-	public LengthRequired(Throwable cause, String msg, Object...args) {
-		super(cause, STATUS_CODE, msg, args);
+	public LengthRequired(HttpExceptionBuilder<?> builder) {
+		super(builder);
 	}
 
 	/**
 	 * Constructor.
 	 *
+	 * @param cause The caused-by exception.  Can be <jk>null</jk>.
 	 * @param msg The message.  Can be <jk>null</jk>.
+	 * @param args The message arguments.
 	 */
-	public LengthRequired(String msg) {
-		this((Throwable)null, msg);
+	public LengthRequired(Throwable cause, String msg, Object...args) {
+		this(create().causedBy(cause).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 */
 	public LengthRequired() {
-		this((Throwable)null, REASON_PHRASE);
+		this(create().build());
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param msg The message.  Can be <jk>null</jk>.
+	 */
+	public LengthRequired(String msg) {
+		this(create().message(msg));
 	}
 
 	/**
@@ -70,7 +89,7 @@ public class LengthRequired extends HttpException {
 	 * @param args Optional {@link MessageFormat}-style arguments in the message.
 	 */
 	public LengthRequired(String msg, Object...args) {
-		this(null, msg, args);
+		this(create().message(msg, args));
 	}
 
 	/**
@@ -79,26 +98,15 @@ public class LengthRequired extends HttpException {
 	 * @param cause The cause.  Can be <jk>null</jk>.
 	 */
 	public LengthRequired(Throwable cause) {
-		this(cause, null);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Fluent setters.
-	//------------------------------------------------------------------------------------------------------------------
-
-	// <FluentSetters>
-
-	@Override /* GENERATED - HttpException */
-	public LengthRequired header(String name, Object val) {
-		super.header(name, val);
-		return this;
+		this(create().causedBy(cause));
 	}
 
-	@Override /* GENERATED - HttpException */
-	public LengthRequired status(int value) {
-		super.status(value);
-		return this;
+	/**
+	 * Creates a builder for this class initialized with the contents of this bean.
+	 *
+	 * @return A new builder bean.
+	 */
+	public HttpExceptionBuilder<LengthRequired> builder() {
+		return super.builder(LengthRequired.class).copyFrom(this);
 	}
-
-	// </FluentSetters>
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/Locked.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/Locked.java
index 95093b9..d68d5e4 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/Locked.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/Locked.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.http.exception.Locked.*;
 import java.text.*;
 
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Exception representing an HTTP 423 (Locked).
@@ -26,7 +25,6 @@ import org.apache.juneau.internal.*;
  * The resource that is being accessed is locked.
  */
 @Response(code=STATUS_CODE, description=REASON_PHRASE)
-@FluentSetters
 public class Locked extends HttpException {
 	private static final long serialVersionUID = 1L;
 
@@ -36,31 +34,52 @@ public class Locked extends HttpException {
 	/** Reason phrase */
 	public static final String REASON_PHRASE = "Locked";
 
+	/** Reusable unmodifiable instance. */
+	public static final Locked INSTANCE = create().unmodifiable(true).build();
+
+	/**
+	 * Creates a builder for this class.
+	 *
+	 * @return A new builder bean.
+	 */
+	public static HttpExceptionBuilder<Locked> create() {
+		return new HttpExceptionBuilder<>(Locked.class).statusCode(STATUS_CODE).reasonPhrase(REASON_PHRASE);
+	}
+
 	/**
 	 * Constructor.
 	 *
-	 * @param cause The cause.  Can be <jk>null</jk>.
-	 * @param msg The message.  Can be <jk>null</jk>.
-	 * @param args Optional {@link MessageFormat}-style arguments in the message.
+	 * @param builder The builder containing the settings for this exception.
 	 */
-	public Locked(Throwable cause, String msg, Object...args) {
-		super(cause, STATUS_CODE, msg, args);
+	public Locked(HttpExceptionBuilder<?> builder) {
+		super(builder);
 	}
 
 	/**
 	 * Constructor.
 	 *
+	 * @param cause The caused-by exception.  Can be <jk>null</jk>.
 	 * @param msg The message.  Can be <jk>null</jk>.
+	 * @param args The message arguments.
 	 */
-	public Locked(String msg) {
-		this((Throwable)null, msg);
+	public Locked(Throwable cause, String msg, Object...args) {
+		this(create().causedBy(cause).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 */
 	public Locked() {
-		this((Throwable)null, REASON_PHRASE);
+		this(create().build());
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param msg The message.  Can be <jk>null</jk>.
+	 */
+	public Locked(String msg) {
+		this(create().message(msg));
 	}
 
 	/**
@@ -70,7 +89,7 @@ public class Locked extends HttpException {
 	 * @param args Optional {@link MessageFormat}-style arguments in the message.
 	 */
 	public Locked(String msg, Object...args) {
-		this(null, msg, args);
+		this(create().message(msg, args));
 	}
 
 	/**
@@ -79,26 +98,15 @@ public class Locked extends HttpException {
 	 * @param cause The cause.  Can be <jk>null</jk>.
 	 */
 	public Locked(Throwable cause) {
-		this(cause, null);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Fluent setters.
-	//------------------------------------------------------------------------------------------------------------------
-
-	// <FluentSetters>
-
-	@Override /* GENERATED - HttpException */
-	public Locked header(String name, Object val) {
-		super.header(name, val);
-		return this;
+		this(create().causedBy(cause));
 	}
 
-	@Override /* GENERATED - HttpException */
-	public Locked status(int value) {
-		super.status(value);
-		return this;
+	/**
+	 * Creates a builder for this class initialized with the contents of this bean.
+	 *
+	 * @return A new builder bean.
+	 */
+	public HttpExceptionBuilder<Locked> builder() {
+		return super.builder(Locked.class).copyFrom(this);
 	}
-
-	// </FluentSetters>
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/LoopDetected.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/LoopDetected.java
index 6d29dfe..7218c4c 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/LoopDetected.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/LoopDetected.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.http.exception.LoopDetected.*;
 import java.text.*;
 
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Exception representing an HTTP 508 (Loop Detected).
@@ -26,7 +25,6 @@ import org.apache.juneau.internal.*;
  * The server detected an infinite loop while processing the request (sent in lieu of 208 Already Reported).
  */
 @Response(code=STATUS_CODE, description=REASON_PHRASE)
-@FluentSetters
 public class LoopDetected extends HttpException {
 	private static final long serialVersionUID = 1L;
 
@@ -36,31 +34,52 @@ public class LoopDetected extends HttpException {
 	/** Reason phrase */
 	public static final String REASON_PHRASE = "Loop Detected";
 
+	/** Reusable unmodifiable instance. */
+	public static final LoopDetected INSTANCE = create().unmodifiable(true).build();
+
+	/**
+	 * Creates a builder for this class.
+	 *
+	 * @return A new builder bean.
+	 */
+	public static HttpExceptionBuilder<LoopDetected> create() {
+		return new HttpExceptionBuilder<>(LoopDetected.class).statusCode(STATUS_CODE).reasonPhrase(REASON_PHRASE);
+	}
+
 	/**
 	 * Constructor.
 	 *
-	 * @param cause The cause.  Can be <jk>null</jk>.
-	 * @param msg The message.  Can be <jk>null</jk>.
-	 * @param args Optional {@link MessageFormat}-style arguments in the message.
+	 * @param builder The builder containing the settings for this exception.
 	 */
-	public LoopDetected(Throwable cause, String msg, Object...args) {
-		super(cause, STATUS_CODE, msg, args);
+	public LoopDetected(HttpExceptionBuilder<?> builder) {
+		super(builder);
 	}
 
 	/**
 	 * Constructor.
 	 *
+	 * @param cause The caused-by exception.  Can be <jk>null</jk>.
 	 * @param msg The message.  Can be <jk>null</jk>.
+	 * @param args The message arguments.
 	 */
-	public LoopDetected(String msg) {
-		this((Throwable)null, msg);
+	public LoopDetected(Throwable cause, String msg, Object...args) {
+		this(create().causedBy(cause).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 */
 	public LoopDetected() {
-		this((Throwable)null, REASON_PHRASE);
+		this(create().build());
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param msg The message.  Can be <jk>null</jk>.
+	 */
+	public LoopDetected(String msg) {
+		this(create().message(msg));
 	}
 
 	/**
@@ -70,7 +89,7 @@ public class LoopDetected extends HttpException {
 	 * @param args Optional {@link MessageFormat}-style arguments in the message.
 	 */
 	public LoopDetected(String msg, Object...args) {
-		this(null, msg, args);
+		this(create().message(msg, args));
 	}
 
 	/**
@@ -79,26 +98,15 @@ public class LoopDetected extends HttpException {
 	 * @param cause The cause.  Can be <jk>null</jk>.
 	 */
 	public LoopDetected(Throwable cause) {
-		this(cause, null);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Fluent setters.
-	//------------------------------------------------------------------------------------------------------------------
-
-	// <FluentSetters>
-
-	@Override /* GENERATED - HttpException */
-	public LoopDetected header(String name, Object val) {
-		super.header(name, val);
-		return this;
+		this(create().causedBy(cause));
 	}
 
-	@Override /* GENERATED - HttpException */
-	public LoopDetected status(int value) {
-		super.status(value);
-		return this;
+	/**
+	 * Creates a builder for this class initialized with the contents of this bean.
+	 *
+	 * @return A new builder bean.
+	 */
+	public HttpExceptionBuilder<LoopDetected> builder() {
+		return super.builder(LoopDetected.class).copyFrom(this);
 	}
-
-	// </FluentSetters>
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/MethodNotAllowed.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/MethodNotAllowed.java
index 42cad4b..3abfa08 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/MethodNotAllowed.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/MethodNotAllowed.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.http.exception.MethodNotAllowed.*;
 import java.text.*;
 
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Exception representing an HTTP 405 (Method Not Allowed).
@@ -26,7 +25,6 @@ import org.apache.juneau.internal.*;
  * A request method is not supported for the requested resource; for example, a GET request on a form that requires data to be presented via POST, or a PUT request on a read-only resource.
  */
 @Response(code=STATUS_CODE, description=REASON_PHRASE)
-@FluentSetters
 public class MethodNotAllowed extends HttpException {
 	private static final long serialVersionUID = 1L;
 
@@ -36,31 +34,52 @@ public class MethodNotAllowed extends HttpException {
 	/** Reason phrase */
 	public static final String REASON_PHRASE = "Method Not Allowed";
 
+	/** Reusable unmodifiable instance. */
+	public static final MethodNotAllowed INSTANCE = create().unmodifiable(true).build();
+
+	/**
+	 * Creates a builder for this class.
+	 *
+	 * @return A new builder bean.
+	 */
+	public static HttpExceptionBuilder<MethodNotAllowed> create() {
+		return new HttpExceptionBuilder<>(MethodNotAllowed.class).statusCode(STATUS_CODE).reasonPhrase(REASON_PHRASE);
+	}
+
 	/**
 	 * Constructor.
 	 *
-	 * @param cause The cause.  Can be <jk>null</jk>.
-	 * @param msg The message.  Can be <jk>null</jk>.
-	 * @param args Optional {@link MessageFormat}-style arguments in the message.
+	 * @param builder The builder containing the settings for this exception.
 	 */
-	public MethodNotAllowed(Throwable cause, String msg, Object...args) {
-		super(cause, STATUS_CODE, msg, args);
+	public MethodNotAllowed(HttpExceptionBuilder<?> builder) {
+		super(builder);
 	}
 
 	/**
 	 * Constructor.
 	 *
+	 * @param cause The caused-by exception.  Can be <jk>null</jk>.
 	 * @param msg The message.  Can be <jk>null</jk>.
+	 * @param args The message arguments.
 	 */
-	public MethodNotAllowed(String msg) {
-		this((Throwable)null, msg);
+	public MethodNotAllowed(Throwable cause, String msg, Object...args) {
+		this(create().causedBy(cause).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 */
 	public MethodNotAllowed() {
-		this((Throwable)null, REASON_PHRASE);
+		this(create().build());
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param msg The message.  Can be <jk>null</jk>.
+	 */
+	public MethodNotAllowed(String msg) {
+		this(create().message(msg));
 	}
 
 	/**
@@ -70,7 +89,7 @@ public class MethodNotAllowed extends HttpException {
 	 * @param args Optional {@link MessageFormat}-style arguments in the message.
 	 */
 	public MethodNotAllowed(String msg, Object...args) {
-		this(null, msg, args);
+		this(create().message(msg, args));
 	}
 
 	/**
@@ -79,26 +98,15 @@ public class MethodNotAllowed extends HttpException {
 	 * @param cause The cause.  Can be <jk>null</jk>.
 	 */
 	public MethodNotAllowed(Throwable cause) {
-		this(cause, null);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Fluent setters.
-	//------------------------------------------------------------------------------------------------------------------
-
-	// <FluentSetters>
-
-	@Override /* GENERATED - HttpException */
-	public MethodNotAllowed header(String name, Object val) {
-		super.header(name, val);
-		return this;
+		this(create().causedBy(cause));
 	}
 
-	@Override /* GENERATED - HttpException */
-	public MethodNotAllowed status(int value) {
-		super.status(value);
-		return this;
+	/**
+	 * Creates a builder for this class initialized with the contents of this bean.
+	 *
+	 * @return A new builder bean.
+	 */
+	public HttpExceptionBuilder<MethodNotAllowed> builder() {
+		return super.builder(MethodNotAllowed.class).copyFrom(this);
 	}
-
-	// </FluentSetters>
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/MisdirectedRequest.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/MisdirectedRequest.java
index 6e06243..ed1d557 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/MisdirectedRequest.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/MisdirectedRequest.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.http.exception.MisdirectedRequest.*;
 import java.text.*;
 
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Exception representing an HTTP 421 (Misdirected Request).
@@ -26,7 +25,6 @@ import org.apache.juneau.internal.*;
  * The request was directed at a server that is not able to produce a response (for example because of connection reuse).
  */
 @Response(code=STATUS_CODE, description=REASON_PHRASE)
-@FluentSetters
 public class MisdirectedRequest extends HttpException {
 	private static final long serialVersionUID = 1L;
 
@@ -36,31 +34,52 @@ public class MisdirectedRequest extends HttpException {
 	/** Reason phrase */
 	public static final String REASON_PHRASE = "Misdirected Request";
 
+	/** Reusable unmodifiable instance. */
+	public static final MisdirectedRequest INSTANCE = create().unmodifiable(true).build();
+
+	/**
+	 * Creates a builder for this class.
+	 *
+	 * @return A new builder bean.
+	 */
+	public static HttpExceptionBuilder<MisdirectedRequest> create() {
+		return new HttpExceptionBuilder<>(MisdirectedRequest.class).statusCode(STATUS_CODE).reasonPhrase(REASON_PHRASE);
+	}
+
 	/**
 	 * Constructor.
 	 *
-	 * @param cause The cause.  Can be <jk>null</jk>.
-	 * @param msg The message.  Can be <jk>null</jk>.
-	 * @param args Optional {@link MessageFormat}-style arguments in the message.
+	 * @param builder The builder containing the settings for this exception.
 	 */
-	public MisdirectedRequest(Throwable cause, String msg, Object...args) {
-		super(cause, STATUS_CODE, msg, args);
+	public MisdirectedRequest(HttpExceptionBuilder<?> builder) {
+		super(builder);
 	}
 
 	/**
 	 * Constructor.
 	 *
+	 * @param cause The caused-by exception.  Can be <jk>null</jk>.
 	 * @param msg The message.  Can be <jk>null</jk>.
+	 * @param args The message arguments.
 	 */
-	public MisdirectedRequest(String msg) {
-		this((Throwable)null, msg);
+	public MisdirectedRequest(Throwable cause, String msg, Object...args) {
+		this(create().causedBy(cause).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 */
 	public MisdirectedRequest() {
-		this((Throwable)null, REASON_PHRASE);
+		this(create().build());
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param msg The message.  Can be <jk>null</jk>.
+	 */
+	public MisdirectedRequest(String msg) {
+		this(create().message(msg));
 	}
 
 	/**
@@ -70,7 +89,7 @@ public class MisdirectedRequest extends HttpException {
 	 * @param args Optional {@link MessageFormat}-style arguments in the message.
 	 */
 	public MisdirectedRequest(String msg, Object...args) {
-		this(null, msg, args);
+		this(create().message(msg, args));
 	}
 
 	/**
@@ -79,26 +98,15 @@ public class MisdirectedRequest extends HttpException {
 	 * @param cause The cause.  Can be <jk>null</jk>.
 	 */
 	public MisdirectedRequest(Throwable cause) {
-		this(cause, null);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Fluent setters.
-	//------------------------------------------------------------------------------------------------------------------
-
-	// <FluentSetters>
-
-	@Override /* GENERATED - HttpException */
-	public MisdirectedRequest header(String name, Object val) {
-		super.header(name, val);
-		return this;
+		this(create().causedBy(cause));
 	}
 
-	@Override /* GENERATED - HttpException */
-	public MisdirectedRequest status(int value) {
-		super.status(value);
-		return this;
+	/**
+	 * Creates a builder for this class initialized with the contents of this bean.
+	 *
+	 * @return A new builder bean.
+	 */
+	public HttpExceptionBuilder<MisdirectedRequest> builder() {
+		return super.builder(MisdirectedRequest.class).copyFrom(this);
 	}
-
-	// </FluentSetters>
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/NetworkAuthenticationRequired.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/NetworkAuthenticationRequired.java
index d85d0d8..511a4f5 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/NetworkAuthenticationRequired.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/NetworkAuthenticationRequired.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.http.exception.NetworkAuthenticationRequired.*;
 import java.text.*;
 
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Exception representing an HTTP 511 (Network Authentication Required).
@@ -27,7 +26,6 @@ import org.apache.juneau.internal.*;
  * <br>Intended for use by intercepting proxies used to control access to the network (e.g., "captive portals" used to require agreement to Terms of Service before granting full Internet access via a Wi-Fi hotspot).
  */
 @Response(code=STATUS_CODE, description=REASON_PHRASE)
-@FluentSetters
 public class NetworkAuthenticationRequired extends HttpException {
 	private static final long serialVersionUID = 1L;
 
@@ -37,31 +35,52 @@ public class NetworkAuthenticationRequired extends HttpException {
 	/** Reason phrase */
 	public static final String REASON_PHRASE = "Network Authentication Required";
 
+	/** Reusable unmodifiable instance. */
+	public static final NetworkAuthenticationRequired INSTANCE = create().unmodifiable(true).build();
+
+	/**
+	 * Creates a builder for this class.
+	 *
+	 * @return A new builder bean.
+	 */
+	public static HttpExceptionBuilder<NetworkAuthenticationRequired> create() {
+		return new HttpExceptionBuilder<>(NetworkAuthenticationRequired.class).statusCode(STATUS_CODE).reasonPhrase(REASON_PHRASE);
+	}
+
 	/**
 	 * Constructor.
 	 *
-	 * @param cause The cause.  Can be <jk>null</jk>.
-	 * @param msg The message.  Can be <jk>null</jk>.
-	 * @param args Optional {@link MessageFormat}-style arguments in the message.
+	 * @param builder The builder containing the settings for this exception.
 	 */
-	public NetworkAuthenticationRequired(Throwable cause, String msg, Object...args) {
-		super(cause, STATUS_CODE, msg, args);
+	public NetworkAuthenticationRequired(HttpExceptionBuilder<?> builder) {
+		super(builder);
 	}
 
 	/**
 	 * Constructor.
 	 *
+	 * @param cause The caused-by exception.  Can be <jk>null</jk>.
 	 * @param msg The message.  Can be <jk>null</jk>.
+	 * @param args The message arguments.
 	 */
-	public NetworkAuthenticationRequired(String msg) {
-		this((Throwable)null, msg);
+	public NetworkAuthenticationRequired(Throwable cause, String msg, Object...args) {
+		this(create().causedBy(cause).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 */
 	public NetworkAuthenticationRequired() {
-		this((Throwable)null, REASON_PHRASE);
+		this(create().build());
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param msg The message.  Can be <jk>null</jk>.
+	 */
+	public NetworkAuthenticationRequired(String msg) {
+		this(create().message(msg));
 	}
 
 	/**
@@ -71,7 +90,7 @@ public class NetworkAuthenticationRequired extends HttpException {
 	 * @param args Optional {@link MessageFormat}-style arguments in the message.
 	 */
 	public NetworkAuthenticationRequired(String msg, Object...args) {
-		this(null, msg, args);
+		this(create().message(msg, args));
 	}
 
 	/**
@@ -80,26 +99,15 @@ public class NetworkAuthenticationRequired extends HttpException {
 	 * @param cause The cause.  Can be <jk>null</jk>.
 	 */
 	public NetworkAuthenticationRequired(Throwable cause) {
-		this(cause, null);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Fluent setters.
-	//------------------------------------------------------------------------------------------------------------------
-
-	// <FluentSetters>
-
-	@Override /* GENERATED - HttpException */
-	public NetworkAuthenticationRequired header(String name, Object val) {
-		super.header(name, val);
-		return this;
+		this(create().causedBy(cause));
 	}
 
-	@Override /* GENERATED - HttpException */
-	public NetworkAuthenticationRequired status(int value) {
-		super.status(value);
-		return this;
+	/**
+	 * Creates a builder for this class initialized with the contents of this bean.
+	 *
+	 * @return A new builder bean.
+	 */
+	public HttpExceptionBuilder<NetworkAuthenticationRequired> builder() {
+		return super.builder(NetworkAuthenticationRequired.class).copyFrom(this);
 	}
-
-	// </FluentSetters>
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/NotAcceptable.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/NotAcceptable.java
index b885d3b..7770707 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/NotAcceptable.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/NotAcceptable.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.http.exception.NotAcceptable.*;
 import java.text.*;
 
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Exception representing an HTTP 406 (Not Acceptable).
@@ -26,7 +25,6 @@ import org.apache.juneau.internal.*;
  * The requested resource is capable of generating only content not acceptable according to the Accept headers sent in the request.
  */
 @Response(code=STATUS_CODE, description=REASON_PHRASE)
-@FluentSetters
 public class NotAcceptable extends HttpException {
 	private static final long serialVersionUID = 1L;
 
@@ -36,31 +34,52 @@ public class NotAcceptable extends HttpException {
 	/** Reason phrase */
 	public static final String REASON_PHRASE = "Not Acceptable";
 
+	/** Reusable unmodifiable instance. */
+	public static final NotAcceptable INSTANCE = create().unmodifiable(true).build();
+
+	/**
+	 * Creates a builder for this class.
+	 *
+	 * @return A new builder bean.
+	 */
+	public static HttpExceptionBuilder<NotAcceptable> create() {
+		return new HttpExceptionBuilder<>(NotAcceptable.class).statusCode(STATUS_CODE).reasonPhrase(REASON_PHRASE);
+	}
+
 	/**
 	 * Constructor.
 	 *
-	 * @param cause The cause.  Can be <jk>null</jk>.
-	 * @param msg The message.  Can be <jk>null</jk>.
-	 * @param args Optional {@link MessageFormat}-style arguments in the message.
+	 * @param builder The builder containing the settings for this exception.
 	 */
-	public NotAcceptable(Throwable cause, String msg, Object...args) {
-		super(cause, STATUS_CODE, msg, args);
+	public NotAcceptable(HttpExceptionBuilder<?> builder) {
+		super(builder);
 	}
 
 	/**
 	 * Constructor.
 	 *
+	 * @param cause The caused-by exception.  Can be <jk>null</jk>.
 	 * @param msg The message.  Can be <jk>null</jk>.
+	 * @param args The message arguments.
 	 */
-	public NotAcceptable(String msg) {
-		this((Throwable)null, msg);
+	public NotAcceptable(Throwable cause, String msg, Object...args) {
+		this(create().causedBy(cause).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 */
 	public NotAcceptable() {
-		this((Throwable)null, REASON_PHRASE);
+		this(create().build());
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param msg The message.  Can be <jk>null</jk>.
+	 */
+	public NotAcceptable(String msg) {
+		this(create().message(msg));
 	}
 
 	/**
@@ -70,7 +89,7 @@ public class NotAcceptable extends HttpException {
 	 * @param args Optional {@link MessageFormat}-style arguments in the message.
 	 */
 	public NotAcceptable(String msg, Object...args) {
-		this(null, msg, args);
+		this(create().message(msg, args));
 	}
 
 	/**
@@ -79,26 +98,15 @@ public class NotAcceptable extends HttpException {
 	 * @param cause The cause.  Can be <jk>null</jk>.
 	 */
 	public NotAcceptable(Throwable cause) {
-		this(cause, null);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Fluent setters.
-	//------------------------------------------------------------------------------------------------------------------
-
-	// <FluentSetters>
-
-	@Override /* GENERATED - HttpException */
-	public NotAcceptable header(String name, Object val) {
-		super.header(name, val);
-		return this;
+		this(create().causedBy(cause));
 	}
 
-	@Override /* GENERATED - HttpException */
-	public NotAcceptable status(int value) {
-		super.status(value);
-		return this;
+	/**
+	 * Creates a builder for this class initialized with the contents of this bean.
+	 *
+	 * @return A new builder bean.
+	 */
+	public HttpExceptionBuilder<NotAcceptable> builder() {
+		return super.builder(NotAcceptable.class).copyFrom(this);
 	}
-
-	// </FluentSetters>
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/NotExtended.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/NotExtended.java
index 68e5f80..f5029fd 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/NotExtended.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/NotExtended.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.http.exception.NotExtended.*;
 import java.text.*;
 
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Exception representing an HTTP 510 (Not Extended).
@@ -26,7 +25,6 @@ import org.apache.juneau.internal.*;
  * Further extensions to the request are required for the server to fulfill it.
  */
 @Response(code=STATUS_CODE, description=REASON_PHRASE)
-@FluentSetters
 public class NotExtended extends HttpException {
 	private static final long serialVersionUID = 1L;
 
@@ -36,31 +34,53 @@ public class NotExtended extends HttpException {
 	/** Reason phrase */
 	public static final String REASON_PHRASE = "Not Extended";
 
+
+	/** Reusable unmodifiable instance. */
+	public static final NotExtended INSTANCE = create().unmodifiable(true).build();
+
+	/**
+	 * Creates a builder for this class.
+	 *
+	 * @return A new builder bean.
+	 */
+	public static HttpExceptionBuilder<NotExtended> create() {
+		return new HttpExceptionBuilder<>(NotExtended.class).statusCode(STATUS_CODE).reasonPhrase(REASON_PHRASE);
+	}
+
 	/**
 	 * Constructor.
 	 *
-	 * @param cause The cause.  Can be <jk>null</jk>.
-	 * @param msg The message.  Can be <jk>null</jk>.
-	 * @param args Optional {@link MessageFormat}-style arguments in the message.
+	 * @param builder The builder containing the settings for this exception.
 	 */
-	public NotExtended(Throwable cause, String msg, Object...args) {
-		super(cause, STATUS_CODE, msg, args);
+	public NotExtended(HttpExceptionBuilder<?> builder) {
+		super(builder);
 	}
 
 	/**
 	 * Constructor.
 	 *
+	 * @param cause The caused-by exception.  Can be <jk>null</jk>.
 	 * @param msg The message.  Can be <jk>null</jk>.
+	 * @param args The message arguments.
 	 */
-	public NotExtended(String msg) {
-		this((Throwable)null, msg);
+	public NotExtended(Throwable cause, String msg, Object...args) {
+		this(create().causedBy(cause).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 */
 	public NotExtended() {
-		this((Throwable)null, REASON_PHRASE);
+		this(create().build());
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param msg The message.  Can be <jk>null</jk>.
+	 */
+	public NotExtended(String msg) {
+		this(create().message(msg));
 	}
 
 	/**
@@ -70,7 +90,7 @@ public class NotExtended extends HttpException {
 	 * @param args Optional {@link MessageFormat}-style arguments in the message.
 	 */
 	public NotExtended(String msg, Object...args) {
-		this(null, msg, args);
+		this(create().message(msg, args));
 	}
 
 	/**
@@ -79,26 +99,15 @@ public class NotExtended extends HttpException {
 	 * @param cause The cause.  Can be <jk>null</jk>.
 	 */
 	public NotExtended(Throwable cause) {
-		this(cause, null);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Fluent setters.
-	//------------------------------------------------------------------------------------------------------------------
-
-	// <FluentSetters>
-
-	@Override /* GENERATED - HttpException */
-	public NotExtended header(String name, Object val) {
-		super.header(name, val);
-		return this;
+		this(create().causedBy(cause));
 	}
 
-	@Override /* GENERATED - HttpException */
-	public NotExtended status(int value) {
-		super.status(value);
-		return this;
+	/**
+	 * Creates a builder for this class initialized with the contents of this bean.
+	 *
+	 * @return A new builder bean.
+	 */
+	public HttpExceptionBuilder<NotExtended> builder() {
+		return super.builder(NotExtended.class).copyFrom(this);
 	}
-
-	// </FluentSetters>
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/NotFound.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/NotFound.java
index 49c795a..bdadb09 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/NotFound.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/NotFound.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.http.exception.NotFound.*;
 import java.text.*;
 
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Exception representing an HTTP 404 (Not Found).
@@ -27,7 +26,6 @@ import org.apache.juneau.internal.*;
  * <br>Subsequent requests by the client are permissible.
  */
 @Response(code=STATUS_CODE, description=REASON_PHRASE)
-@FluentSetters
 public class NotFound extends HttpException {
 	private static final long serialVersionUID = 1L;
 
@@ -37,31 +35,52 @@ public class NotFound extends HttpException {
 	/** Reason phrase */
 	public static final String REASON_PHRASE = "Not Found";
 
+	/** Reusable unmodifiable instance. */
+	public static final NotFound INSTANCE = create().unmodifiable(true).build();
+
+	/**
+	 * Creates a builder for this class.
+	 *
+	 * @return A new builder bean.
+	 */
+	public static HttpExceptionBuilder<NotFound> create() {
+		return new HttpExceptionBuilder<>(NotFound.class).statusCode(STATUS_CODE).reasonPhrase(REASON_PHRASE);
+	}
+
 	/**
 	 * Constructor.
 	 *
-	 * @param cause The cause.  Can be <jk>null</jk>.
-	 * @param msg The message.  Can be <jk>null</jk>.
-	 * @param args Optional {@link MessageFormat}-style arguments in the message.
+	 * @param builder The builder containing the settings for this exception.
 	 */
-	public NotFound(Throwable cause, String msg, Object...args) {
-		super(cause, STATUS_CODE, msg, args);
+	public NotFound(HttpExceptionBuilder<?> builder) {
+		super(builder);
 	}
 
 	/**
 	 * Constructor.
 	 *
+	 * @param cause The caused-by exception.  Can be <jk>null</jk>.
 	 * @param msg The message.  Can be <jk>null</jk>.
+	 * @param args The message arguments.
 	 */
-	public NotFound(String msg) {
-		this((Throwable)null, msg);
+	public NotFound(Throwable cause, String msg, Object...args) {
+		this(create().causedBy(cause).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 */
 	public NotFound() {
-		this((Throwable)null, REASON_PHRASE);
+		this(create().build());
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param msg The message.  Can be <jk>null</jk>.
+	 */
+	public NotFound(String msg) {
+		this(create().message(msg));
 	}
 
 	/**
@@ -71,7 +90,7 @@ public class NotFound extends HttpException {
 	 * @param args Optional {@link MessageFormat}-style arguments in the message.
 	 */
 	public NotFound(String msg, Object...args) {
-		this(null, msg, args);
+		this(create().message(msg, args));
 	}
 
 	/**
@@ -80,26 +99,15 @@ public class NotFound extends HttpException {
 	 * @param cause The cause.  Can be <jk>null</jk>.
 	 */
 	public NotFound(Throwable cause) {
-		this(cause, null);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Fluent setters.
-	//------------------------------------------------------------------------------------------------------------------
-
-	// <FluentSetters>
-
-	@Override /* GENERATED - HttpException */
-	public NotFound header(String name, Object val) {
-		super.header(name, val);
-		return this;
+		this(create().causedBy(cause));
 	}
 
-	@Override /* GENERATED - HttpException */
-	public NotFound status(int value) {
-		super.status(value);
-		return this;
+	/**
+	 * Creates a builder for this class initialized with the contents of this bean.
+	 *
+	 * @return A new builder bean.
+	 */
+	public HttpExceptionBuilder<NotFound> builder() {
+		return super.builder(NotFound.class).copyFrom(this);
 	}
-
-	// </FluentSetters>
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/NotImplemented.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/NotImplemented.java
index 32f8ffd..6d002c7 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/NotImplemented.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/NotImplemented.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.http.exception.NotImplemented.*;
 import java.text.*;
 
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Exception representing an HTTP 501 (Not Implemented).
@@ -27,7 +26,6 @@ import org.apache.juneau.internal.*;
  * <br>Usually this implies future availability (e.g., a new feature of a web-service API).
  */
 @Response(code=STATUS_CODE, description=REASON_PHRASE)
-@FluentSetters
 public class NotImplemented extends HttpException {
 	private static final long serialVersionUID = 1L;
 
@@ -37,31 +35,52 @@ public class NotImplemented extends HttpException {
 	/** Reason phrase */
 	public static final String REASON_PHRASE = "Not Implemented";
 
+	/** Reusable unmodifiable instance. */
+	public static final NotImplemented INSTANCE = create().unmodifiable(true).build();
+
+	/**
+	 * Creates a builder for this class.
+	 *
+	 * @return A new builder bean.
+	 */
+	public static HttpExceptionBuilder<NotImplemented> create() {
+		return new HttpExceptionBuilder<>(NotImplemented.class).statusCode(STATUS_CODE).reasonPhrase(REASON_PHRASE);
+	}
+
 	/**
 	 * Constructor.
 	 *
-	 * @param cause The cause.  Can be <jk>null</jk>.
-	 * @param msg The message.  Can be <jk>null</jk>.
-	 * @param args Optional {@link MessageFormat}-style arguments in the message.
+	 * @param builder The builder containing the settings for this exception.
 	 */
-	public NotImplemented(Throwable cause, String msg, Object...args) {
-		super(cause, STATUS_CODE, msg, args);
+	public NotImplemented(HttpExceptionBuilder<?> builder) {
+		super(builder);
 	}
 
 	/**
 	 * Constructor.
 	 *
+	 * @param cause The caused-by exception.  Can be <jk>null</jk>.
 	 * @param msg The message.  Can be <jk>null</jk>.
+	 * @param args The message arguments.
 	 */
-	public NotImplemented(String msg) {
-		this((Throwable)null, msg);
+	public NotImplemented(Throwable cause, String msg, Object...args) {
+		this(create().causedBy(cause).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 */
 	public NotImplemented() {
-		this((Throwable)null, REASON_PHRASE);
+		this(create().build());
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param msg The message.  Can be <jk>null</jk>.
+	 */
+	public NotImplemented(String msg) {
+		this(create().message(msg));
 	}
 
 	/**
@@ -71,7 +90,7 @@ public class NotImplemented extends HttpException {
 	 * @param args Optional {@link MessageFormat}-style arguments in the message.
 	 */
 	public NotImplemented(String msg, Object...args) {
-		this(null, msg, args);
+		this(create().message(msg, args));
 	}
 
 	/**
@@ -80,26 +99,15 @@ public class NotImplemented extends HttpException {
 	 * @param cause The cause.  Can be <jk>null</jk>.
 	 */
 	public NotImplemented(Throwable cause) {
-		this(cause, null);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Fluent setters.
-	//------------------------------------------------------------------------------------------------------------------
-
-	// <FluentSetters>
-
-	@Override /* GENERATED - HttpException */
-	public NotImplemented header(String name, Object val) {
-		super.header(name, val);
-		return this;
+		this(create().causedBy(cause));
 	}
 
-	@Override /* GENERATED - HttpException */
-	public NotImplemented status(int value) {
-		super.status(value);
-		return this;
+	/**
+	 * Creates a builder for this class initialized with the contents of this bean.
+	 *
+	 * @return A new builder bean.
+	 */
+	public HttpExceptionBuilder<NotImplemented> builder() {
+		return super.builder(NotImplemented.class).copyFrom(this);
 	}
-
-	// </FluentSetters>
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/PayloadTooLarge.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/PayloadTooLarge.java
index b9bf014..d1d5f20 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/PayloadTooLarge.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/PayloadTooLarge.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.http.exception.PayloadTooLarge.*;
 import java.text.*;
 
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Exception representing an HTTP 413 (Payload Too Large).
@@ -26,7 +25,6 @@ import org.apache.juneau.internal.*;
  * The request is larger than the server is willing or able to process.
  */
 @Response(code=STATUS_CODE, description=REASON_PHRASE)
-@FluentSetters
 public class PayloadTooLarge extends HttpException {
 	private static final long serialVersionUID = 1L;
 
@@ -36,31 +34,52 @@ public class PayloadTooLarge extends HttpException {
 	/** Reason phrase */
 	public static final String REASON_PHRASE = "Payload Too Large";
 
+	/** Reusable unmodifiable instance. */
+	public static final PayloadTooLarge INSTANCE = create().unmodifiable(true).build();
+
+	/**
+	 * Creates a builder for this class.
+	 *
+	 * @return A new builder bean.
+	 */
+	public static HttpExceptionBuilder<PayloadTooLarge> create() {
+		return new HttpExceptionBuilder<>(PayloadTooLarge.class).statusCode(STATUS_CODE).reasonPhrase(REASON_PHRASE);
+	}
+
 	/**
 	 * Constructor.
 	 *
-	 * @param cause The cause.  Can be <jk>null</jk>.
-	 * @param msg The message.  Can be <jk>null</jk>.
-	 * @param args Optional {@link MessageFormat}-style arguments in the message.
+	 * @param builder The builder containing the settings for this exception.
 	 */
-	public PayloadTooLarge(Throwable cause, String msg, Object...args) {
-		super(cause, STATUS_CODE, msg, args);
+	public PayloadTooLarge(HttpExceptionBuilder<?> builder) {
+		super(builder);
 	}
 
 	/**
 	 * Constructor.
 	 *
+	 * @param cause The caused-by exception.  Can be <jk>null</jk>.
 	 * @param msg The message.  Can be <jk>null</jk>.
+	 * @param args The message arguments.
 	 */
-	public PayloadTooLarge(String msg) {
-		this((Throwable)null, msg);
+	public PayloadTooLarge(Throwable cause, String msg, Object...args) {
+		this(create().causedBy(cause).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 */
 	public PayloadTooLarge() {
-		this((Throwable)null, REASON_PHRASE);
+		this(create().build());
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param msg The message.  Can be <jk>null</jk>.
+	 */
+	public PayloadTooLarge(String msg) {
+		this(create().message(msg));
 	}
 
 	/**
@@ -70,7 +89,7 @@ public class PayloadTooLarge extends HttpException {
 	 * @param args Optional {@link MessageFormat}-style arguments in the message.
 	 */
 	public PayloadTooLarge(String msg, Object...args) {
-		this(null, msg, args);
+		this(create().message(msg, args));
 	}
 
 	/**
@@ -79,26 +98,15 @@ public class PayloadTooLarge extends HttpException {
 	 * @param cause The cause.  Can be <jk>null</jk>.
 	 */
 	public PayloadTooLarge(Throwable cause) {
-		this(cause, null);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Fluent setters.
-	//------------------------------------------------------------------------------------------------------------------
-
-	// <FluentSetters>
-
-	@Override /* GENERATED - HttpException */
-	public PayloadTooLarge header(String name, Object val) {
-		super.header(name, val);
-		return this;
+		this(create().causedBy(cause));
 	}
 
-	@Override /* GENERATED - HttpException */
-	public PayloadTooLarge status(int value) {
-		super.status(value);
-		return this;
+	/**
+	 * Creates a builder for this class initialized with the contents of this bean.
+	 *
+	 * @return A new builder bean.
+	 */
+	public HttpExceptionBuilder<PayloadTooLarge> builder() {
+		return super.builder(PayloadTooLarge.class).copyFrom(this);
 	}
-
-	// </FluentSetters>
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/PreconditionFailed.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/PreconditionFailed.java
index 8caae95..fb29c1e 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/PreconditionFailed.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/PreconditionFailed.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.http.exception.PreconditionFailed.*;
 import java.text.*;
 
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Exception representing an HTTP 412 (Precondition Failed).
@@ -26,7 +25,6 @@ import org.apache.juneau.internal.*;
  * The server does not meet one of the preconditions that the requester put on the request.
  */
 @Response(code=STATUS_CODE, description=REASON_PHRASE)
-@FluentSetters
 public class PreconditionFailed extends HttpException {
 	private static final long serialVersionUID = 1L;
 
@@ -36,22 +34,43 @@ public class PreconditionFailed extends HttpException {
 	/** Reason phrase */
 	public static final String REASON_PHRASE = "Precondition Failed";
 
+	/** Reusable unmodifiable instance. */
+	public static final PreconditionFailed INSTANCE = create().unmodifiable(true).build();
+
+	/**
+	 * Creates a builder for this class.
+	 *
+	 * @return A new builder bean.
+	 */
+	public static HttpExceptionBuilder<PreconditionFailed> create() {
+		return new HttpExceptionBuilder<>(PreconditionFailed.class).statusCode(STATUS_CODE).reasonPhrase(REASON_PHRASE);
+	}
+
 	/**
 	 * Constructor.
 	 *
-	 * @param cause The cause.  Can be <jk>null</jk>.
+	 * @param builder The builder containing the settings for this exception.
+	 */
+	public PreconditionFailed(HttpExceptionBuilder<?> builder) {
+		super(builder);
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param cause The caused-by exception.  Can be <jk>null</jk>.
 	 * @param msg The message.  Can be <jk>null</jk>.
-	 * @param args Optional {@link MessageFormat}-style arguments in the message.
+	 * @param args The message arguments.
 	 */
 	public PreconditionFailed(Throwable cause, String msg, Object...args) {
-		super(cause, STATUS_CODE, msg, args);
+		this(create().causedBy(cause).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 */
 	public PreconditionFailed() {
-		this((Throwable)null, REASON_PHRASE);
+		this(create().build());
 	}
 
 	/**
@@ -60,7 +79,7 @@ public class PreconditionFailed extends HttpException {
 	 * @param msg The message.  Can be <jk>null</jk>.
 	 */
 	public PreconditionFailed(String msg) {
-		this((Throwable)null, msg);
+		this(create().message(msg));
 	}
 
 	/**
@@ -70,7 +89,7 @@ public class PreconditionFailed extends HttpException {
 	 * @param args Optional {@link MessageFormat}-style arguments in the message.
 	 */
 	public PreconditionFailed(String msg, Object...args) {
-		this(null, msg, args);
+		this(create().message(msg, args));
 	}
 
 	/**
@@ -79,26 +98,15 @@ public class PreconditionFailed extends HttpException {
 	 * @param cause The cause.  Can be <jk>null</jk>.
 	 */
 	public PreconditionFailed(Throwable cause) {
-		this(cause, null);
+		this(create().causedBy(cause));
 	}
 
-	//------------------------------------------------------------------------------------------------------------------
-	// Fluent setters.
-	//------------------------------------------------------------------------------------------------------------------
-
-	// <FluentSetters>
-
-	@Override /* GENERATED - HttpException */
-	public PreconditionFailed header(String name, Object val) {
-		super.header(name, val);
-		return this;
-	}
-
-	@Override /* GENERATED - HttpException */
-	public PreconditionFailed status(int value) {
-		super.status(value);
-		return this;
+	/**
+	 * Creates a builder for this class initialized with the contents of this bean.
+	 *
+	 * @return A new builder bean.
+	 */
+	public HttpExceptionBuilder<PreconditionFailed> builder() {
+		return super.builder(PreconditionFailed.class).copyFrom(this);
 	}
-
-	// </FluentSetters>
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/PreconditionRequired.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/PreconditionRequired.java
index 1b79123..8e74676 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/PreconditionRequired.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/PreconditionRequired.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.http.exception.PreconditionRequired.*;
 import java.text.*;
 
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Exception representing an HTTP 428 (Precondition Required).
@@ -27,7 +26,6 @@ import org.apache.juneau.internal.*;
  * <br>Intended to prevent the 'lost update' problem, where a client GETs a resource's state, modifies it, and PUTs it back to the server, when meanwhile a third party has modified the state on the server, leading to a conflict.
  */
 @Response(code=STATUS_CODE, description=REASON_PHRASE)
-@FluentSetters
 public class PreconditionRequired extends HttpException {
 	private static final long serialVersionUID = 1L;
 
@@ -37,31 +35,52 @@ public class PreconditionRequired extends HttpException {
 	/** Reason phrase */
 	public static final String REASON_PHRASE = "Precondition Required";
 
+	/** Reusable unmodifiable instance. */
+	public static final PreconditionRequired INSTANCE = create().unmodifiable(true).build();
+
+	/**
+	 * Creates a builder for this class.
+	 *
+	 * @return A new builder bean.
+	 */
+	public static HttpExceptionBuilder<PreconditionRequired> create() {
+		return new HttpExceptionBuilder<>(PreconditionRequired.class).statusCode(STATUS_CODE).reasonPhrase(REASON_PHRASE);
+	}
+
 	/**
 	 * Constructor.
 	 *
-	 * @param cause The cause.  Can be <jk>null</jk>.
-	 * @param msg The message.  Can be <jk>null</jk>.
-	 * @param args Optional {@link MessageFormat}-style arguments in the message.
+	 * @param builder The builder containing the settings for this exception.
 	 */
-	public PreconditionRequired(Throwable cause, String msg, Object...args) {
-		super(cause, STATUS_CODE, msg, args);
+	public PreconditionRequired(HttpExceptionBuilder<?> builder) {
+		super(builder);
 	}
 
 	/**
 	 * Constructor.
 	 *
+	 * @param cause The caused-by exception.  Can be <jk>null</jk>.
 	 * @param msg The message.  Can be <jk>null</jk>.
+	 * @param args The message arguments.
 	 */
-	public PreconditionRequired(String msg) {
-		this((Throwable)null, msg);
+	public PreconditionRequired(Throwable cause, String msg, Object...args) {
+		this(create().causedBy(cause).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 */
 	public PreconditionRequired() {
-		this((Throwable)null, REASON_PHRASE);
+		this(create().build());
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param msg The message.  Can be <jk>null</jk>.
+	 */
+	public PreconditionRequired(String msg) {
+		this(create().message(msg));
 	}
 
 	/**
@@ -71,7 +90,7 @@ public class PreconditionRequired extends HttpException {
 	 * @param args Optional {@link MessageFormat}-style arguments in the message.
 	 */
 	public PreconditionRequired(String msg, Object...args) {
-		this(null, msg, args);
+		this(create().message(msg, args));
 	}
 
 	/**
@@ -80,26 +99,15 @@ public class PreconditionRequired extends HttpException {
 	 * @param cause The cause.  Can be <jk>null</jk>.
 	 */
 	public PreconditionRequired(Throwable cause) {
-		this(cause, null);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Fluent setters.
-	//------------------------------------------------------------------------------------------------------------------
-
-	// <FluentSetters>
-
-	@Override /* GENERATED - HttpException */
-	public PreconditionRequired header(String name, Object val) {
-		super.header(name, val);
-		return this;
+		this(create().causedBy(cause));
 	}
 
-	@Override /* GENERATED - HttpException */
-	public PreconditionRequired status(int value) {
-		super.status(value);
-		return this;
+	/**
+	 * Creates a builder for this class initialized with the contents of this bean.
+	 *
+	 * @return A new builder bean.
+	 */
+	public HttpExceptionBuilder<PreconditionRequired> builder() {
+		return super.builder(PreconditionRequired.class).copyFrom(this);
 	}
-
-	// </FluentSetters>
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/RangeNotSatisfiable.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/RangeNotSatisfiable.java
index 9fd3eed..a8739c8 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/RangeNotSatisfiable.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/RangeNotSatisfiable.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.http.exception.RangeNotSatisfiable.*;
 import java.text.*;
 
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Exception representing an HTTP 416 (Range Not Satisfiable).
@@ -27,7 +26,6 @@ import org.apache.juneau.internal.*;
  * <br>For example, if the client asked for a part of the file that lies beyond the end of the file.
  */
 @Response(code=STATUS_CODE, description=REASON_PHRASE)
-@FluentSetters
 public class RangeNotSatisfiable extends HttpException {
 	private static final long serialVersionUID = 1L;
 
@@ -37,31 +35,52 @@ public class RangeNotSatisfiable extends HttpException {
 	/** Reason phrase */
 	public static final String REASON_PHRASE = "Range Not Satisfiable";
 
+	/** Reusable unmodifiable instance. */
+	public static final RangeNotSatisfiable INSTANCE = create().unmodifiable(true).build();
+
+	/**
+	 * Creates a builder for this class.
+	 *
+	 * @return A new builder bean.
+	 */
+	public static HttpExceptionBuilder<RangeNotSatisfiable> create() {
+		return new HttpExceptionBuilder<>(RangeNotSatisfiable.class).statusCode(STATUS_CODE).reasonPhrase(REASON_PHRASE);
+	}
+
 	/**
 	 * Constructor.
 	 *
-	 * @param cause The cause.  Can be <jk>null</jk>.
-	 * @param msg The message.  Can be <jk>null</jk>.
-	 * @param args Optional {@link MessageFormat}-style arguments in the message.
+	 * @param builder The builder containing the settings for this exception.
 	 */
-	public RangeNotSatisfiable(Throwable cause, String msg, Object...args) {
-		super(cause, STATUS_CODE, msg, args);
+	public RangeNotSatisfiable(HttpExceptionBuilder<?> builder) {
+		super(builder);
 	}
 
 	/**
 	 * Constructor.
 	 *
+	 * @param cause The caused-by exception.  Can be <jk>null</jk>.
 	 * @param msg The message.  Can be <jk>null</jk>.
+	 * @param args The message arguments.
 	 */
-	public RangeNotSatisfiable(String msg) {
-		this((Throwable)null, msg);
+	public RangeNotSatisfiable(Throwable cause, String msg, Object...args) {
+		this(create().causedBy(cause).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 */
 	public RangeNotSatisfiable() {
-		this((Throwable)null, REASON_PHRASE);
+		this(create().build());
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param msg The message.  Can be <jk>null</jk>.
+	 */
+	public RangeNotSatisfiable(String msg) {
+		this(create().message(msg));
 	}
 
 	/**
@@ -71,7 +90,7 @@ public class RangeNotSatisfiable extends HttpException {
 	 * @param args Optional {@link MessageFormat}-style arguments in the message.
 	 */
 	public RangeNotSatisfiable(String msg, Object...args) {
-		this(null, msg, args);
+		this(create().message(msg, args));
 	}
 
 	/**
@@ -80,26 +99,15 @@ public class RangeNotSatisfiable extends HttpException {
 	 * @param cause The cause.  Can be <jk>null</jk>.
 	 */
 	public RangeNotSatisfiable(Throwable cause) {
-		this(cause, null);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Fluent setters.
-	//------------------------------------------------------------------------------------------------------------------
-
-	// <FluentSetters>
-
-	@Override /* GENERATED - HttpException */
-	public RangeNotSatisfiable header(String name, Object val) {
-		super.header(name, val);
-		return this;
+		this(create().causedBy(cause));
 	}
 
-	@Override /* GENERATED - HttpException */
-	public RangeNotSatisfiable status(int value) {
-		super.status(value);
-		return this;
+	/**
+	 * Creates a builder for this class initialized with the contents of this bean.
+	 *
+	 * @return A new builder bean.
+	 */
+	public HttpExceptionBuilder<RangeNotSatisfiable> builder() {
+		return super.builder(RangeNotSatisfiable.class).copyFrom(this);
 	}
-
-	// </FluentSetters>
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/RequestHeaderFieldsTooLarge.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/RequestHeaderFieldsTooLarge.java
index aec88c0..91ef8d9 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/RequestHeaderFieldsTooLarge.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/RequestHeaderFieldsTooLarge.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.http.exception.RequestHeaderFieldsTooLarge.*;
 import java.text.*;
 
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Exception representing an HTTP 431 (Request Header Fields Too Large).
@@ -26,7 +25,6 @@ import org.apache.juneau.internal.*;
  * The server is unwilling to process the request because either an individual header field, or all the header fields collectively, are too large.
  */
 @Response(code=STATUS_CODE, description=REASON_PHRASE)
-@FluentSetters
 public class RequestHeaderFieldsTooLarge extends HttpException {
 	private static final long serialVersionUID = 1L;
 
@@ -36,31 +34,52 @@ public class RequestHeaderFieldsTooLarge extends HttpException {
 	/** Reason phrase */
 	public static final String REASON_PHRASE = "Request Header Fields Too Large";
 
+	/** Reusable unmodifiable instance. */
+	public static final RequestHeaderFieldsTooLarge INSTANCE = create().unmodifiable(true).build();
+
+	/**
+	 * Creates a builder for this class.
+	 *
+	 * @return A new builder bean.
+	 */
+	public static HttpExceptionBuilder<RequestHeaderFieldsTooLarge> create() {
+		return new HttpExceptionBuilder<>(RequestHeaderFieldsTooLarge.class).statusCode(STATUS_CODE).reasonPhrase(REASON_PHRASE);
+	}
+
 	/**
 	 * Constructor.
 	 *
-	 * @param cause The cause.  Can be <jk>null</jk>.
-	 * @param msg The message.  Can be <jk>null</jk>.
-	 * @param args Optional {@link MessageFormat}-style arguments in the message.
+	 * @param builder The builder containing the settings for this exception.
 	 */
-	public RequestHeaderFieldsTooLarge(Throwable cause, String msg, Object...args) {
-		super(cause, STATUS_CODE, msg, args);
+	public RequestHeaderFieldsTooLarge(HttpExceptionBuilder<?> builder) {
+		super(builder);
 	}
 
 	/**
 	 * Constructor.
 	 *
+	 * @param cause The caused-by exception.  Can be <jk>null</jk>.
 	 * @param msg The message.  Can be <jk>null</jk>.
+	 * @param args The message arguments.
 	 */
-	public RequestHeaderFieldsTooLarge(String msg) {
-		this((Throwable)null, msg);
+	public RequestHeaderFieldsTooLarge(Throwable cause, String msg, Object...args) {
+		this(create().causedBy(cause).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 */
 	public RequestHeaderFieldsTooLarge() {
-		this((Throwable)null, REASON_PHRASE);
+		this(create().build());
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param msg The message.  Can be <jk>null</jk>.
+	 */
+	public RequestHeaderFieldsTooLarge(String msg) {
+		this(create().message(msg));
 	}
 
 	/**
@@ -70,7 +89,7 @@ public class RequestHeaderFieldsTooLarge extends HttpException {
 	 * @param args Optional {@link MessageFormat}-style arguments in the message.
 	 */
 	public RequestHeaderFieldsTooLarge(String msg, Object...args) {
-		this(null, msg, args);
+		this(create().message(msg, args));
 	}
 
 	/**
@@ -79,26 +98,15 @@ public class RequestHeaderFieldsTooLarge extends HttpException {
 	 * @param cause The cause.  Can be <jk>null</jk>.
 	 */
 	public RequestHeaderFieldsTooLarge(Throwable cause) {
-		this(cause, null);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Fluent setters.
-	//------------------------------------------------------------------------------------------------------------------
-
-	// <FluentSetters>
-
-	@Override /* GENERATED - HttpException */
-	public RequestHeaderFieldsTooLarge header(String name, Object val) {
-		super.header(name, val);
-		return this;
+		this(create().causedBy(cause));
 	}
 
-	@Override /* GENERATED - HttpException */
-	public RequestHeaderFieldsTooLarge status(int value) {
-		super.status(value);
-		return this;
+	/**
+	 * Creates a builder for this class initialized with the contents of this bean.
+	 *
+	 * @return A new builder bean.
+	 */
+	public HttpExceptionBuilder<RequestHeaderFieldsTooLarge> builder() {
+		return super.builder(RequestHeaderFieldsTooLarge.class).copyFrom(this);
 	}
-
-	// </FluentSetters>
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/ServiceUnavailable.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/ServiceUnavailable.java
index 3b609cc..fadcbaf 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/ServiceUnavailable.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/ServiceUnavailable.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.http.exception.ServiceUnavailable.*;
 import java.text.*;
 
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Exception representing an HTTP 503 (Service Unavailable).
@@ -27,7 +26,6 @@ import org.apache.juneau.internal.*;
  * <br>Generally, this is a temporary state.
  */
 @Response(code=STATUS_CODE, description=REASON_PHRASE)
-@FluentSetters
 public class ServiceUnavailable extends HttpException {
 	private static final long serialVersionUID = 1L;
 
@@ -37,31 +35,52 @@ public class ServiceUnavailable extends HttpException {
 	/** Reason phrase */
 	public static final String REASON_PHRASE = "Service Unavailable";
 
+	/** Reusable unmodifiable instance. */
+	public static final ServiceUnavailable INSTANCE = create().unmodifiable(true).build();
+
+	/**
+	 * Creates a builder for this class.
+	 *
+	 * @return A new builder bean.
+	 */
+	public static HttpExceptionBuilder<ServiceUnavailable> create() {
+		return new HttpExceptionBuilder<>(ServiceUnavailable.class).statusCode(STATUS_CODE).reasonPhrase(REASON_PHRASE);
+	}
+
 	/**
 	 * Constructor.
 	 *
-	 * @param cause The cause.  Can be <jk>null</jk>.
-	 * @param msg The message.  Can be <jk>null</jk>.
-	 * @param args Optional {@link MessageFormat}-style arguments in the message.
+	 * @param builder The builder containing the settings for this exception.
 	 */
-	public ServiceUnavailable(Throwable cause, String msg, Object...args) {
-		super(cause, STATUS_CODE, msg, args);
+	public ServiceUnavailable(HttpExceptionBuilder<?> builder) {
+		super(builder);
 	}
 
 	/**
 	 * Constructor.
 	 *
+	 * @param cause The caused-by exception.  Can be <jk>null</jk>.
 	 * @param msg The message.  Can be <jk>null</jk>.
+	 * @param args The message arguments.
 	 */
-	public ServiceUnavailable(String msg) {
-		this((Throwable)null, msg);
+	public ServiceUnavailable(Throwable cause, String msg, Object...args) {
+		this(create().causedBy(cause).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 */
 	public ServiceUnavailable() {
-		this((Throwable)null, REASON_PHRASE);
+		this(create().build());
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param msg The message.  Can be <jk>null</jk>.
+	 */
+	public ServiceUnavailable(String msg) {
+		this(create().message(msg));
 	}
 
 	/**
@@ -71,7 +90,7 @@ public class ServiceUnavailable extends HttpException {
 	 * @param args Optional {@link MessageFormat}-style arguments in the message.
 	 */
 	public ServiceUnavailable(String msg, Object...args) {
-		this(null, msg, args);
+		this(create().message(msg, args));
 	}
 
 	/**
@@ -80,26 +99,15 @@ public class ServiceUnavailable extends HttpException {
 	 * @param cause The cause.  Can be <jk>null</jk>.
 	 */
 	public ServiceUnavailable(Throwable cause) {
-		this(cause, null);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Fluent setters.
-	//------------------------------------------------------------------------------------------------------------------
-
-	// <FluentSetters>
-
-	@Override /* GENERATED - HttpException */
-	public ServiceUnavailable header(String name, Object val) {
-		super.header(name, val);
-		return this;
+		this(create().causedBy(cause));
 	}
 
-	@Override /* GENERATED - HttpException */
-	public ServiceUnavailable status(int value) {
-		super.status(value);
-		return this;
+	/**
+	 * Creates a builder for this class initialized with the contents of this bean.
+	 *
+	 * @return A new builder bean.
+	 */
+	public HttpExceptionBuilder<ServiceUnavailable> builder() {
+		return super.builder(ServiceUnavailable.class).copyFrom(this);
 	}
-
-	// </FluentSetters>
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/StandardExceptions.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/StandardExceptions.java
new file mode 100644
index 0000000..2cd8fcc
--- /dev/null
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/StandardExceptions.java
@@ -0,0 +1,491 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.http.exception;
+
+/**
+ * Standard predefined HTTP exception responses.
+ */
+public class StandardExceptions {
+
+	/**
+	 * A synonym for {@link BadRequest#INSTANCE}.
+	 */
+	public static final BadRequest BAD_REQUEST = BadRequest.INSTANCE;
+
+	/**
+	 * A synonym for {@link Conflict#INSTANCE}.
+	 */
+	public static final Conflict CONFLICT = Conflict.INSTANCE;
+
+	/**
+	 * A synonym for {@link ExpectationFailed#INSTANCE}.
+	 */
+	public static final ExpectationFailed EXPECTATION_FAILED = ExpectationFailed.INSTANCE;
+
+	/**
+	 * A synonym for {@link FailedDependency#INSTANCE}.
+	 */
+	public static final FailedDependency FAILED_DEPENDENCY = FailedDependency.INSTANCE;
+
+	/**
+	 * A synonym for {@link Forbidden#INSTANCE}.
+	 */
+	public static final Forbidden FORBIDDEN = Forbidden.INSTANCE;
+
+	/**
+	 * A synonym for {@link Gone#INSTANCE}.
+	 */
+	public static final Gone GONE = Gone.INSTANCE;
+
+	/**
+	 * A synonym for {@link HttpVersionNotSupported#INSTANCE}.
+	 */
+	public static final HttpVersionNotSupported HTTP_VERSION_NOT_SUPPORTED = HttpVersionNotSupported.INSTANCE;
+
+	/**
+	 * A synonym for {@link InsufficientStorage#INSTANCE}.
+	 */
+	public static final InsufficientStorage INSUFFICIENT_STORAGE = InsufficientStorage.INSTANCE;
+
+	/**
+	 * A synonym for {@link InternalServerError#INSTANCE}.
+	 */
+	public static final InternalServerError INTERNAL_SERVER_ERROR = InternalServerError.INSTANCE;
+
+	/**
+	 * A synonym for {@link LengthRequired#INSTANCE}.
+	 */
+	public static final LengthRequired LENGTH_REQUIRED = LengthRequired.INSTANCE;
+
+	/**
+	 * A synonym for {@link Locked#INSTANCE}.
+	 */
+	public static final Locked LOCKED = Locked.INSTANCE;
+
+	/**
+	 * A synonym for {@link LoopDetected#INSTANCE}.
+	 */
+	public static final LoopDetected LOOP_DETECTED = LoopDetected.INSTANCE;
+
+	/**
+	 * A synonym for {@link MethodNotAllowed#INSTANCE}.
+	 */
+	public static final MethodNotAllowed METHOD_NOT_ALLOWED = MethodNotAllowed.INSTANCE;
+
+	/**
+	 * A synonym for {@link MisdirectedRequest#INSTANCE}.
+	 */
+	public static final MisdirectedRequest MISDIRECTED_REQUEST = MisdirectedRequest.INSTANCE;
+
+	/**
+	 * A synonym for {@link NetworkAuthenticationRequired#INSTANCE}.
+	 */
+	public static final NetworkAuthenticationRequired NETWORK_AUTHENTICATION_REQUIRED = NetworkAuthenticationRequired.INSTANCE;
+
+	/**
+	 * A synonym for {@link NotAcceptable#INSTANCE}.
+	 */
+	public static final NotAcceptable NOT_ACCEPTABLE = NotAcceptable.INSTANCE;
+
+	/**
+	 * A synonym for {@link NotExtended#INSTANCE}.
+	 */
+	public static final NotExtended NOT_EXTENDED = NotExtended.INSTANCE;
+
+	/**
+	 * A synonym for {@link NotFound#INSTANCE}.
+	 */
+	public static final NotFound NOT_FOUND = NotFound.INSTANCE;
+
+	/**
+	 * A synonym for {@link NotImplemented#INSTANCE}.
+	 */
+	public static final NotImplemented NOT_IMPLEMENTED = NotImplemented.INSTANCE;
+
+	/**
+	 * A synonym for {@link PayloadTooLarge#INSTANCE}.
+	 */
+	public static final PayloadTooLarge PAYLOAD_TOO_LARGE = PayloadTooLarge.INSTANCE;
+
+	/**
+	 * A synonym for {@link PreconditionFailed#INSTANCE}.
+	 */
+	public static final PreconditionFailed PRECONDITION_FAILED = PreconditionFailed.INSTANCE;
+
+	/**
+	 * A synonym for {@link PreconditionRequired#INSTANCE}.
+	 */
+	public static final PreconditionRequired PRECONDITION_REQUIRED = PreconditionRequired.INSTANCE;
+
+	/**
+	 * A synonym for {@link RangeNotSatisfiable#INSTANCE}.
+	 */
+	public static final RangeNotSatisfiable RANGE_NOT_SATISFIABLE = RangeNotSatisfiable.INSTANCE;
+
+	/**
+	 * A synonym for {@link RequestHeaderFieldsTooLarge#INSTANCE}.
+	 */
+	public static final RequestHeaderFieldsTooLarge REQUEST_HEADER_FIELDS_TOO_LARGE = RequestHeaderFieldsTooLarge.INSTANCE;
+
+	/**
+	 * A synonym for {@link ServiceUnavailable#INSTANCE}.
+	 */
+	public static final ServiceUnavailable SERVICE_UNAVAILABLE = ServiceUnavailable.INSTANCE;
+
+	/**
+	 * A synonym for {@link TooManyRequests#INSTANCE}.
+	 */
+	public static final TooManyRequests TOO_MANY_REQUESTS = TooManyRequests.INSTANCE;
+
+	/**
+	 * A synonym for {@link Unauthorized#INSTANCE}.
+	 */
+	public static final Unauthorized UNAUTHORIZED = Unauthorized.INSTANCE;
+
+	/**
+	 * A synonym for {@link UnavailableForLegalReasons#INSTANCE}.
+	 */
+	public static final UnavailableForLegalReasons UNAVAILABLE_FOR_LEGAL_REASONS = UnavailableForLegalReasons.INSTANCE;
+
+	/**
+	 * A synonym for {@link UnprocessableEntity#INSTANCE}.
+	 */
+	public static final UnprocessableEntity UNPROCESSABLE_ENTITIY = UnprocessableEntity.INSTANCE;
+
+	/**
+	 * A synonym for {@link UnsupportedMediaType#INSTANCE}.
+	 */
+	public static final UnsupportedMediaType UNSUPPORTED_MEDIA_TYPE = UnsupportedMediaType.INSTANCE;
+
+	/**
+	 * A synonym for {@link UpgradeRequired#INSTANCE}.
+	 */
+	public static final UpgradeRequired UPGRADE_REQUIRED = UpgradeRequired.INSTANCE;
+
+	/**
+	 * A synonym for {@link UriTooLong#INSTANCE}.
+	 */
+	public static final UriTooLong URI_TOO_LONG = UriTooLong.INSTANCE;
+
+	/**
+	 * A synonym for {@link VariantAlsoNegotiates#INSTANCE}.
+	 */
+	public static final VariantAlsoNegotiates VARIANT_ALSO_NEGOTIATES = VariantAlsoNegotiates.INSTANCE;
+
+
+	/**
+	 * A shortcut for calling {@link BadRequest#create()}.
+	 *
+	 * @return A new bean builder.
+	 */
+	public static HttpExceptionBuilder<BadRequest> badRequest() {
+		return BadRequest.create();
+	}
+
+	/**
+	 * A shortcut for calling {@link Conflict#create()}.
+	 *
+	 * @return A new bean builder.
+	 */
+	public static HttpExceptionBuilder<Conflict> conflict() {
+		return Conflict.create();
+	}
+
+	/**
+	 * A shortcut for calling {@link ExpectationFailed#create()}.
+	 *
+	 * @return A new bean builder.
+	 */
+	public static HttpExceptionBuilder<ExpectationFailed> expectationFailed() {
+		return ExpectationFailed.create();
+	}
+
+	/**
+	 * A shortcut for calling {@link FailedDependency#create()}.
+	 *
+	 * @return A new bean builder.
+	 */
+	public static HttpExceptionBuilder<FailedDependency> failedDependency() {
+		return FailedDependency.create();
+	}
+
+	/**
+	 * A shortcut for calling {@link Forbidden#create()}.
+	 *
+	 * @return A new bean builder.
+	 */
+	public static HttpExceptionBuilder<Forbidden> forbidden() {
+		return Forbidden.create();
+	}
+
+	/**
+	 * A shortcut for calling {@link Gone#create()}.
+	 *
+	 * @return A new bean builder.
+	 */
+	public static HttpExceptionBuilder<Gone> gone() {
+		return Gone.create();
+	}
+
+	/**
+	 * A shortcut for calling {@link HttpException#create()}.
+	 *
+	 * @return A new bean builder.
+	 */
+	public static HttpExceptionBuilder<HttpException> httpException() {
+		return HttpException.create(HttpException.class);
+	}
+
+	/**
+	 * A shortcut for calling {@link HttpVersionNotSupported#create()}.
+	 *
+	 * @return A new bean builder.
+	 */
+	public static HttpExceptionBuilder<HttpVersionNotSupported> httpVersionNotSupported() {
+		return HttpVersionNotSupported.create();
+	}
+
+	/**
+	 * A shortcut for calling {@link InsufficientStorage#create()}.
+	 *
+	 * @return A new bean builder.
+	 */
+	public static HttpExceptionBuilder<InsufficientStorage> insufficientStorage() {
+		return InsufficientStorage.create();
+	}
+
+	/**
+	 * A shortcut for calling {@link InternalServerError#create()}.
+	 *
+	 * @return A new bean builder.
+	 */
+	public static HttpExceptionBuilder<InternalServerError> internalServerError() {
+		return InternalServerError.create();
+	}
+
+	/**
+	 * A shortcut for calling {@link LengthRequired#create()}.
+	 *
+	 * @return A new bean builder.
+	 */
+	public static HttpExceptionBuilder<LengthRequired> lengthRequired() {
+		return LengthRequired.create();
+	}
+
+	/**
+	 * A shortcut for calling {@link Locked#create()}.
+	 *
+	 * @return A new bean builder.
+	 */
+	public static HttpExceptionBuilder<Locked> locked() {
+		return Locked.create();
+	}
+
+	/**
+	 * A shortcut for calling {@link LoopDetected#create()}.
+	 *
+	 * @return A new bean builder.
+	 */
+	public static HttpExceptionBuilder<LoopDetected> loopDetected() {
+		return LoopDetected.create();
+	}
+
+	/**
+	 * A shortcut for calling {@link MethodNotAllowed#create()}.
+	 *
+	 * @return A new bean builder.
+	 */
+	public static HttpExceptionBuilder<MethodNotAllowed> methodNotAllowed() {
+		return MethodNotAllowed.create();
+	}
+
+	/**
+	 * A shortcut for calling {@link MisdirectedRequest#create()}.
+	 *
+	 * @return A new bean builder.
+	 */
+	public static HttpExceptionBuilder<MisdirectedRequest> misdirectedRequest() {
+		return MisdirectedRequest.create();
+	}
+
+	/**
+	 * A shortcut for calling {@link NetworkAuthenticationRequired#create()}.
+	 *
+	 * @return A new bean builder.
+	 */
+	public static HttpExceptionBuilder<NetworkAuthenticationRequired> networkAuthenticationRequired() {
+		return NetworkAuthenticationRequired.create();
+	}
+
+	/**
+	 * A shortcut for calling {@link NotAcceptable#create()}.
+	 *
+	 * @return A new bean builder.
+	 */
+	public static HttpExceptionBuilder<NotAcceptable> notAcceptable() {
+		return NotAcceptable.create();
+	}
+
+	/**
+	 * A shortcut for calling {@link NotExtended#create()}.
+	 *
+	 * @return A new bean builder.
+	 */
+	public static HttpExceptionBuilder<NotExtended> notExtended() {
+		return NotExtended.create();
+	}
+
+	/**
+	 * A shortcut for calling {@link NotFound#create()}.
+	 *
+	 * @return A new bean builder.
+	 */
+	public static HttpExceptionBuilder<NotFound> notFound() {
+		return NotFound.create();
+	}
+
+	/**
+	 * A shortcut for calling {@link NotImplemented#create()}.
+	 *
+	 * @return A new bean builder.
+	 */
+	public static HttpExceptionBuilder<NotImplemented> notImplemented() {
+		return NotImplemented.create();
+	}
+
+	/**
+	 * A shortcut for calling {@link PayloadTooLarge#create()}.
+	 *
+	 * @return A new bean builder.
+	 */
+	public static HttpExceptionBuilder<PayloadTooLarge> payloadTooLarge() {
+		return PayloadTooLarge.create();
+	}
+
+	/**
+	 * A shortcut for calling {@link PreconditionFailed#create()}.
+	 *
+	 * @return A new bean builder.
+	 */
+	public static HttpExceptionBuilder<PreconditionFailed> preconditionFailed() {
+		return PreconditionFailed.create();
+	}
+
+	/**
+	 * A shortcut for calling {@link PreconditionRequired#create()}.
+	 *
+	 * @return A new bean builder.
+	 */
+	public static HttpExceptionBuilder<PreconditionRequired> preconditionRequired() {
+		return PreconditionRequired.create();
+	}
+
+	/**
+	 * A shortcut for calling {@link RangeNotSatisfiable#create()}.
+	 *
+	 * @return A new bean builder.
+	 */
+	public static HttpExceptionBuilder<RangeNotSatisfiable> rangeNotSatisfiable() {
+		return RangeNotSatisfiable.create();
+	}
+
+	/**
+	 * A shortcut for calling {@link RequestHeaderFieldsTooLarge#create()}.
+	 *
+	 * @return A new bean builder.
+	 */
+	public static HttpExceptionBuilder<RequestHeaderFieldsTooLarge> requestHeaderFieldsTooLarge() {
+		return RequestHeaderFieldsTooLarge.create();
+	}
+
+	/**
+	 * A shortcut for calling {@link ServiceUnavailable#create()}.
+	 *
+	 * @return A new bean builder.
+	 */
+	public static HttpExceptionBuilder<ServiceUnavailable> serviceUnavailable() {
+		return ServiceUnavailable.create();
+	}
+
+	/**
+	 * A shortcut for calling {@link TooManyRequests#create()}.
+	 *
+	 * @return A new bean builder.
+	 */
+	public static HttpExceptionBuilder<TooManyRequests> tooManyRequests() {
+		return TooManyRequests.create();
+	}
+
+	/**
+	 * A shortcut for calling {@link Unauthorized#create()}.
+	 *
+	 * @return A new bean builder.
+	 */
+	public static HttpExceptionBuilder<Unauthorized> unauthorized() {
+		return Unauthorized.create();
+	}
+
+	/**
+	 * A shortcut for calling {@link UnavailableForLegalReasons#create()}.
+	 *
+	 * @return A new bean builder.
+	 */
+	public static HttpExceptionBuilder<UnavailableForLegalReasons> unavailableForLegalReasons() {
+		return UnavailableForLegalReasons.create();
+	}
+
+	/**
+	 * A shortcut for calling {@link UnprocessableEntity#create()}.
+	 *
+	 * @return A new bean builder.
+	 */
+	public static HttpExceptionBuilder<UnprocessableEntity> unprocessableEntity() {
+		return UnprocessableEntity.create();
+	}
+
+	/**
+	 * A shortcut for calling {@link UnsupportedMediaType#create()}.
+	 *
+	 * @return A new bean builder.
+	 */
+	public static HttpExceptionBuilder<UnsupportedMediaType> unsupportedMediaType() {
+		return UnsupportedMediaType.create();
+	}
+
+	/**
+	 * A shortcut for calling {@link UpgradeRequired#create()}.
+	 *
+	 * @return A new bean builder.
+	 */
+	public static HttpExceptionBuilder<UpgradeRequired> upgradeRequired() {
+		return UpgradeRequired.create();
+	}
+
+	/**
+	 * A shortcut for calling {@link UriTooLong#create()}.
+	 *
+	 * @return A new bean builder.
+	 */
+	public static HttpExceptionBuilder<UriTooLong> uriTooLong() {
+		return UriTooLong.create();
+	}
+
+	/**
+	 * A shortcut for calling {@link VariantAlsoNegotiates#create()}.
+	 *
+	 * @return A new bean builder.
+	 */
+	public static HttpExceptionBuilder<VariantAlsoNegotiates> variantAlsoNegotiates() {
+		return VariantAlsoNegotiates.create();
+	}
+}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/TooManyRequests.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/TooManyRequests.java
index 2e055d3..29e5c21 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/TooManyRequests.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/TooManyRequests.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.http.exception.TooManyRequests.*;
 import java.text.*;
 
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Exception representing an HTTP 429 (Too Many Requests).
@@ -27,7 +26,6 @@ import org.apache.juneau.internal.*;
  * <br>Intended for use with rate-limiting schemes.
  */
 @Response(code=STATUS_CODE, description=REASON_PHRASE)
-@FluentSetters
 public class TooManyRequests extends HttpException {
 	private static final long serialVersionUID = 1L;
 
@@ -37,31 +35,52 @@ public class TooManyRequests extends HttpException {
 	/** Reason phrase */
 	public static final String REASON_PHRASE = "Too Many Requests";
 
+	/** Reusable unmodifiable instance. */
+	public static final TooManyRequests INSTANCE = create().unmodifiable(true).build();
+
+	/**
+	 * Creates a builder for this class.
+	 *
+	 * @return A new builder bean.
+	 */
+	public static HttpExceptionBuilder<TooManyRequests> create() {
+		return new HttpExceptionBuilder<>(TooManyRequests.class).statusCode(STATUS_CODE).reasonPhrase(REASON_PHRASE);
+	}
+
 	/**
 	 * Constructor.
 	 *
-	 * @param cause The cause.  Can be <jk>null</jk>.
-	 * @param msg The message.  Can be <jk>null</jk>.
-	 * @param args Optional {@link MessageFormat}-style arguments in the message.
+	 * @param builder The builder containing the settings for this exception.
 	 */
-	public TooManyRequests(Throwable cause, String msg, Object...args) {
-		super(cause, STATUS_CODE, msg, args);
+	public TooManyRequests(HttpExceptionBuilder<?> builder) {
+		super(builder);
 	}
 
 	/**
 	 * Constructor.
 	 *
+	 * @param cause The caused-by exception.  Can be <jk>null</jk>.
 	 * @param msg The message.  Can be <jk>null</jk>.
+	 * @param args The message arguments.
 	 */
-	public TooManyRequests(String msg) {
-		this((Throwable)null, msg);
+	public TooManyRequests(Throwable cause, String msg, Object...args) {
+		this(create().causedBy(cause).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 */
 	public TooManyRequests() {
-		this((Throwable)null, REASON_PHRASE);
+		this(create().build());
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param msg The message.  Can be <jk>null</jk>.
+	 */
+	public TooManyRequests(String msg) {
+		this(create().message(msg));
 	}
 
 	/**
@@ -71,7 +90,7 @@ public class TooManyRequests extends HttpException {
 	 * @param args Optional {@link MessageFormat}-style arguments in the message.
 	 */
 	public TooManyRequests(String msg, Object...args) {
-		this(null, msg, args);
+		this(create().message(msg, args));
 	}
 
 	/**
@@ -80,26 +99,15 @@ public class TooManyRequests extends HttpException {
 	 * @param cause The cause.  Can be <jk>null</jk>.
 	 */
 	public TooManyRequests(Throwable cause) {
-		this(cause, null);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Fluent setters.
-	//------------------------------------------------------------------------------------------------------------------
-
-	// <FluentSetters>
-
-	@Override /* GENERATED - HttpException */
-	public TooManyRequests header(String name, Object val) {
-		super.header(name, val);
-		return this;
+		this(create().causedBy(cause));
 	}
 
-	@Override /* GENERATED - HttpException */
-	public TooManyRequests status(int value) {
-		super.status(value);
-		return this;
+	/**
+	 * Creates a builder for this class initialized with the contents of this bean.
+	 *
+	 * @return A new builder bean.
+	 */
+	public HttpExceptionBuilder<TooManyRequests> builder() {
+		return super.builder(TooManyRequests.class).copyFrom(this);
 	}
-
-	// </FluentSetters>
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/Unauthorized.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/Unauthorized.java
index 3dbd83e..9f1a971 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/Unauthorized.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/Unauthorized.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.http.exception.Unauthorized.*;
 import java.text.*;
 
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Exception representing an HTTP 401 (Unauthorized).
@@ -29,7 +28,6 @@ import org.apache.juneau.internal.*;
  * <br>Note: Some sites issue HTTP 401 when an IP address is banned from the website (usually the website domain) and that specific address is refused permission to access a website.
  */
 @Response(code=STATUS_CODE, description=REASON_PHRASE)
-@FluentSetters
 public class Unauthorized extends HttpException {
 	private static final long serialVersionUID = 1L;
 
@@ -39,31 +37,52 @@ public class Unauthorized extends HttpException {
 	/** Reason phrase */
 	public static final String REASON_PHRASE = "Unauthorized";
 
+	/** Reusable unmodifiable instance. */
+	public static final Unauthorized INSTANCE = create().unmodifiable(true).build();
+
+	/**
+	 * Creates a builder for this class.
+	 *
+	 * @return A new builder bean.
+	 */
+	public static HttpExceptionBuilder<Unauthorized> create() {
+		return new HttpExceptionBuilder<>(Unauthorized.class).statusCode(STATUS_CODE).reasonPhrase(REASON_PHRASE);
+	}
+
 	/**
 	 * Constructor.
 	 *
-	 * @param cause The cause.  Can be <jk>null</jk>.
-	 * @param msg The message.  Can be <jk>null</jk>.
-	 * @param args Optional {@link MessageFormat}-style arguments in the message.
+	 * @param builder The builder containing the settings for this exception.
 	 */
-	public Unauthorized(Throwable cause, String msg, Object...args) {
-		super(cause, STATUS_CODE, msg, args);
+	public Unauthorized(HttpExceptionBuilder<?> builder) {
+		super(builder);
 	}
 
 	/**
 	 * Constructor.
 	 *
+	 * @param cause The caused-by exception.  Can be <jk>null</jk>.
 	 * @param msg The message.  Can be <jk>null</jk>.
+	 * @param args The message arguments.
 	 */
-	public Unauthorized(String msg) {
-		this((Throwable)null, msg);
+	public Unauthorized(Throwable cause, String msg, Object...args) {
+		this(create().causedBy(cause).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 */
 	public Unauthorized() {
-		this((Throwable)null, REASON_PHRASE);
+		this(create().build());
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param msg The message.  Can be <jk>null</jk>.
+	 */
+	public Unauthorized(String msg) {
+		this(create().message(msg));
 	}
 
 	/**
@@ -73,7 +92,7 @@ public class Unauthorized extends HttpException {
 	 * @param args Optional {@link MessageFormat}-style arguments in the message.
 	 */
 	public Unauthorized(String msg, Object...args) {
-		this(null, msg, args);
+		this(create().message(msg, args));
 	}
 
 	/**
@@ -82,26 +101,15 @@ public class Unauthorized extends HttpException {
 	 * @param cause The cause.  Can be <jk>null</jk>.
 	 */
 	public Unauthorized(Throwable cause) {
-		this(cause, null);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Fluent setters.
-	//------------------------------------------------------------------------------------------------------------------
-
-	// <FluentSetters>
-
-	@Override /* GENERATED - HttpException */
-	public Unauthorized header(String name, Object val) {
-		super.header(name, val);
-		return this;
+		this(create().causedBy(cause));
 	}
 
-	@Override /* GENERATED - HttpException */
-	public Unauthorized status(int value) {
-		super.status(value);
-		return this;
+	/**
+	 * Creates a builder for this class initialized with the contents of this bean.
+	 *
+	 * @return A new builder bean.
+	 */
+	public HttpExceptionBuilder<Unauthorized> builder() {
+		return super.builder(Unauthorized.class).copyFrom(this);
 	}
-
-	// </FluentSetters>
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/UnavailableForLegalReasons.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/UnavailableForLegalReasons.java
index b6577ea..6054641 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/UnavailableForLegalReasons.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/UnavailableForLegalReasons.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.http.exception.UnavailableForLegalReasons.*;
 import java.text.*;
 
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Exception representing an HTTP 451 (Unavailable For Legal Reasons).
@@ -26,7 +25,6 @@ import org.apache.juneau.internal.*;
  * A server operator has received a legal demand to deny access to a resource or to a set of resources that includes the requested resource.
  */
 @Response(code=STATUS_CODE, description=REASON_PHRASE)
-@FluentSetters
 public class UnavailableForLegalReasons extends HttpException {
 	private static final long serialVersionUID = 1L;
 
@@ -36,31 +34,52 @@ public class UnavailableForLegalReasons extends HttpException {
 	/** Reason phrase */
 	public static final String REASON_PHRASE = "Unavailable For Legal Reasons";
 
+	/** Reusable unmodifiable instance. */
+	public static final UnavailableForLegalReasons INSTANCE = create().unmodifiable(true).build();
+
+	/**
+	 * Creates a builder for this class.
+	 *
+	 * @return A new builder bean.
+	 */
+	public static HttpExceptionBuilder<UnavailableForLegalReasons> create() {
+		return new HttpExceptionBuilder<>(UnavailableForLegalReasons.class).statusCode(STATUS_CODE).reasonPhrase(REASON_PHRASE);
+	}
+
 	/**
 	 * Constructor.
 	 *
-	 * @param cause The cause.  Can be <jk>null</jk>.
-	 * @param msg The message.  Can be <jk>null</jk>.
-	 * @param args Optional {@link MessageFormat}-style arguments in the message.
+	 * @param builder The builder containing the settings for this exception.
 	 */
-	public UnavailableForLegalReasons(Throwable cause, String msg, Object...args) {
-		super(cause, STATUS_CODE, msg, args);
+	public UnavailableForLegalReasons(HttpExceptionBuilder<?> builder) {
+		super(builder);
 	}
 
 	/**
 	 * Constructor.
 	 *
+	 * @param cause The caused-by exception.  Can be <jk>null</jk>.
 	 * @param msg The message.  Can be <jk>null</jk>.
+	 * @param args The message arguments.
 	 */
-	public UnavailableForLegalReasons(String msg) {
-		this((Throwable)null, msg);
+	public UnavailableForLegalReasons(Throwable cause, String msg, Object...args) {
+		this(create().causedBy(cause).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 */
 	public UnavailableForLegalReasons() {
-		this((Throwable)null, REASON_PHRASE);
+		this(create().build());
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param msg The message.  Can be <jk>null</jk>.
+	 */
+	public UnavailableForLegalReasons(String msg) {
+		this(create().message(msg));
 	}
 
 	/**
@@ -70,7 +89,7 @@ public class UnavailableForLegalReasons extends HttpException {
 	 * @param args Optional {@link MessageFormat}-style arguments in the message.
 	 */
 	public UnavailableForLegalReasons(String msg, Object...args) {
-		this(null, msg, args);
+		this(create().message(msg, args));
 	}
 
 	/**
@@ -79,26 +98,15 @@ public class UnavailableForLegalReasons extends HttpException {
 	 * @param cause The cause.  Can be <jk>null</jk>.
 	 */
 	public UnavailableForLegalReasons(Throwable cause) {
-		this(cause, null);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Fluent setters.
-	//------------------------------------------------------------------------------------------------------------------
-
-	// <FluentSetters>
-
-	@Override /* GENERATED - HttpException */
-	public UnavailableForLegalReasons header(String name, Object val) {
-		super.header(name, val);
-		return this;
+		this(create().causedBy(cause));
 	}
 
-	@Override /* GENERATED - HttpException */
-	public UnavailableForLegalReasons status(int value) {
-		super.status(value);
-		return this;
+	/**
+	 * Creates a builder for this class initialized with the contents of this bean.
+	 *
+	 * @return A new builder bean.
+	 */
+	public HttpExceptionBuilder<UnavailableForLegalReasons> builder() {
+		return super.builder(UnavailableForLegalReasons.class).copyFrom(this);
 	}
-
-	// </FluentSetters>
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/UnprocessableEntity.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/UnprocessableEntity.java
index 511e297..e334ebc 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/UnprocessableEntity.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/UnprocessableEntity.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.http.exception.UnprocessableEntity.*;
 import java.text.*;
 
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Exception representing an HTTP 422 (Unprocessable Entity).
@@ -26,7 +25,6 @@ import org.apache.juneau.internal.*;
  * The request was well-formed but was unable to be followed due to semantic errors.
  */
 @Response(code=STATUS_CODE, description=REASON_PHRASE)
-@FluentSetters
 public class UnprocessableEntity extends HttpException {
 	private static final long serialVersionUID = 1L;
 
@@ -36,31 +34,52 @@ public class UnprocessableEntity extends HttpException {
 	/** Reason phrase */
 	public static final String REASON_PHRASE = "Unprocessable Entity";
 
+	/** Reusable unmodifiable instance. */
+	public static final UnprocessableEntity INSTANCE = create().unmodifiable(true).build();
+
+	/**
+	 * Creates a builder for this class.
+	 *
+	 * @return A new builder bean.
+	 */
+	public static HttpExceptionBuilder<UnprocessableEntity> create() {
+		return new HttpExceptionBuilder<>(UnprocessableEntity.class).statusCode(STATUS_CODE).reasonPhrase(REASON_PHRASE);
+	}
+
 	/**
 	 * Constructor.
 	 *
-	 * @param cause The cause.  Can be <jk>null</jk>.
-	 * @param msg The message.  Can be <jk>null</jk>.
-	 * @param args Optional {@link MessageFormat}-style arguments in the message.
+	 * @param builder The builder containing the settings for this exception.
 	 */
-	public UnprocessableEntity(Throwable cause, String msg, Object...args) {
-		super(cause, STATUS_CODE, msg, args);
+	public UnprocessableEntity(HttpExceptionBuilder<?> builder) {
+		super(builder);
 	}
 
 	/**
 	 * Constructor.
 	 *
+	 * @param cause The caused-by exception.  Can be <jk>null</jk>.
 	 * @param msg The message.  Can be <jk>null</jk>.
+	 * @param args The message arguments.
 	 */
-	public UnprocessableEntity(String msg) {
-		this((Throwable)null, msg);
+	public UnprocessableEntity(Throwable cause, String msg, Object...args) {
+		this(create().causedBy(cause).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 */
 	public UnprocessableEntity() {
-		this((Throwable)null, REASON_PHRASE);
+		this(create().build());
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param msg The message.  Can be <jk>null</jk>.
+	 */
+	public UnprocessableEntity(String msg) {
+		this(create().message(msg));
 	}
 
 	/**
@@ -70,7 +89,7 @@ public class UnprocessableEntity extends HttpException {
 	 * @param args Optional {@link MessageFormat}-style arguments in the message.
 	 */
 	public UnprocessableEntity(String msg, Object...args) {
-		this(null, msg, args);
+		this(create().message(msg, args));
 	}
 
 	/**
@@ -79,26 +98,15 @@ public class UnprocessableEntity extends HttpException {
 	 * @param cause The cause.  Can be <jk>null</jk>.
 	 */
 	public UnprocessableEntity(Throwable cause) {
-		this(cause, null);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Fluent setters.
-	//------------------------------------------------------------------------------------------------------------------
-
-	// <FluentSetters>
-
-	@Override /* GENERATED - HttpException */
-	public UnprocessableEntity header(String name, Object val) {
-		super.header(name, val);
-		return this;
+		this(create().causedBy(cause));
 	}
 
-	@Override /* GENERATED - HttpException */
-	public UnprocessableEntity status(int value) {
-		super.status(value);
-		return this;
+	/**
+	 * Creates a builder for this class initialized with the contents of this bean.
+	 *
+	 * @return A new builder bean.
+	 */
+	public HttpExceptionBuilder<UnprocessableEntity> builder() {
+		return super.builder(UnprocessableEntity.class).copyFrom(this);
 	}
-
-	// </FluentSetters>
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/UnsupportedMediaType.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/UnsupportedMediaType.java
index 56cedac..3264f95 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/UnsupportedMediaType.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/UnsupportedMediaType.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.http.exception.UnsupportedMediaType.*;
 import java.text.*;
 
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Exception representing an HTTP 415 (Unsupported Media Type).
@@ -27,7 +26,6 @@ import org.apache.juneau.internal.*;
  * <br>For example, the client uploads an image as image/svg+xml, but the server requires that images use a different format.
  */
 @Response(code=STATUS_CODE, description=REASON_PHRASE)
-@FluentSetters
 public class UnsupportedMediaType extends HttpException {
 	private static final long serialVersionUID = 1L;
 
@@ -37,31 +35,52 @@ public class UnsupportedMediaType extends HttpException {
 	/** Reason phrase */
 	public static final String REASON_PHRASE = "Unsupported Media Type";
 
+	/** Reusable unmodifiable instance. */
+	public static final UnsupportedMediaType INSTANCE = create().unmodifiable(true).build();
+
+	/**
+	 * Creates a builder for this class.
+	 *
+	 * @return A new builder bean.
+	 */
+	public static HttpExceptionBuilder<UnsupportedMediaType> create() {
+		return new HttpExceptionBuilder<>(UnsupportedMediaType.class).statusCode(STATUS_CODE).reasonPhrase(REASON_PHRASE);
+	}
+
 	/**
 	 * Constructor.
 	 *
-	 * @param cause The cause.  Can be <jk>null</jk>.
-	 * @param msg The message.  Can be <jk>null</jk>.
-	 * @param args Optional {@link MessageFormat}-style arguments in the message.
+	 * @param builder The builder containing the settings for this exception.
 	 */
-	public UnsupportedMediaType(Throwable cause, String msg, Object...args) {
-		super(cause, STATUS_CODE, msg, args);
+	public UnsupportedMediaType(HttpExceptionBuilder<?> builder) {
+		super(builder);
 	}
 
 	/**
 	 * Constructor.
 	 *
+	 * @param cause The caused-by exception.  Can be <jk>null</jk>.
 	 * @param msg The message.  Can be <jk>null</jk>.
+	 * @param args The message arguments.
 	 */
-	public UnsupportedMediaType(String msg) {
-		this((Throwable)null, msg);
+	public UnsupportedMediaType(Throwable cause, String msg, Object...args) {
+		this(create().causedBy(cause).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 */
 	public UnsupportedMediaType() {
-		this((Throwable)null, REASON_PHRASE);
+		this(create().build());
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param msg The message.  Can be <jk>null</jk>.
+	 */
+	public UnsupportedMediaType(String msg) {
+		this(create().message(msg));
 	}
 
 	/**
@@ -71,7 +90,7 @@ public class UnsupportedMediaType extends HttpException {
 	 * @param args Optional {@link MessageFormat}-style arguments in the message.
 	 */
 	public UnsupportedMediaType(String msg, Object...args) {
-		this(null, msg, args);
+		this(create().message(msg, args));
 	}
 
 	/**
@@ -80,26 +99,15 @@ public class UnsupportedMediaType extends HttpException {
 	 * @param cause The cause.  Can be <jk>null</jk>.
 	 */
 	public UnsupportedMediaType(Throwable cause) {
-		this(cause, null);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Fluent setters.
-	//------------------------------------------------------------------------------------------------------------------
-
-	// <FluentSetters>
-
-	@Override /* GENERATED - HttpException */
-	public UnsupportedMediaType header(String name, Object val) {
-		super.header(name, val);
-		return this;
+		this(create().causedBy(cause));
 	}
 
-	@Override /* GENERATED - HttpException */
-	public UnsupportedMediaType status(int value) {
-		super.status(value);
-		return this;
+	/**
+	 * Creates a builder for this class initialized with the contents of this bean.
+	 *
+	 * @return A new builder bean.
+	 */
+	public HttpExceptionBuilder<UnsupportedMediaType> builder() {
+		return super.builder(UnsupportedMediaType.class).copyFrom(this);
 	}
-
-	// </FluentSetters>
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/UpgradeRequired.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/UpgradeRequired.java
index ea9ed4a..b14b341 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/UpgradeRequired.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/UpgradeRequired.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.http.exception.UpgradeRequired.*;
 import java.text.*;
 
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Exception representing an HTTP 426 (Upgrade Required).
@@ -26,7 +25,6 @@ import org.apache.juneau.internal.*;
  * The client should switch to a different protocol such as TLS/1.0, given in the Upgrade header field.
  */
 @Response(code=STATUS_CODE, description=REASON_PHRASE)
-@FluentSetters
 public class UpgradeRequired extends HttpException {
 	private static final long serialVersionUID = 1L;
 
@@ -36,31 +34,52 @@ public class UpgradeRequired extends HttpException {
 	/** Reason phrase */
 	public static final String REASON_PHRASE = "Upgrade Required";
 
+	/** Reusable unmodifiable instance. */
+	public static final UpgradeRequired INSTANCE = create().unmodifiable(true).build();
+
+	/**
+	 * Creates a builder for this class.
+	 *
+	 * @return A new builder bean.
+	 */
+	public static HttpExceptionBuilder<UpgradeRequired> create() {
+		return new HttpExceptionBuilder<>(UpgradeRequired.class).statusCode(STATUS_CODE).reasonPhrase(REASON_PHRASE);
+	}
+
 	/**
 	 * Constructor.
 	 *
-	 * @param cause The cause.  Can be <jk>null</jk>.
-	 * @param msg The message.  Can be <jk>null</jk>.
-	 * @param args Optional {@link MessageFormat}-style arguments in the message.
+	 * @param builder The builder containing the settings for this exception.
 	 */
-	public UpgradeRequired(Throwable cause, String msg, Object...args) {
-		super(cause, STATUS_CODE, msg, args);
+	public UpgradeRequired(HttpExceptionBuilder<?> builder) {
+		super(builder);
 	}
 
 	/**
 	 * Constructor.
 	 *
+	 * @param cause The caused-by exception.  Can be <jk>null</jk>.
 	 * @param msg The message.  Can be <jk>null</jk>.
+	 * @param args The message arguments.
 	 */
-	public UpgradeRequired(String msg) {
-		this((Throwable)null, msg);
+	public UpgradeRequired(Throwable cause, String msg, Object...args) {
+		this(create().causedBy(cause).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 */
 	public UpgradeRequired() {
-		this((Throwable)null, REASON_PHRASE);
+		this(create().build());
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param msg The message.  Can be <jk>null</jk>.
+	 */
+	public UpgradeRequired(String msg) {
+		this(create().message(msg));
 	}
 
 	/**
@@ -70,7 +89,7 @@ public class UpgradeRequired extends HttpException {
 	 * @param args Optional {@link MessageFormat}-style arguments in the message.
 	 */
 	public UpgradeRequired(String msg, Object...args) {
-		this(null, msg, args);
+		this(create().message(msg, args));
 	}
 
 	/**
@@ -79,26 +98,15 @@ public class UpgradeRequired extends HttpException {
 	 * @param cause The cause.  Can be <jk>null</jk>.
 	 */
 	public UpgradeRequired(Throwable cause) {
-		this(cause, null);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Fluent setters.
-	//------------------------------------------------------------------------------------------------------------------
-
-	// <FluentSetters>
-
-	@Override /* GENERATED - HttpException */
-	public UpgradeRequired header(String name, Object val) {
-		super.header(name, val);
-		return this;
+		this(create().causedBy(cause));
 	}
 
-	@Override /* GENERATED - HttpException */
-	public UpgradeRequired status(int value) {
-		super.status(value);
-		return this;
+	/**
+	 * Creates a builder for this class initialized with the contents of this bean.
+	 *
+	 * @return A new builder bean.
+	 */
+	public HttpExceptionBuilder<UpgradeRequired> builder() {
+		return super.builder(UpgradeRequired.class).copyFrom(this);
 	}
-
-	// </FluentSetters>
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/UriTooLong.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/UriTooLong.java
index e22852f..3137752 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/UriTooLong.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/UriTooLong.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.http.exception.UriTooLong.*;
 import java.text.*;
 
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Exception representing an HTTP 414 (URI Too Long).
@@ -27,7 +26,6 @@ import org.apache.juneau.internal.*;
  * <br>Often the result of too much data being encoded as a query-string of a GET request, in which case it should be converted to a POST request.
  */
 @Response(code=STATUS_CODE, description=REASON_PHRASE)
-@FluentSetters
 public class UriTooLong extends HttpException {
 	private static final long serialVersionUID = 1L;
 
@@ -37,31 +35,52 @@ public class UriTooLong extends HttpException {
 	/** Reason phrase */
 	public static final String REASON_PHRASE = "URI Too Long";
 
+	/** Reusable unmodifiable instance. */
+	public static final UriTooLong INSTANCE = create().unmodifiable(true).build();
+
+	/**
+	 * Creates a builder for this class.
+	 *
+	 * @return A new builder bean.
+	 */
+	public static HttpExceptionBuilder<UriTooLong> create() {
+		return new HttpExceptionBuilder<>(UriTooLong.class).statusCode(STATUS_CODE).reasonPhrase(REASON_PHRASE);
+	}
+
 	/**
 	 * Constructor.
 	 *
-	 * @param cause The cause.  Can be <jk>null</jk>.
-	 * @param msg The message.  Can be <jk>null</jk>.
-	 * @param args Optional {@link MessageFormat}-style arguments in the message.
+	 * @param builder The builder containing the settings for this exception.
 	 */
-	public UriTooLong(Throwable cause, String msg, Object...args) {
-		super(cause, STATUS_CODE, msg, args);
+	public UriTooLong(HttpExceptionBuilder<?> builder) {
+		super(builder);
 	}
 
 	/**
 	 * Constructor.
 	 *
+	 * @param cause The caused-by exception.  Can be <jk>null</jk>.
 	 * @param msg The message.  Can be <jk>null</jk>.
+	 * @param args The message arguments.
 	 */
-	public UriTooLong(String msg) {
-		this((Throwable)null, msg);
+	public UriTooLong(Throwable cause, String msg, Object...args) {
+		this(create().causedBy(cause).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 */
 	public UriTooLong() {
-		this((Throwable)null, REASON_PHRASE);
+		this(create().build());
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param msg The message.  Can be <jk>null</jk>.
+	 */
+	public UriTooLong(String msg) {
+		this(create().message(msg));
 	}
 
 	/**
@@ -71,7 +90,7 @@ public class UriTooLong extends HttpException {
 	 * @param args Optional {@link MessageFormat}-style arguments in the message.
 	 */
 	public UriTooLong(String msg, Object...args) {
-		this(null, msg, args);
+		this(create().message(msg, args));
 	}
 
 	/**
@@ -80,26 +99,15 @@ public class UriTooLong extends HttpException {
 	 * @param cause The cause.  Can be <jk>null</jk>.
 	 */
 	public UriTooLong(Throwable cause) {
-		this(cause, null);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Fluent setters.
-	//------------------------------------------------------------------------------------------------------------------
-
-	// <FluentSetters>
-
-	@Override /* GENERATED - HttpException */
-	public UriTooLong header(String name, Object val) {
-		super.header(name, val);
-		return this;
+		this(create().causedBy(cause));
 	}
 
-	@Override /* GENERATED - HttpException */
-	public UriTooLong status(int value) {
-		super.status(value);
-		return this;
+	/**
+	 * Creates a builder for this class initialized with the contents of this bean.
+	 *
+	 * @return A new builder bean.
+	 */
+	public HttpExceptionBuilder<UriTooLong> builder() {
+		return super.builder(UriTooLong.class).copyFrom(this);
 	}
-
-	// </FluentSetters>
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/VariantAlsoNegotiates.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/VariantAlsoNegotiates.java
index 83dc16b..48686a1 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/VariantAlsoNegotiates.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/exception/VariantAlsoNegotiates.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.http.exception.VariantAlsoNegotiates.*;
 import java.text.*;
 
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Exception representing an HTTP 506 (Variant Also Negotiate).
@@ -26,7 +25,6 @@ import org.apache.juneau.internal.*;
  * Transparent content negotiation for the request results in a circular reference.
  */
 @Response(code=STATUS_CODE, description=REASON_PHRASE)
-@FluentSetters
 public class VariantAlsoNegotiates extends HttpException {
 	private static final long serialVersionUID = 1L;
 
@@ -36,31 +34,52 @@ public class VariantAlsoNegotiates extends HttpException {
 	/** Reason phrase */
 	public static final String REASON_PHRASE = "Variant Also Negotiates";
 
+	/** Reusable unmodifiable instance. */
+	public static final VariantAlsoNegotiates INSTANCE = create().unmodifiable(true).build();
+
+	/**
+	 * Creates a builder for this class.
+	 *
+	 * @return A new builder bean.
+	 */
+	public static HttpExceptionBuilder<VariantAlsoNegotiates> create() {
+		return new HttpExceptionBuilder<>(VariantAlsoNegotiates.class).statusCode(STATUS_CODE).reasonPhrase(REASON_PHRASE);
+	}
+
 	/**
 	 * Constructor.
 	 *
-	 * @param cause The cause.  Can be <jk>null</jk>.
-	 * @param msg The message.  Can be <jk>null</jk>.
-	 * @param args Optional {@link MessageFormat}-style arguments in the message.
+	 * @param builder The builder containing the settings for this exception.
 	 */
-	public VariantAlsoNegotiates(Throwable cause, String msg, Object...args) {
-		super(cause, STATUS_CODE, msg, args);
+	public VariantAlsoNegotiates(HttpExceptionBuilder<?> builder) {
+		super(builder);
 	}
 
 	/**
 	 * Constructor.
 	 *
+	 * @param cause The caused-by exception.  Can be <jk>null</jk>.
 	 * @param msg The message.  Can be <jk>null</jk>.
+	 * @param args The message arguments.
 	 */
-	public VariantAlsoNegotiates(String msg) {
-		this((Throwable)null, msg);
+	public VariantAlsoNegotiates(Throwable cause, String msg, Object...args) {
+		this(create().causedBy(cause).message(msg, args));
 	}
 
 	/**
 	 * Constructor.
 	 */
 	public VariantAlsoNegotiates() {
-		this((Throwable)null, REASON_PHRASE);
+		this(create().build());
+	}
+
+	/**
+	 * Constructor.
+	 *
+	 * @param msg The message.  Can be <jk>null</jk>.
+	 */
+	public VariantAlsoNegotiates(String msg) {
+		this(create().message(msg));
 	}
 
 	/**
@@ -70,7 +89,7 @@ public class VariantAlsoNegotiates extends HttpException {
 	 * @param args Optional {@link MessageFormat}-style arguments in the message.
 	 */
 	public VariantAlsoNegotiates(String msg, Object...args) {
-		this(null, msg, args);
+		this(create().message(msg, args));
 	}
 
 	/**
@@ -79,26 +98,15 @@ public class VariantAlsoNegotiates extends HttpException {
 	 * @param cause The cause.  Can be <jk>null</jk>.
 	 */
 	public VariantAlsoNegotiates(Throwable cause) {
-		this(cause, null);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Fluent setters.
-	//------------------------------------------------------------------------------------------------------------------
-
-	// <FluentSetters>
-
-	@Override /* GENERATED - HttpException */
-	public VariantAlsoNegotiates header(String name, Object val) {
-		super.header(name, val);
-		return this;
+		this(create().causedBy(cause));
 	}
 
-	@Override /* GENERATED - HttpException */
-	public VariantAlsoNegotiates status(int value) {
-		super.status(value);
-		return this;
+	/**
+	 * Creates a builder for this class initialized with the contents of this bean.
+	 *
+	 * @return A new builder bean.
+	 */
+	public HttpExceptionBuilder<VariantAlsoNegotiates> builder() {
+		return super.builder(VariantAlsoNegotiates.class).copyFrom(this);
 	}
-
-	// </FluentSetters>
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/VarResolverException.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/VarResolverException.java
index aa9e7da..f2953dc 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/VarResolverException.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/VarResolverException.java
@@ -30,7 +30,7 @@ public class VarResolverException extends BasicRuntimeException {
 	 * @param args Optional {@link MessageFormat}-style arguments.
 	 */
 	public VarResolverException(Throwable cause, String message, Object... args) {
-		super(cause, getMessage(cause, message, null), args);
+		super(cause, message, args);
 	}
 
 	/**
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/PojoRestException.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/PojoRestException.java
index 3110653..476ab74 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/PojoRestException.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/PojoRestException.java
@@ -52,7 +52,7 @@ public final class PojoRestException extends BasicRuntimeException {
 	 * @param args Optional {@link MessageFormat}-style arguments.
 	 */
 	public PojoRestException(Throwable cause, int status, String message, Object... args) {
-		super(cause, getMessage(cause, message, null), args);
+		super(cause, message, args);
 		this.status = status;
 	}
 
diff --git a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteMetadataException.java b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteMetadataException.java
index f8944a4..020cd08 100644
--- a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteMetadataException.java
+++ b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteMetadataException.java
@@ -32,7 +32,7 @@ public class RemoteMetadataException extends BasicRuntimeException {
 	 * @param args Optional {@link MessageFormat}-style arguments.
 	 */
 	public RemoteMetadataException(Throwable cause, String message, Object... args) {
-		super(cause, getMessage(cause, message, null), args);
+		super(cause, message, args);
 	}
 
 	/**
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
index 0d2d54f..aae5fc6 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
@@ -6881,7 +6881,7 @@ public class RestContext extends BeanContext {
 			if (r.code().length > 0)
 				code = r.code()[0];
 
-		HttpException e2 = (e instanceof HttpException ? (HttpException)e : new HttpException(e, code));
+		HttpException e2 = (e instanceof HttpException ? (HttpException)e : HttpException.create(HttpException.class).causedBy(e).statusCode(code).build());
 
 		HttpServletRequest req = call.getRequest();
 		HttpServletResponse res = call.getResponse();
@@ -6899,7 +6899,7 @@ public class RestContext extends BeanContext {
 		try {
 			res.setContentType("text/plain");
 			res.setHeader("Content-Encoding", "identity");
-			res.setStatus(e2.getStatus());
+			res.setStatus(e2.getStatusCode());
 
 			PrintWriter w = null;
 			try {
@@ -6909,9 +6909,9 @@ public class RestContext extends BeanContext {
 			}
 
 			try (PrintWriter w2 = w) {
-				String httpMessage = RestUtils.getHttpResponseText(e2.getStatus());
+				String httpMessage = RestUtils.getHttpResponseText(e2.getStatusCode());
 				if (httpMessage != null)
-					w2.append("HTTP ").append(String.valueOf(e2.getStatus())).append(": ").append(httpMessage).append("\n\n");
+					w2.append("HTTP ").append(String.valueOf(e2.getStatusCode())).append(": ").append(httpMessage).append("\n\n");
 				if (isRenderResponseStackTraces())
 					e.printStackTrace(w2);
 				else
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/converters/Traversable.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/converters/Traversable.java
index 0d6e8f5..beb73c0 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/converters/Traversable.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/converters/Traversable.java
@@ -60,7 +60,7 @@ public final class Traversable implements RestConverter {
 				PojoRest p = new PojoRest(o, req.getBody().getReaderParser());
 				o = p.get(pathRemainder);
 			} catch (PojoRestException e) {
-				throw new HttpException(e, e.getStatus());
+				throw new HttpException(e.getStatus(), e);
 			} catch (Throwable t) {
 				throw toHttpException(t, InternalServerError.class);
 			}
diff --git a/juneau-utest/src/test/java/org/apache/juneau/assertions/ArrayAssertion_Test.java b/juneau-utest/src/test/java/org/apache/juneau/assertions/ArrayAssertion_Test.java
index db94217..6130ea7 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/assertions/ArrayAssertion_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/assertions/ArrayAssertion_Test.java
@@ -20,45 +20,49 @@ import org.junit.*;
 @FixMethodOrder(NAME_ASCENDING)
 public class ArrayAssertion_Test {
 
+	private ArrayAssertion test(Object value) {
+		return assertArray(value).silent();
+	}
+
 	@Test
 	public void a01_basic() throws Exception {
 		String[] x1={}, x2={"foo","bar"};
 
-		assertThrown(()->assertArray(null).exists()).is("Value was null.");
-		assertArray(x1).exists();
+		assertThrown(()->test(null).exists()).is("Value was null.");
+		test(x1).exists();
 
-		assertArray(null).doesNotExist();
-		assertThrown(()->assertArray(x1).doesNotExist()).is("Value was not null.");
+		test(null).doesNotExist();
+		assertThrown(()->test(x1).doesNotExist()).is("Value was not null.");
 
-		assertThrown(()->assertArray(null).isSize(0)).is("Value was null.");
-		assertArray(x1).isSize(0);
-		assertThrown(()->assertArray(x1).isSize(2)).is("Array did not have the expected size.  Expect=2, Actual=0.");
-		assertArray(x2).isSize(2);
-		assertThrown(()->assertArray(x2).isSize(0)).is("Array did not have the expected size.  Expect=0, Actual=2.");
+		assertThrown(()->test(null).isSize(0)).is("Value was null.");
+		test(x1).isSize(0);
+		assertThrown(()->test(x1).isSize(2)).is("Array did not have the expected size.  Expect=2, Actual=0.");
+		test(x2).isSize(2);
+		assertThrown(()->test(x2).isSize(0)).is("Array did not have the expected size.  Expect=0, Actual=2.");
 
-		assertThrown(()->assertArray(null).isEmpty()).is("Value was null.");
-		assertArray(x1).isEmpty();
-		assertThrown(()->assertArray(x2).isEmpty()).is("Array was not empty.");
+		assertThrown(()->test(null).isEmpty()).is("Value was null.");
+		test(x1).isEmpty();
+		assertThrown(()->test(x2).isEmpty()).is("Array was not empty.");
 
-		assertThrown(()->assertArray(null).isNotEmpty()).is("Value was null.");
-		assertThrown(()->assertArray(x1).isNotEmpty()).is("Array was empty.");
-		assertArray(x2).isNotEmpty();
+		assertThrown(()->test(null).isNotEmpty()).is("Value was null.");
+		assertThrown(()->test(x1).isNotEmpty()).is("Array was empty.");
+		test(x2).isNotEmpty();
 
-		assertArray(null).item(0).doesNotExist();
-		assertArray(x1).item(0).doesNotExist();
-		assertArray(x2).item(0).exists();
+		test(null).item(0).doesNotExist();
+		test(x1).item(0).doesNotExist();
+		test(x2).item(0).exists();
 
-		assertArray(x2).contains("foo");
-		assertThrown(()->assertArray(x2).contains("z")).is("Array did not contain expected value.\n\tContents: ['foo','bar']\n\tExpected: z");
+		test(x2).contains("foo");
+		assertThrown(()->test(x2).contains("z")).is("Array did not contain expected value.\n\tContents: ['foo','bar']\n\tExpected: z");
 
-		assertArray(x1).doesNotContain("foo");
-		assertThrown(()->assertArray(x2).doesNotContain("foo")).is("Array contained unexpected value.\n\tContents: ['foo','bar']\n\tUnexpected: foo");
-		assertThrown(()->assertArray(x2).doesNotContain("bar")).is("Array contained unexpected value.\n\tContents: ['foo','bar']\n\tUnexpected: bar");
+		test(x1).doesNotContain("foo");
+		assertThrown(()->test(x2).doesNotContain("foo")).is("Array contained unexpected value.\n\tContents: ['foo','bar']\n\tUnexpected: foo");
+		assertThrown(()->test(x2).doesNotContain("bar")).is("Array contained unexpected value.\n\tContents: ['foo','bar']\n\tUnexpected: bar");
 	}
 
 	@Test
 	public void a02_other() throws Exception {
-		assertThrown(()->ArrayAssertion.create(null).msg("Foo {0}", 1).exists()).is("Foo 1");
-		ArrayAssertion.create(null).stdout().silent();
+		assertThrown(()->test(null).msg("Foo {0}", 1).exists()).is("Foo 1");
+		test(null).stdout();
 	}
 }
diff --git a/juneau-utest/src/test/java/org/apache/juneau/assertions/BeanAssertion_Test.java b/juneau-utest/src/test/java/org/apache/juneau/assertions/BeanAssertion_Test.java
index f521aa7..38de897 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/assertions/BeanAssertion_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/assertions/BeanAssertion_Test.java
@@ -20,6 +20,10 @@ import org.junit.*;
 @FixMethodOrder(NAME_ASCENDING)
 public class BeanAssertion_Test {
 
+	private BeanAssertion<?> test(Object value) {
+		return assertBean(value).silent();
+	}
+
 	public static class A {
 		public int f1 = 1, f2 = 2;
 	}
@@ -28,23 +32,23 @@ public class BeanAssertion_Test {
 	public void a01_basic() throws Exception {
 		A a = new A();
 
-		assertThrown(()->assertBean((Object)null).exists()).is("Value was null.");
-		assertBean(a).exists();
+		assertThrown(()->test((Object)null).exists()).is("Value was null.");
+		test(a).exists();
 
 		assertCollection(null).doesNotExist();
-		assertThrown(()->assertBean(a).doesNotExist()).is("Value was not null.");
+		assertThrown(()->test(a).doesNotExist()).is("Value was not null.");
 
-		assertBean(a).field("f1").asInteger().is(1);
-		assertBean(a).field("x").asInteger().isNull();
-		assertThrown(()->assertBean((Object)null).field("x")).is("Value was null.");
+		test(a).field("f1").asInteger().is(1);
+		test(a).field("x").asInteger().isNull();
+		assertThrown(()->test((Object)null).field("x")).is("Value was null.");
 
-		assertBean(a).fields("f2,f1").asJson().is("{f2:2,f1:1}");
-		assertBean(a).fields("x").asJson().is("{}");
+		test(a).fields("f2,f1").asJson().is("{f2:2,f1:1}");
+		test(a).fields("x").asJson().is("{}");
 	}
 
 	@Test
 	public void a02_other() throws Exception {
-		assertThrown(()->BeanAssertion.create(null).msg("Foo {0}", 1).exists()).is("Foo 1");
-		BeanAssertion.create(null).stdout().silent();
+		assertThrown(()->test(null).msg("Foo {0}", 1).exists()).is("Foo 1");
+		test(null).stdout();
 	}
 }
diff --git a/juneau-utest/src/test/java/org/apache/juneau/assertions/BooleanAssertion_Test.java b/juneau-utest/src/test/java/org/apache/juneau/assertions/BooleanAssertion_Test.java
index a4a884e..61de9bf 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/assertions/BooleanAssertion_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/assertions/BooleanAssertion_Test.java
@@ -15,6 +15,8 @@ package org.apache.juneau.assertions;
 import static org.apache.juneau.assertions.Assertions.*;
 import static org.junit.runners.MethodSorters.*;
 
+import java.util.*;
+
 import static java.util.Optional.*;
 
 import org.junit.*;
@@ -22,35 +24,43 @@ import org.junit.*;
 @FixMethodOrder(NAME_ASCENDING)
 public class BooleanAssertion_Test {
 
+	private BooleanAssertion test(Boolean value) {
+		return assertBoolean(value).silent();
+	}
+
+	private BooleanAssertion test(Optional<Boolean> value) {
+		return assertBoolean(value).silent();
+	}
+
 	@Test
 	public void a01_basic() throws Exception {
 
-		assertThrown(()->assertBoolean((Boolean)null).exists()).is("Value was null.");
-		assertBoolean(true).exists();
-		assertThrown(()->assertBoolean(empty()).exists()).is("Value was null.");
-		assertBoolean(true).exists();
+		assertThrown(()->test((Boolean)null).exists()).is("Value was null.");
+		test(true).exists();
+		assertThrown(()->test(empty()).exists()).is("Value was null.");
+		test(true).exists();
 
-		assertBoolean(empty()).doesNotExist();
-		assertThrown(()->assertBoolean(true).doesNotExist()).is("Value was not null.");
+		test(empty()).doesNotExist();
+		assertThrown(()->test(true).doesNotExist()).is("Value was not null.");
 
-		assertBoolean(empty()).isEqual(null);
-		assertBoolean(true).isEqual(true);
-		assertBoolean(of(true)).isEqual(true);
+		test(empty()).isEqual(null);
+		test(true).isEqual(true);
+		test(of(true)).isEqual(true);
 
-		assertBoolean(true).isTrue();
-		assertThrown(()->assertBoolean(true).isFalse()).is("Value was true.");
-		assertBoolean(false).isFalse();
-		assertThrown(()->assertBoolean(false).isTrue()).is("Value was false.");
+		test(true).isTrue();
+		assertThrown(()->test(true).isFalse()).is("Value was true.");
+		test(false).isFalse();
+		assertThrown(()->test(false).isTrue()).is("Value was false.");
 
-		assertThrown(()->assertBoolean(true).isEqual(false)).contains("Unexpected value.");
-		assertBoolean(empty()).isEqual(null);
+		assertThrown(()->test(true).isEqual(false)).contains("Unexpected value.");
+		test(empty()).isEqual(null);
 
-		assertBoolean(true).isNot("true");
+		test(true).isNot("true");
 	}
 
 	@Test
 	public void a02_other() throws Exception {
-		assertThrown(()->BooleanAssertion.create(null).msg("Foo {0}", 1).exists()).is("Foo 1");
-		BooleanAssertion.create(null).stdout().silent();
+		assertThrown(()->test((Boolean)null).msg("Foo {0}", 1).exists()).is("Foo 1");
+		test((Boolean)null).stdout();
 	}
 }
diff --git a/juneau-utest/src/test/java/org/apache/juneau/assertions/ByteArrayAssertion_Test.java b/juneau-utest/src/test/java/org/apache/juneau/assertions/ByteArrayAssertion_Test.java
index bfd1d03..5509a32 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/assertions/ByteArrayAssertion_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/assertions/ByteArrayAssertion_Test.java
@@ -14,6 +14,9 @@ package org.apache.juneau.assertions;
 
 import static org.apache.juneau.assertions.Assertions.*;
 import static org.junit.runners.MethodSorters.*;
+
+import java.util.*;
+
 import static java.util.Optional.*;
 
 import org.junit.*;
@@ -21,64 +24,72 @@ import org.junit.*;
 @FixMethodOrder(NAME_ASCENDING)
 public class ByteArrayAssertion_Test {
 
+	private ByteArrayAssertion test(byte[] value) {
+		return assertBytes(value).silent();
+	}
+
+	private ByteArrayAssertion test(Optional<byte[]> value) {
+		return assertBytes(value).silent();
+	}
+
 	@Test
 	public void a01_basic() throws Exception {
 		byte[] x1={}, x2={'a','b'};
 
-		assertThrown(()->assertBytes((byte[])null).exists()).is("Value was null.");
-		assertBytes(x1).exists();
-		assertThrown(()->assertBytes(empty()).exists()).is("Value was null.");
-		assertBytes(x1).exists();
-
-		assertBytes((byte[])null).doesNotExist();
-		assertThrown(()->assertBytes(x1).doesNotExist()).is("Value was not null.");
-		assertBytes(empty()).doesNotExist();
-		assertThrown(()->assertBytes(x1).doesNotExist()).is("Value was not null.");
-
-		assertThrown(()->assertBytes(empty()).isSize(0)).is("Value was null.");
-		assertBytes(x1).isSize(0);
-		assertThrown(()->assertBytes(x1).isSize(1)).is("Array did not have the expected size.  Expect=1, Actual=0.");
-		assertBytes(x2).isSize(2);
-		assertThrown(()->assertBytes(of(x1)).isSize(1)).is("Array did not have the expected size.  Expect=1, Actual=0.");
-		assertBytes(x2).isSize(2);
-		assertThrown(()->assertBytes(x2).isSize(0)).is("Array did not have the expected size.  Expect=0, Actual=2.");
-
-		assertThrown(()->assertBytes(empty()).isEmpty()).is("Value was null.");
-		assertBytes(x1).isEmpty();
-		assertThrown(()->assertBytes(x2).isEmpty()).is("Array was not empty.");
-
-		assertThrown(()->assertBytes(empty()).isNotEmpty()).is("Value was null.");
-		assertThrown(()->assertBytes(x1).isNotEmpty()).is("Array was empty.");
-		assertBytes(x2).isNotEmpty();
-
-		assertBytes(empty()).item(0).doesNotExist();
-		assertBytes(x1).item(0).doesNotExist();
-		assertBytes(x2).item(0).exists();
-
-		assertBytes(empty()).asString().isNull();
-		assertBytes(x1).asString().is("");
-		assertBytes(x2).asString().is("ab");
-		assertThrown(()->assertBytes(x2).asString().is("xx")).is("Unexpected value.\n\tExpect=[xx]\n\tActual=[ab]");
-
-		assertBytes(empty()).asBase64().isNull();
-		assertBytes(x1).asBase64().is("");
-		assertBytes(x2).asBase64().is("YWI=");
-		assertThrown(()->assertBytes(x2).asBase64().is("xx")).is("Unexpected value.\n\tExpect=[xx]\n\tActual=[YWI=]");
-
-		assertBytes(empty()).asHex().isNull();
-		assertBytes(x1).asHex().is("");
-		assertBytes(x2).asHex().is("6162");
-		assertThrown(()->assertBytes(x2).asHex().is("xx")).is("Unexpected value.\n\tExpect=[xx]\n\tActual=[6162]");
-
-		assertBytes(empty()).asSpacedHex().isNull();
-		assertBytes(x1).asSpacedHex().is("");
-		assertBytes(x2).asSpacedHex().is("61 62");
-		assertThrown(()->assertBytes(x2).asSpacedHex().is("xx")).is("Unexpected value.\n\tExpect=[xx]\n\tActual=[61 62]");
+		assertThrown(()->test((byte[])null).exists()).is("Value was null.");
+		test(x1).exists();
+		assertThrown(()->test(empty()).exists()).is("Value was null.");
+		test(x1).exists();
+
+		test((byte[])null).doesNotExist();
+		assertThrown(()->test(x1).doesNotExist()).is("Value was not null.");
+		test(empty()).doesNotExist();
+		assertThrown(()->test(x1).doesNotExist()).is("Value was not null.");
+
+		assertThrown(()->test(empty()).isSize(0)).is("Value was null.");
+		test(x1).isSize(0);
+		assertThrown(()->test(x1).isSize(1)).is("Array did not have the expected size.  Expect=1, Actual=0.");
+		test(x2).isSize(2);
+		assertThrown(()->test(of(x1)).isSize(1)).is("Array did not have the expected size.  Expect=1, Actual=0.");
+		test(x2).isSize(2);
+		assertThrown(()->test(x2).isSize(0)).is("Array did not have the expected size.  Expect=0, Actual=2.");
+
+		assertThrown(()->test(empty()).isEmpty()).is("Value was null.");
+		test(x1).isEmpty();
+		assertThrown(()->test(x2).isEmpty()).is("Array was not empty.");
+
+		assertThrown(()->test(empty()).isNotEmpty()).is("Value was null.");
+		assertThrown(()->test(x1).isNotEmpty()).is("Array was empty.");
+		test(x2).isNotEmpty();
+
+		test(empty()).item(0).doesNotExist();
+		test(x1).item(0).doesNotExist();
+		test(x2).item(0).exists();
+
+		test(empty()).asString().isNull();
+		test(x1).asString().is("");
+		test(x2).asString().is("ab");
+		assertThrown(()->test(x2).asString().is("xx")).is("Unexpected value.\n\tExpect=[xx]\n\tActual=[ab]");
+
+		test(empty()).asBase64().isNull();
+		test(x1).asBase64().is("");
+		test(x2).asBase64().is("YWI=");
+		assertThrown(()->test(x2).asBase64().is("xx")).is("Unexpected value.\n\tExpect=[xx]\n\tActual=[YWI=]");
+
+		test(empty()).asHex().isNull();
+		test(x1).asHex().is("");
+		test(x2).asHex().is("6162");
+		assertThrown(()->test(x2).asHex().is("xx")).is("Unexpected value.\n\tExpect=[xx]\n\tActual=[6162]");
+
+		test(empty()).asSpacedHex().isNull();
+		test(x1).asSpacedHex().is("");
+		test(x2).asSpacedHex().is("61 62");
+		assertThrown(()->test(x2).asSpacedHex().is("xx")).is("Unexpected value.\n\tExpect=[xx]\n\tActual=[61 62]");
 	}
 
 	@Test
 	public void a02_other() throws Exception {
-		assertThrown(()->ByteArrayAssertion.create(null).msg("Foo {0}", 1).exists()).is("Foo 1");
-		ByteArrayAssertion.create(null).stdout().silent();
+		assertThrown(()->test((byte[])null).msg("Foo {0}", 1).exists()).is("Foo 1");
+		test((byte[])null).stdout();
 	}
 }
diff --git a/juneau-utest/src/test/java/org/apache/juneau/assertions/CollectionAssertion_Test.java b/juneau-utest/src/test/java/org/apache/juneau/assertions/CollectionAssertion_Test.java
index 68fbecd..8e5ac11 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/assertions/CollectionAssertion_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/assertions/CollectionAssertion_Test.java
@@ -23,40 +23,44 @@ import org.junit.*;
 @FixMethodOrder(NAME_ASCENDING)
 public class CollectionAssertion_Test {
 
+	private CollectionAssertion test(Collection<?> value) {
+		return assertCollection(value).silent();
+	}
+
 	@Test
 	public void a01_basic() throws Exception {
 		List<String> x1 = AList.create(), x2 = AList.of("a","b");
 
-		assertThrown(()->assertCollection(null).exists()).is("Value was null.");
-		assertCollection(x1).exists();
+		assertThrown(()->test(null).exists()).is("Value was null.");
+		test(x1).exists();
 
-		assertCollection(null).doesNotExist();
-		assertThrown(()->assertCollection(x1).doesNotExist()).is("Value was not null.");
+		test(null).doesNotExist();
+		assertThrown(()->test(x1).doesNotExist()).is("Value was not null.");
 
-		assertThrown(()->assertCollection(null).isSize(0)).is("Value was null.");
-		assertCollection(x1).isSize(0);
-		assertThrown(()->assertCollection(x1).isSize(1)).is("Collection did not have the expected size.  Expect=1, Actual=0.");
-		assertCollection(x2).isSize(2);
-		assertThrown(()->assertCollection(x2).isSize(0)).is("Collection did not have the expected size.  Expect=0, Actual=2.");
+		assertThrown(()->test(null).isSize(0)).is("Value was null.");
+		test(x1).isSize(0);
+		assertThrown(()->test(x1).isSize(1)).is("Collection did not have the expected size.  Expect=1, Actual=0.");
+		test(x2).isSize(2);
+		assertThrown(()->test(x2).isSize(0)).is("Collection did not have the expected size.  Expect=0, Actual=2.");
 
-		assertThrown(()->assertCollection(null).isEmpty()).is("Value was null.");
-		assertCollection(x1).isEmpty();
-		assertThrown(()->assertCollection(x2).isEmpty()).is("Collection was not empty.");
+		assertThrown(()->test(null).isEmpty()).is("Value was null.");
+		test(x1).isEmpty();
+		assertThrown(()->test(x2).isEmpty()).is("Collection was not empty.");
 
-		assertThrown(()->assertCollection(null).isNotEmpty()).is("Value was null.");
-		assertThrown(()->assertCollection(x1).isNotEmpty()).is("Collection was empty.");
-		assertCollection(x2).isNotEmpty();
+		assertThrown(()->test(null).isNotEmpty()).is("Value was null.");
+		assertThrown(()->test(x1).isNotEmpty()).is("Collection was empty.");
+		test(x2).isNotEmpty();
 
-		assertCollection(x2).contains("a");
-		assertThrown(()->assertCollection(x2).contains("z")).is("Collection did not contain expected value.\n\tContents: ['a','b']\n\tExpected: z");
+		test(x2).contains("a");
+		assertThrown(()->test(x2).contains("z")).is("Collection did not contain expected value.\n\tContents: ['a','b']\n\tExpected: z");
 
-		assertCollection(x1).doesNotContain("a");
-		assertThrown(()->assertCollection(x2).doesNotContain("a")).is("Collection contained unexpected value.\n\tContents: ['a','b']\n\tUnexpected: a");
+		test(x1).doesNotContain("a");
+		assertThrown(()->test(x2).doesNotContain("a")).is("Collection contained unexpected value.\n\tContents: ['a','b']\n\tUnexpected: a");
 	}
 
 	@Test
 	public void a02_other() throws Exception {
-		assertThrown(()->CollectionAssertion.create(null).msg("Foo {0}", 1).exists()).is("Foo 1");
-		CollectionAssertion.create(null).stdout().silent();
+		assertThrown(()->test(null).msg("Foo {0}", 1).exists()).is("Foo 1");
+		test(null).stdout().silent();
 	}
 }
diff --git a/juneau-utest/src/test/java/org/apache/juneau/assertions/ComparableAssertion_Test.java b/juneau-utest/src/test/java/org/apache/juneau/assertions/ComparableAssertion_Test.java
index a5413e4..fa84f7e 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/assertions/ComparableAssertion_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/assertions/ComparableAssertion_Test.java
@@ -20,15 +20,19 @@ import org.junit.*;
 @FixMethodOrder(NAME_ASCENDING)
 public class ComparableAssertion_Test {
 
+	private ComparableAssertion test(Comparable<?> value) {
+		return assertComparable(value).silent();
+	}
+
 	@Test
 	public void a01_basic() throws Exception {
-		assertComparable(null).doesNotExist();
-		assertComparable(1).isGte(1);
+		test(null).doesNotExist();
+		test(1).isGte(1);
 	}
 
 	@Test
 	public void a02_other() throws Exception {
-		assertThrown(()->ComparableAssertion.create(null).msg("Foo {0}", 1).exists()).is("Foo 1");
-		ComparableAssertion.create(null).stdout().silent();
+		assertThrown(()->test(null).msg("Foo {0}", 1).exists()).is("Foo 1");
+		test(null).stdout().silent();
 	}
 }
diff --git a/juneau-utest/src/test/java/org/apache/juneau/assertions/DateAssertion_Test.java b/juneau-utest/src/test/java/org/apache/juneau/assertions/DateAssertion_Test.java
index ad96d6c..199cdd7 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/assertions/DateAssertion_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/assertions/DateAssertion_Test.java
@@ -24,58 +24,66 @@ import org.junit.*;
 @FixMethodOrder(NAME_ASCENDING)
 public class DateAssertion_Test {
 
+	private DateAssertion test(Date value) {
+		return assertDate(value).silent();
+	}
+
+	private DateAssertion test(Optional<Date> value) {
+		return assertDate(value).silent();
+	}
+
 	@Test
 	public void a01_basic() throws Exception {
 		Date x1 = new Date(0), x2 = new Date(Long.MAX_VALUE), now = new Date();
 
-		assertThrown(()->assertDate((Date)null).exists()).is("Value was null.");
-		assertDate(x1).exists();
-		assertThrown(()->assertDate(empty()).exists()).is("Value was null.");
-		assertDate(x1).exists();
-
-		assertDate(empty()).doesNotExist();
-		assertThrown(()->assertDate(x1).doesNotExist()).is("Value was not null.");
-
-		assertDate(empty()).isEqual(null);
-		assertDate(x1).isEqual(x1);
-		assertDate(of(x1)).isEqual(x1);
-		assertDate(x1).isEqual(x1, ChronoUnit.DAYS);
-		assertThrown(()->assertDate(x2).isEqual(x1, ChronoUnit.DAYS)).contains("Unexpected value.");
-
-		assertDate(empty()).isEqual(null);
-		assertDate(x1).isEqual(x1);
-		assertDate(x1).isEqual(x1, ChronoUnit.DAYS);
-		assertThrown(()->assertDate(x2).isEqual(x1, ChronoUnit.DAYS)).contains("Unexpected value.");
-
-		assertThrown(()->assertDate(empty()).isBefore(x1)).is("Value was null.");
-		assertThrown(()->assertDate(x1).isBefore(null)).is("Parameter 'value' cannot be null.");
-		assertDate(x1).isBefore(x2);
-		assertThrown(()->assertDate(x2).isBefore(x1)).contains("Value was not before expected.");
-
-		assertThrown(()->assertDate(empty()).isAfter(x1)).is("Value was null.");
-		assertThrown(()->assertDate(x1).isAfter(null)).is("Parameter 'value' cannot be null.");
-		assertDate(x2).isAfter(x1);
-		assertThrown(()->assertDate(x1).isAfter(x2)).contains("Value was not after expected.");
-
-		assertThrown(()->assertDate(empty()).isBeforeNow()).is("Value was null.");
-		assertDate(x1).isBeforeNow();
-		assertThrown(()->assertDate(x2).isBeforeNow()).contains("Value was not before expected.");
-
-		assertThrown(()->assertDate(empty()).isAfterNow()).is("Value was null.");
-		assertDate(x2).isAfterNow();
-		assertThrown(()->assertDate(x1).isAfterNow()).contains("Value was not after expected.");
-
-		assertThrown(()->assertDate(empty()).isBetween(x1,x2)).is("Value was null.");
-		assertThrown(()->assertDate(now).isBetween(null,x2)).is("Parameter 'lower' cannot be null.");
-		assertThrown(()->assertDate(now).isBetween(x1,null)).is("Parameter 'upper' cannot be null.");
-		assertDate(now).isBetween(x1, x2);
-		assertThrown(()->assertDate(x1).isBetween(now,x2)).contains("Value was not after expected.");
-		assertThrown(()->assertDate(x2).isBetween(x1,now)).contains("Value was not before expected.");
+		assertThrown(()->test((Date)null).exists()).is("Value was null.");
+		test(x1).exists();
+		assertThrown(()->test(empty()).exists()).is("Value was null.");
+		test(x1).exists();
+
+		test(empty()).doesNotExist();
+		assertThrown(()->test(x1).doesNotExist()).is("Value was not null.");
+
+		test(empty()).isEqual(null);
+		test(x1).isEqual(x1);
+		test(of(x1)).isEqual(x1);
+		test(x1).isEqual(x1, ChronoUnit.DAYS);
+		assertThrown(()->test(x2).isEqual(x1, ChronoUnit.DAYS)).contains("Unexpected value.");
+
+		test(empty()).isEqual(null);
+		test(x1).isEqual(x1);
+		test(x1).isEqual(x1, ChronoUnit.DAYS);
+		assertThrown(()->test(x2).isEqual(x1, ChronoUnit.DAYS)).contains("Unexpected value.");
+
+		assertThrown(()->test(empty()).isBefore(x1)).is("Value was null.");
+		assertThrown(()->test(x1).isBefore(null)).is("Parameter 'value' cannot be null.");
+		test(x1).isBefore(x2);
+		assertThrown(()->test(x2).isBefore(x1)).contains("Value was not before expected.");
+
+		assertThrown(()->test(empty()).isAfter(x1)).is("Value was null.");
+		assertThrown(()->test(x1).isAfter(null)).is("Parameter 'value' cannot be null.");
+		test(x2).isAfter(x1);
+		assertThrown(()->test(x1).isAfter(x2)).contains("Value was not after expected.");
+
+		assertThrown(()->test(empty()).isBeforeNow()).is("Value was null.");
+		test(x1).isBeforeNow();
+		assertThrown(()->test(x2).isBeforeNow()).contains("Value was not before expected.");
+
+		assertThrown(()->test(empty()).isAfterNow()).is("Value was null.");
+		test(x2).isAfterNow();
+		assertThrown(()->test(x1).isAfterNow()).contains("Value was not after expected.");
+
+		assertThrown(()->test(empty()).isBetween(x1,x2)).is("Value was null.");
+		assertThrown(()->test(now).isBetween(null,x2)).is("Parameter 'lower' cannot be null.");
+		assertThrown(()->test(now).isBetween(x1,null)).is("Parameter 'upper' cannot be null.");
+		test(now).isBetween(x1, x2);
+		assertThrown(()->test(x1).isBetween(now,x2)).contains("Value was not after expected.");
+		assertThrown(()->test(x2).isBetween(x1,now)).contains("Value was not before expected.");
 	}
 
 	@Test
 	public void a02_other() throws Exception {
-		assertThrown(()->DateAssertion.create(null).msg("Foo {0}", 1).exists()).is("Foo 1");
-		DateAssertion.create(null).stdout().silent();
+		assertThrown(()->test((Date)null).msg("Foo {0}", 1).exists()).is("Foo 1");
+		test((Date)null).stdout();
 	}
 }
diff --git a/juneau-utest/src/test/java/org/apache/juneau/assertions/IntegerAssertion_Test.java b/juneau-utest/src/test/java/org/apache/juneau/assertions/IntegerAssertion_Test.java
index ce52acf..2d56968 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/assertions/IntegerAssertion_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/assertions/IntegerAssertion_Test.java
@@ -15,6 +15,8 @@ package org.apache.juneau.assertions;
 import static org.apache.juneau.assertions.Assertions.*;
 import static org.junit.runners.MethodSorters.*;
 
+import java.util.*;
+
 import static java.util.Optional.*;
 
 import org.junit.*;
@@ -22,87 +24,95 @@ import org.junit.*;
 @FixMethodOrder(NAME_ASCENDING)
 public class IntegerAssertion_Test {
 
+	private IntegerAssertion test(Integer value) {
+		return assertInteger(value).silent();
+	}
+
+	private IntegerAssertion test(Optional<Integer> value) {
+		return assertInteger(value).silent();
+	}
+
 	@Test
 	public void a01_basic() throws Exception {
 
-		assertThrown(()->assertInteger((Integer)null).exists()).is("Value was null.");
-		assertInteger(1).exists();
-		assertThrown(()->assertInteger(empty()).exists()).is("Value was null.");
-		assertInteger(1).exists();
-
-		assertInteger(empty()).doesNotExist();
-		assertThrown(()->assertInteger(1).doesNotExist()).is("Value was not null.");
-
-		assertInteger(empty()).isEqual(null);
-		assertInteger(1).isEqual(1);
-		assertInteger(of(1)).isEqual(1);
-
-		assertThrown(()->assertInteger(1).isEqual(2)).contains("Unexpected value.");
-		assertInteger(empty()).isEqual(null);
-
-		assertThrown(()->assertInteger(empty()).isGreaterThan(1)).is("Value was null.");
-		assertThrown(()->assertInteger(1).isGreaterThan(null)).is("Parameter 'value' cannot be null.");
-		assertInteger(2).isGreaterThan(1);
-		assertThrown(()->assertInteger(1).isGreaterThan(2)).is("Value was not greater than expected.\n\tExpect=[2]\n\tActual=[1]");
-		assertThrown(()->assertInteger(1).isGreaterThan(1)).is("Value was not greater than expected.\n\tExpect=[1]\n\tActual=[1]");
-
-		assertThrown(()->assertInteger(empty()).isGt(1)).is("Value was null.");
-		assertThrown(()->assertInteger(1).isGt(null)).is("Parameter 'value' cannot be null.");
-		assertInteger(2).isGt(1);
-		assertThrown(()->assertInteger(1).isGt(2)).is("Value was not greater than expected.\n\tExpect=[2]\n\tActual=[1]");
-		assertThrown(()->assertInteger(1).isGt(1)).is("Value was not greater than expected.\n\tExpect=[1]\n\tActual=[1]");
-
-		assertThrown(()->assertInteger(empty()).isGreaterThanOrEqual(1)).is("Value was null.");
-		assertThrown(()->assertInteger(1).isGreaterThanOrEqual(null)).is("Parameter 'value' cannot be null.");
-		assertInteger(2).isGreaterThanOrEqual(1);
-		assertThrown(()->assertInteger(1).isGreaterThanOrEqual(2)).is("Value was not greater than or equals to expected.\n\tExpect=[2]\n\tActual=[1]");
-		assertInteger(1).isGreaterThanOrEqual(1);
-
-		assertThrown(()->assertInteger(empty()).isGte(1)).is("Value was null.");
-		assertThrown(()->assertInteger(1).isGte(null)).is("Parameter 'value' cannot be null.");
-		assertInteger(2).isGte(1);
-		assertThrown(()->assertInteger(1).isGte(2)).is("Value was not greater than or equals to expected.\n\tExpect=[2]\n\tActual=[1]");
-		assertInteger(1).isGte(1);
-
-		assertThrown(()->assertInteger(empty()).isLessThan(1)).is("Value was null.");
-		assertThrown(()->assertInteger(1).isLessThan(null)).is("Parameter 'value' cannot be null.");
-		assertInteger(1).isLessThan(2);
-		assertThrown(()->assertInteger(2).isLessThan(1)).is("Value was not less than expected.\n\tExpect=[1]\n\tActual=[2]");
-		assertThrown(()->assertInteger(1).isLessThan(1)).is("Value was not less than expected.\n\tExpect=[1]\n\tActual=[1]");
-
-		assertThrown(()->assertInteger(empty()).isLt(1)).is("Value was null.");
-		assertThrown(()->assertInteger(1).isLt(null)).is("Parameter 'value' cannot be null.");
-		assertInteger(1).isLt(2);
-		assertThrown(()->assertInteger(2).isLt(1)).is("Value was not less than expected.\n\tExpect=[1]\n\tActual=[2]");
-		assertThrown(()->assertInteger(1).isLt(1)).is("Value was not less than expected.\n\tExpect=[1]\n\tActual=[1]");
-
-		assertThrown(()->assertInteger(empty()).isLessThanOrEqual(1)).is("Value was null.");
-		assertThrown(()->assertInteger(1).isLessThanOrEqual(null)).is("Parameter 'value' cannot be null.");
-		assertInteger(1).isLessThanOrEqual(2);
-		assertThrown(()->assertInteger(2).isLessThanOrEqual(1)).is("Value was not less than or equals to expected.\n\tExpect=[1]\n\tActual=[2]");
-		assertInteger(1).isLessThanOrEqual(1);
-
-		assertThrown(()->assertInteger(empty()).isLte(1)).is("Value was null.");
-		assertThrown(()->assertInteger(1).isLte(null)).is("Parameter 'value' cannot be null.");
-		assertInteger(1).isLte(2);
-		assertThrown(()->assertInteger(2).isLte(1)).is("Value was not less than or equals to expected.\n\tExpect=[1]\n\tActual=[2]");
-		assertInteger(1).isLte(1);
-
-		assertThrown(()->assertInteger(empty()).isBetween(1,3)).is("Value was null.");
-		assertThrown(()->assertInteger(2).isBetween(null,3)).is("Parameter 'lower' cannot be null.");
-		assertThrown(()->assertInteger(2).isBetween(1,null)).is("Parameter 'upper' cannot be null.");
-		assertInteger(2).isBetween(1,3);
-		assertInteger(1).isBetween(1,3);
-		assertInteger(3).isBetween(1,3);
-		assertThrown(()->assertInteger(2).isBetween(1,1)).is("Value was not less than or equals to expected.\n\tExpect=[1]\n\tActual=[2]");
-		assertThrown(()->assertInteger(2).isBetween(3,3)).is("Value was not greater than or equals to expected.\n\tExpect=[3]\n\tActual=[2]");
-
-		assertInteger(2).isNot("2");
+		assertThrown(()->test((Integer)null).exists()).is("Value was null.");
+		test(1).exists();
+		assertThrown(()->test(empty()).exists()).is("Value was null.");
+		test(1).exists();
+
+		test(empty()).doesNotExist();
+		assertThrown(()->test(1).doesNotExist()).is("Value was not null.");
+
+		test(empty()).isEqual(null);
+		test(1).isEqual(1);
+		test(of(1)).isEqual(1);
+
+		assertThrown(()->test(1).isEqual(2)).contains("Unexpected value.");
+		test(empty()).isEqual(null);
+
+		assertThrown(()->test(empty()).isGreaterThan(1)).is("Value was null.");
+		assertThrown(()->test(1).isGreaterThan(null)).is("Parameter 'value' cannot be null.");
+		test(2).isGreaterThan(1);
+		assertThrown(()->test(1).isGreaterThan(2)).is("Value was not greater than expected.\n\tExpect=[2]\n\tActual=[1]");
+		assertThrown(()->test(1).isGreaterThan(1)).is("Value was not greater than expected.\n\tExpect=[1]\n\tActual=[1]");
+
+		assertThrown(()->test(empty()).isGt(1)).is("Value was null.");
+		assertThrown(()->test(1).isGt(null)).is("Parameter 'value' cannot be null.");
+		test(2).isGt(1);
+		assertThrown(()->test(1).isGt(2)).is("Value was not greater than expected.\n\tExpect=[2]\n\tActual=[1]");
+		assertThrown(()->test(1).isGt(1)).is("Value was not greater than expected.\n\tExpect=[1]\n\tActual=[1]");
+
+		assertThrown(()->test(empty()).isGreaterThanOrEqual(1)).is("Value was null.");
+		assertThrown(()->test(1).isGreaterThanOrEqual(null)).is("Parameter 'value' cannot be null.");
+		test(2).isGreaterThanOrEqual(1);
+		assertThrown(()->test(1).isGreaterThanOrEqual(2)).is("Value was not greater than or equals to expected.\n\tExpect=[2]\n\tActual=[1]");
+		test(1).isGreaterThanOrEqual(1);
+
+		assertThrown(()->test(empty()).isGte(1)).is("Value was null.");
+		assertThrown(()->test(1).isGte(null)).is("Parameter 'value' cannot be null.");
+		test(2).isGte(1);
+		assertThrown(()->test(1).isGte(2)).is("Value was not greater than or equals to expected.\n\tExpect=[2]\n\tActual=[1]");
+		test(1).isGte(1);
+
+		assertThrown(()->test(empty()).isLessThan(1)).is("Value was null.");
+		assertThrown(()->test(1).isLessThan(null)).is("Parameter 'value' cannot be null.");
+		test(1).isLessThan(2);
+		assertThrown(()->test(2).isLessThan(1)).is("Value was not less than expected.\n\tExpect=[1]\n\tActual=[2]");
+		assertThrown(()->test(1).isLessThan(1)).is("Value was not less than expected.\n\tExpect=[1]\n\tActual=[1]");
+
+		assertThrown(()->test(empty()).isLt(1)).is("Value was null.");
+		assertThrown(()->test(1).isLt(null)).is("Parameter 'value' cannot be null.");
+		test(1).isLt(2);
+		assertThrown(()->test(2).isLt(1)).is("Value was not less than expected.\n\tExpect=[1]\n\tActual=[2]");
+		assertThrown(()->test(1).isLt(1)).is("Value was not less than expected.\n\tExpect=[1]\n\tActual=[1]");
+
+		assertThrown(()->test(empty()).isLessThanOrEqual(1)).is("Value was null.");
+		assertThrown(()->test(1).isLessThanOrEqual(null)).is("Parameter 'value' cannot be null.");
+		test(1).isLessThanOrEqual(2);
+		assertThrown(()->test(2).isLessThanOrEqual(1)).is("Value was not less than or equals to expected.\n\tExpect=[1]\n\tActual=[2]");
+		test(1).isLessThanOrEqual(1);
+
+		assertThrown(()->test(empty()).isLte(1)).is("Value was null.");
+		assertThrown(()->test(1).isLte(null)).is("Parameter 'value' cannot be null.");
+		test(1).isLte(2);
+		assertThrown(()->test(2).isLte(1)).is("Value was not less than or equals to expected.\n\tExpect=[1]\n\tActual=[2]");
+		test(1).isLte(1);
+
+		assertThrown(()->test(empty()).isBetween(1,3)).is("Value was null.");
+		assertThrown(()->test(2).isBetween(null,3)).is("Parameter 'lower' cannot be null.");
+		assertThrown(()->test(2).isBetween(1,null)).is("Parameter 'upper' cannot be null.");
+		test(2).isBetween(1,3);
+		test(1).isBetween(1,3);
+		test(3).isBetween(1,3);
+		assertThrown(()->test(2).isBetween(1,1)).is("Value was not less than or equals to expected.\n\tExpect=[1]\n\tActual=[2]");
+		assertThrown(()->test(2).isBetween(3,3)).is("Value was not greater than or equals to expected.\n\tExpect=[3]\n\tActual=[2]");
+
+		test(2).isNot("2");
 	}
 
 	@Test
 	public void a02_other() throws Exception {
-		assertThrown(()->IntegerAssertion.create(null).msg("Foo {0}", 1).exists()).is("Foo 1");
-		IntegerAssertion.create(null).stdout().silent();
+		assertThrown(()->test((Integer)null).msg("Foo {0}", 1).exists()).is("Foo 1");
+		test((Integer)null).stdout();
 	}
 }
diff --git a/juneau-utest/src/test/java/org/apache/juneau/assertions/ListAssertion_Test.java b/juneau-utest/src/test/java/org/apache/juneau/assertions/ListAssertion_Test.java
index de6062f..3205965 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/assertions/ListAssertion_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/assertions/ListAssertion_Test.java
@@ -23,38 +23,42 @@ import org.junit.*;
 @FixMethodOrder(NAME_ASCENDING)
 public class ListAssertion_Test {
 
+	private ListAssertion test(List<?> value) {
+		return assertList(value).silent();
+	}
+
 	@Test
 	public void a01_basic() throws Exception {
 		List<String> x1 = AList.create(), x2 = AList.of("a","b");
 
-		assertThrown(()->assertList(null).exists()).is("Value was null.");
-		assertList(x1).exists();
+		assertThrown(()->test(null).exists()).is("Value was null.");
+		test(x1).exists();
 
-		assertList(null).doesNotExist();
-		assertThrown(()->assertList(x1).doesNotExist()).is("Value was not null.");
+		test(null).doesNotExist();
+		assertThrown(()->test(x1).doesNotExist()).is("Value was not null.");
 
-		assertThrown(()->assertList(null).isSize(0)).is("Value was null.");
-		assertList(x1).isSize(0);
-		assertThrown(()->assertList(x1).isSize(1)).is("Collection did not have the expected size.  Expect=1, Actual=0.");
-		assertList(x2).isSize(2);
-		assertThrown(()->assertList(x2).isSize(0)).is("Collection did not have the expected size.  Expect=0, Actual=2.");
+		assertThrown(()->test(null).isSize(0)).is("Value was null.");
+		test(x1).isSize(0);
+		assertThrown(()->test(x1).isSize(1)).is("Collection did not have the expected size.  Expect=1, Actual=0.");
+		test(x2).isSize(2);
+		assertThrown(()->test(x2).isSize(0)).is("Collection did not have the expected size.  Expect=0, Actual=2.");
 
-		assertThrown(()->assertList(null).isEmpty()).is("Value was null.");
-		assertList(x1).isEmpty();
-		assertThrown(()->assertList(x2).isEmpty()).is("Collection was not empty.");
+		assertThrown(()->test(null).isEmpty()).is("Value was null.");
+		test(x1).isEmpty();
+		assertThrown(()->test(x2).isEmpty()).is("Collection was not empty.");
 
-		assertThrown(()->assertList(null).isNotEmpty()).is("Value was null.");
-		assertThrown(()->assertList(x1).isNotEmpty()).is("Collection was empty.");
-		assertList(x2).isNotEmpty();
+		assertThrown(()->test(null).isNotEmpty()).is("Value was null.");
+		assertThrown(()->test(x1).isNotEmpty()).is("Collection was empty.");
+		test(x2).isNotEmpty();
 
-		assertList(null).item(0).doesNotExist();
-		assertList(x1).item(0).doesNotExist();
-		assertList(x2).item(0).exists();
+		test(null).item(0).doesNotExist();
+		test(x1).item(0).doesNotExist();
+		test(x2).item(0).exists();
 	}
 
 	@Test
 	public void a02_other() throws Exception {
-		assertThrown(()->ListAssertion.create(null).msg("Foo {0}", 1).exists()).is("Foo 1");
-		ListAssertion.create(null).stdout().silent();
+		assertThrown(()->test(null).msg("Foo {0}", 1).exists()).is("Foo 1");
+		test(null).stdout();
 	}
 }
diff --git a/juneau-utest/src/test/java/org/apache/juneau/assertions/LongAssertion_Test.java b/juneau-utest/src/test/java/org/apache/juneau/assertions/LongAssertion_Test.java
index d4b9b19..7552785 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/assertions/LongAssertion_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/assertions/LongAssertion_Test.java
@@ -14,6 +14,9 @@ package org.apache.juneau.assertions;
 
 import static org.apache.juneau.assertions.Assertions.*;
 import static org.junit.runners.MethodSorters.*;
+
+import java.util.*;
+
 import static java.util.Optional.*;
 
 import org.junit.*;
@@ -21,90 +24,98 @@ import org.junit.*;
 @FixMethodOrder(NAME_ASCENDING)
 public class LongAssertion_Test {
 
+	private LongAssertion test(Long value) {
+		return assertLong(value).silent();
+	}
+
+	private LongAssertion test(Optional<Long> value) {
+		return assertLong(value).silent();
+	}
+
 	@Test
 	public void a01_basic() throws Exception {
 
-		assertThrown(()->assertLong((Long)null).exists()).is("Value was null.");
-		assertLong(1l).exists();
-		assertThrown(()->assertLong(empty()).exists()).is("Value was null.");
-		assertLong(1l).exists();
-
-		assertLong(empty()).doesNotExist();
-		assertThrown(()->assertLong(1l).doesNotExist()).is("Value was not null.");
-
-		assertLong(empty()).isEqual(null);
-		assertLong(of(1l)).isEqual(1l);
-		assertLong(1l).isEqual(1l);
-
-		assertThrown(()->assertLong(1l).isEqual(2)).contains("Unexpected value.");
-		assertLong(empty()).isEqual(null);
-
-		assertThrown(()->assertLong(empty()).isGreaterThan(1)).is("Value was null.");
-		assertThrown(()->assertLong(1l).isGreaterThan(null)).is("Parameter 'value' cannot be null.");
-		assertLong(2l).isGreaterThan(1);
-		assertThrown(()->assertLong(1l).isGreaterThan(2l)).is("Value was not greater than expected.\n\tExpect=[2]\n\tActual=[1]");
-		assertThrown(()->assertLong(1l).isGreaterThan(1l)).is("Value was not greater than expected.\n\tExpect=[1]\n\tActual=[1]");
-
-		assertLong(2l).asInteger().isGreaterThan(1);
-		assertLong(empty()).asInteger().isNull();
-
-		assertThrown(()->assertLong(empty()).isGt(1l)).is("Value was null.");
-		assertThrown(()->assertLong(1l).isGt(null)).is("Parameter 'value' cannot be null.");
-		assertLong(2l).isGt(1);
-		assertThrown(()->assertLong(1l).isGt(2)).is("Value was not greater than expected.\n\tExpect=[2]\n\tActual=[1]");
-		assertThrown(()->assertLong(1l).isGt(1)).is("Value was not greater than expected.\n\tExpect=[1]\n\tActual=[1]");
-
-		assertThrown(()->assertLong(empty()).isGreaterThanOrEqual(1)).is("Value was null.");
-		assertThrown(()->assertLong(1l).isGreaterThanOrEqual(null)).is("Parameter 'value' cannot be null.");
-		assertLong(2l).isGreaterThanOrEqual(1);
-		assertThrown(()->assertLong(1l).isGreaterThanOrEqual(2)).is("Value was not greater than or equals to expected.\n\tExpect=[2]\n\tActual=[1]");
-		assertLong(1l).isGreaterThanOrEqual(1);
-
-		assertThrown(()->assertLong(empty()).isGte(1)).is("Value was null.");
-		assertThrown(()->assertLong(1l).isGte(null)).is("Parameter 'value' cannot be null.");
-		assertLong(2l).isGte(1);
-		assertThrown(()->assertLong(1l).isGte(2l)).is("Value was not greater than or equals to expected.\n\tExpect=[2]\n\tActual=[1]");
-		assertLong(1l).isGte(1l);
-
-		assertThrown(()->assertLong(empty()).isLessThan(1)).is("Value was null.");
-		assertThrown(()->assertLong(1l).isLessThan(null)).is("Parameter 'value' cannot be null.");
-		assertLong(1l).isLessThan(2l);
-		assertThrown(()->assertLong(2l).isLessThan(1)).is("Value was not less than expected.\n\tExpect=[1]\n\tActual=[2]");
-		assertThrown(()->assertLong(1l).isLessThan(1)).is("Value was not less than expected.\n\tExpect=[1]\n\tActual=[1]");
-
-		assertThrown(()->assertLong(empty()).isLt(1)).is("Value was null.");
-		assertThrown(()->assertLong(1l).isLt(null)).is("Parameter 'value' cannot be null.");
-		assertLong(1l).isLt(2);
-		assertThrown(()->assertLong(2l).isLt(1)).is("Value was not less than expected.\n\tExpect=[1]\n\tActual=[2]");
-		assertThrown(()->assertLong(1l).isLt(1)).is("Value was not less than expected.\n\tExpect=[1]\n\tActual=[1]");
-
-		assertThrown(()->assertLong(empty()).isLessThanOrEqual(1)).is("Value was null.");
-		assertThrown(()->assertLong(1l).isLessThanOrEqual(null)).is("Parameter 'value' cannot be null.");
-		assertLong(1l).isLessThanOrEqual(2);
-		assertThrown(()->assertLong(2l).isLessThanOrEqual(1)).is("Value was not less than or equals to expected.\n\tExpect=[1]\n\tActual=[2]");
-		assertLong(1l).isLessThanOrEqual(1);
-
-		assertThrown(()->assertLong(empty()).isLte(1)).is("Value was null.");
-		assertThrown(()->assertLong(1l).isLte(null)).is("Parameter 'value' cannot be null.");
-		assertLong(1l).isLte(2);
-		assertThrown(()->assertLong(2l).isLte(1)).is("Value was not less than or equals to expected.\n\tExpect=[1]\n\tActual=[2]");
-		assertLong(1l).isLte(1);
-
-		assertThrown(()->assertLong(empty()).isBetween(1,3)).is("Value was null.");
-		assertThrown(()->assertLong(2l).isBetween(null,3)).is("Parameter 'lower' cannot be null.");
-		assertThrown(()->assertLong(2l).isBetween(1,null)).is("Parameter 'upper' cannot be null.");
-		assertLong(2l).isBetween(1,3);
-		assertLong(1l).isBetween(1,3);
-		assertLong(3l).isBetween(1,3);
-		assertThrown(()->assertLong(2l).isBetween(1,1)).is("Value was not less than or equals to expected.\n\tExpect=[1]\n\tActual=[2]");
-		assertThrown(()->assertLong(2l).isBetween(3,3)).is("Value was not greater than or equals to expected.\n\tExpect=[3]\n\tActual=[2]");
-
-		assertLong(2l).isNot("2");
+		assertThrown(()->test((Long)null).exists()).is("Value was null.");
+		test(1l).exists();
+		assertThrown(()->test(empty()).exists()).is("Value was null.");
+		test(1l).exists();
+
+		test(empty()).doesNotExist();
+		assertThrown(()->test(1l).doesNotExist()).is("Value was not null.");
+
+		test(empty()).isEqual(null);
+		test(of(1l)).isEqual(1l);
+		test(1l).isEqual(1l);
+
+		assertThrown(()->test(1l).isEqual(2)).contains("Unexpected value.");
+		test(empty()).isEqual(null);
+
+		assertThrown(()->test(empty()).isGreaterThan(1)).is("Value was null.");
+		assertThrown(()->test(1l).isGreaterThan(null)).is("Parameter 'value' cannot be null.");
+		test(2l).isGreaterThan(1);
+		assertThrown(()->test(1l).isGreaterThan(2l)).is("Value was not greater than expected.\n\tExpect=[2]\n\tActual=[1]");
+		assertThrown(()->test(1l).isGreaterThan(1l)).is("Value was not greater than expected.\n\tExpect=[1]\n\tActual=[1]");
+
+		test(2l).asInteger().isGreaterThan(1);
+		test(empty()).asInteger().isNull();
+
+		assertThrown(()->test(empty()).isGt(1l)).is("Value was null.");
+		assertThrown(()->test(1l).isGt(null)).is("Parameter 'value' cannot be null.");
+		test(2l).isGt(1);
+		assertThrown(()->test(1l).isGt(2)).is("Value was not greater than expected.\n\tExpect=[2]\n\tActual=[1]");
+		assertThrown(()->test(1l).isGt(1)).is("Value was not greater than expected.\n\tExpect=[1]\n\tActual=[1]");
+
+		assertThrown(()->test(empty()).isGreaterThanOrEqual(1)).is("Value was null.");
+		assertThrown(()->test(1l).isGreaterThanOrEqual(null)).is("Parameter 'value' cannot be null.");
+		test(2l).isGreaterThanOrEqual(1);
+		assertThrown(()->test(1l).isGreaterThanOrEqual(2)).is("Value was not greater than or equals to expected.\n\tExpect=[2]\n\tActual=[1]");
+		test(1l).isGreaterThanOrEqual(1);
+
+		assertThrown(()->test(empty()).isGte(1)).is("Value was null.");
+		assertThrown(()->test(1l).isGte(null)).is("Parameter 'value' cannot be null.");
+		test(2l).isGte(1);
+		assertThrown(()->test(1l).isGte(2l)).is("Value was not greater than or equals to expected.\n\tExpect=[2]\n\tActual=[1]");
+		test(1l).isGte(1l);
+
+		assertThrown(()->test(empty()).isLessThan(1)).is("Value was null.");
+		assertThrown(()->test(1l).isLessThan(null)).is("Parameter 'value' cannot be null.");
+		test(1l).isLessThan(2l);
+		assertThrown(()->test(2l).isLessThan(1)).is("Value was not less than expected.\n\tExpect=[1]\n\tActual=[2]");
+		assertThrown(()->test(1l).isLessThan(1)).is("Value was not less than expected.\n\tExpect=[1]\n\tActual=[1]");
+
+		assertThrown(()->test(empty()).isLt(1)).is("Value was null.");
+		assertThrown(()->test(1l).isLt(null)).is("Parameter 'value' cannot be null.");
+		test(1l).isLt(2);
+		assertThrown(()->test(2l).isLt(1)).is("Value was not less than expected.\n\tExpect=[1]\n\tActual=[2]");
+		assertThrown(()->test(1l).isLt(1)).is("Value was not less than expected.\n\tExpect=[1]\n\tActual=[1]");
+
+		assertThrown(()->test(empty()).isLessThanOrEqual(1)).is("Value was null.");
+		assertThrown(()->test(1l).isLessThanOrEqual(null)).is("Parameter 'value' cannot be null.");
+		test(1l).isLessThanOrEqual(2);
+		assertThrown(()->test(2l).isLessThanOrEqual(1)).is("Value was not less than or equals to expected.\n\tExpect=[1]\n\tActual=[2]");
+		test(1l).isLessThanOrEqual(1);
+
+		assertThrown(()->test(empty()).isLte(1)).is("Value was null.");
+		assertThrown(()->test(1l).isLte(null)).is("Parameter 'value' cannot be null.");
+		test(1l).isLte(2);
+		assertThrown(()->test(2l).isLte(1)).is("Value was not less than or equals to expected.\n\tExpect=[1]\n\tActual=[2]");
+		test(1l).isLte(1);
+
+		assertThrown(()->test(empty()).isBetween(1,3)).is("Value was null.");
+		assertThrown(()->test(2l).isBetween(null,3)).is("Parameter 'lower' cannot be null.");
+		assertThrown(()->test(2l).isBetween(1,null)).is("Parameter 'upper' cannot be null.");
+		test(2l).isBetween(1,3);
+		test(1l).isBetween(1,3);
+		test(3l).isBetween(1,3);
+		assertThrown(()->test(2l).isBetween(1,1)).is("Value was not less than or equals to expected.\n\tExpect=[1]\n\tActual=[2]");
+		assertThrown(()->test(2l).isBetween(3,3)).is("Value was not greater than or equals to expected.\n\tExpect=[3]\n\tActual=[2]");
+
+		test(2l).isNot("2");
 	}
 
 	@Test
 	public void a02_other() throws Exception {
-		assertThrown(()->LongAssertion.create(null).msg("Foo {0}", 1).exists()).is("Foo 1");
-		LongAssertion.create(null).stdout().silent();
+		assertThrown(()->test((Long)null).msg("Foo {0}", 1).exists()).is("Foo 1");
+		test((Long)null).stdout();
 	}
 }
diff --git a/juneau-utest/src/test/java/org/apache/juneau/assertions/MapAssertion_Test.java b/juneau-utest/src/test/java/org/apache/juneau/assertions/MapAssertion_Test.java
index f83e898..27b733d 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/assertions/MapAssertion_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/assertions/MapAssertion_Test.java
@@ -23,46 +23,50 @@ import org.junit.*;
 @FixMethodOrder(NAME_ASCENDING)
 public class MapAssertion_Test {
 
+	private MapAssertion test(Map<?,?> value) {
+		return assertMap(value).silent();
+	}
+
 	@Test
 	public void a01_basic() throws Exception {
 		Map<String,Integer> x1 = AMap.create(), x2 = AMap.of("a",1,"b",2);
 
-		assertThrown(()->assertMap(null).exists()).is("Value was null.");
-		assertMap(x1).exists();
+		assertThrown(()->test(null).exists()).is("Value was null.");
+		test(x1).exists();
 
 		assertCollection(null).doesNotExist();
-		assertThrown(()->assertMap(x1).doesNotExist()).is("Value was not null.");
+		assertThrown(()->test(x1).doesNotExist()).is("Value was not null.");
 
-		assertThrown(()->assertMap(null).isSize(0)).is("Value was null.");
-		assertMap(x1).isSize(0);
-		assertThrown(()->assertMap(x1).isSize(1)).is("Map did not have the expected size.  Expect=1, Actual=0.");
-		assertMap(x2).isSize(2);
-		assertThrown(()->assertMap(x2).isSize(0)).is("Map did not have the expected size.  Expect=0, Actual=2.");
+		assertThrown(()->test(null).isSize(0)).is("Value was null.");
+		test(x1).isSize(0);
+		assertThrown(()->test(x1).isSize(1)).is("Map did not have the expected size.  Expect=1, Actual=0.");
+		test(x2).isSize(2);
+		assertThrown(()->test(x2).isSize(0)).is("Map did not have the expected size.  Expect=0, Actual=2.");
 
-		assertThrown(()->assertMap(null).isEmpty()).is("Value was null.");
-		assertMap(x1).isEmpty();
-		assertThrown(()->assertMap(x2).isEmpty()).is("Map was not empty.");
+		assertThrown(()->test(null).isEmpty()).is("Value was null.");
+		test(x1).isEmpty();
+		assertThrown(()->test(x2).isEmpty()).is("Map was not empty.");
 
-		assertThrown(()->assertMap(null).isNotEmpty()).is("Value was null.");
-		assertThrown(()->assertMap(x1).isNotEmpty()).is("Map was empty.");
-		assertMap(x2).isNotEmpty();
+		assertThrown(()->test(null).isNotEmpty()).is("Value was null.");
+		assertThrown(()->test(x1).isNotEmpty()).is("Map was empty.");
+		test(x2).isNotEmpty();
 
-		assertMap(x2).value("a").asInteger().is(1);
-		assertMap(x2).value("z").asInteger().isNull();
-		assertMap((Map<?,?>)null).value("a").asInteger().isNull();
+		test(x2).value("a").asInteger().is(1);
+		test(x2).value("z").asInteger().isNull();
+		test((Map<?,?>)null).value("a").asInteger().isNull();
 
-		assertMap(x2).containsKey("a");
-		assertThrown(()->assertMap(x2).containsKey("x")).is("Map did not contain expected key.\n\tContents: {a:1,b:2}\n\tExpected key: x");
-		assertThrown(()->assertMap((Map<?,?>)null).containsKey("x")).is("Value was null.");
+		test(x2).containsKey("a");
+		assertThrown(()->test(x2).containsKey("x")).is("Map did not contain expected key.\n\tContents: {a:1,b:2}\n\tExpected key: x");
+		assertThrown(()->test((Map<?,?>)null).containsKey("x")).is("Value was null.");
 
-		assertMap(x2).doesNotContainKey("x");
-		assertThrown(()->assertMap(x2).doesNotContainKey("a")).is("Map contained unexpected key.\n\tContents: {a:1,b:2}\n\tUnexpected key: a");
-		assertThrown(()->assertMap((Map<?,?>)null).containsKey("x")).is("Value was null.");
+		test(x2).doesNotContainKey("x");
+		assertThrown(()->test(x2).doesNotContainKey("a")).is("Map contained unexpected key.\n\tContents: {a:1,b:2}\n\tUnexpected key: a");
+		assertThrown(()->test((Map<?,?>)null).containsKey("x")).is("Value was null.");
 	}
 
 	@Test
 	public void a02_other() throws Exception {
-		assertThrown(()->MapAssertion.create(null).msg("Foo {0}", 1).exists()).is("Foo 1");
-		MapAssertion.create(null).stdout().silent();
+		assertThrown(()->test(null).msg("Foo {0}", 1).exists()).is("Foo 1");
+		test(null).stdout();
 	}
 }
diff --git a/juneau-utest/src/test/java/org/apache/juneau/assertions/ObjectAssertion_Test.java b/juneau-utest/src/test/java/org/apache/juneau/assertions/ObjectAssertion_Test.java
index 65712c7..01ac6ac 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/assertions/ObjectAssertion_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/assertions/ObjectAssertion_Test.java
@@ -26,6 +26,14 @@ import org.junit.*;
 @FixMethodOrder(NAME_ASCENDING)
 public class ObjectAssertion_Test {
 
+	private <T> ObjectAssertion<T> test(T value) {
+		return assertObject(value).silent();
+	}
+
+	private <T> ObjectAssertion<T> test(Optional<T> value) {
+		return assertObject(value).silent();
+	}
+
 	public static class A1 {
 		public int getFoo() {
 			throw new RuntimeException("foo");
@@ -43,95 +51,95 @@ public class ObjectAssertion_Test {
 
 	@Test
 	public void a01_basic() throws Exception {
-		assertObject((Object)null).doesNotExist();
-		assertObject(empty()).doesNotExist();
-		assertObject(1).exists();
-		assertObject(of(1)).exists();
+		test((Object)null).doesNotExist();
+		test(empty()).doesNotExist();
+		test(1).exists();
+		test(of(1)).exists();
 
-		assertThrown(()->assertObject(empty()).isType(null)).is("Value was null.");
-		assertThrown(()->assertObject("foo").isType(null)).is("Parameter 'parent' cannot be null.");
-		assertObject("foo").isType(String.class);
-		assertObject("foo").isType(CharSequence.class);
-		assertObject("foo").isType(Comparable.class);
-		assertThrown(()->assertObject(1).isType(String.class)).is("Unexpected class.\n\tExpect=[java.lang.String]\n\tActual=[java.lang.Integer]");
+		assertThrown(()->test(empty()).isType(null)).is("Value was null.");
+		assertThrown(()->test("foo").isType(null)).is("Parameter 'parent' cannot be null.");
+		test("foo").isType(String.class);
+		test("foo").isType(CharSequence.class);
+		test("foo").isType(Comparable.class);
+		assertThrown(()->test(1).isType(String.class)).is("Unexpected class.\n\tExpect=[java.lang.String]\n\tActual=[java.lang.Integer]");
 
-		assertObject("foo").asString(JsonSerializer.DEFAULT).is("\"foo\"");
-		assertObject(empty()).asString(JsonSerializer.DEFAULT).is("null");
+		test("foo").asString(JsonSerializer.DEFAULT).is("\"foo\"");
+		test(empty()).asString(JsonSerializer.DEFAULT).is("null");
 
-		assertThrown(()->assertObject(new A1()).asJson()).contains("Could not call getValue() on property 'foo'");
+		assertThrown(()->test(new A1()).asJson()).contains("Could not call getValue() on property 'foo'");
 
-		assertObject("foo").asJson().is("'foo'");
-		assertObject(empty()).asString(JsonSerializer.DEFAULT).is("null");
+		test("foo").asJson().is("'foo'");
+		test(empty()).asString(JsonSerializer.DEFAULT).is("null");
 
-		assertObject(new A2()).asJsonSorted().is("{bar:2,foo:1}");
+		test(new A2()).asJsonSorted().is("{bar:2,foo:1}");
 
 		int[] x1 = {1,2}, x2 = {2,1};
-		assertObject(x2).asJsonSorted().is("[1,2]");
-		assertThrown(()->assertObject(x2).asJsonSorted().is("[2,1]")).is("Unexpected value.\n\tExpect=[[2,1]]\n\tActual=[[1,2]]");
-		assertObject(empty()).asJsonSorted().is("null");
+		test(x2).asJsonSorted().is("[1,2]");
+		assertThrown(()->test(x2).asJsonSorted().is("[2,1]")).is("Unexpected value.\n\tExpect=[[2,1]]\n\tActual=[[1,2]]");
+		test(empty()).asJsonSorted().is("null");
 
-		assertObject(x1).isSameJsonAs(x1);
-		assertThrown(()->assertObject(x1).isSameJsonAs(x2)).is("Unexpected comparison.\n\tExpect=[[2,1]]\n\tActual=[[1,2]]");
-		assertObject(empty()).isSameJsonAs(null);
-		assertThrown(()->assertObject(new A1()).isSameJsonAs(null)).contains("Could not call getValue() on property 'foo'");
+		test(x1).isSameJsonAs(x1);
+		assertThrown(()->test(x1).isSameJsonAs(x2)).is("Unexpected comparison.\n\tExpect=[[2,1]]\n\tActual=[[1,2]]");
+		test(empty()).isSameJsonAs(null);
+		assertThrown(()->test(new A1()).isSameJsonAs(null)).contains("Could not call getValue() on property 'foo'");
 
-		assertObject(x1).isSameSortedAs(x1);
-		assertObject(x1).isSameSortedAs(x2);
-		assertThrown(()->assertObject(x1).isSameJsonAs(null)).is("Unexpected comparison.\n\tExpect=[null]\n\tActual=[[1,2]]");
-		assertObject(empty()).isSameSortedAs(null);
+		test(x1).isSameSortedAs(x1);
+		test(x1).isSameSortedAs(x2);
+		assertThrown(()->test(x1).isSameJsonAs(null)).is("Unexpected comparison.\n\tExpect=[null]\n\tActual=[[1,2]]");
+		test(empty()).isSameSortedAs(null);
 
-		assertObject(x1).doesNotEqual(null);
-		assertObject(empty()).doesNotEqual(x1);
-		assertObject(x1).doesNotEqual(x2);
-		assertThrown(()->assertObject(empty()).doesNotEqual(null)).is("Unexpected value.\n\tExpected not=[null]\n\tActual=[null]");
-		assertThrown(()->assertObject(x1).doesNotEqual(x1)).is("Unexpected value.\n\tExpected not=[[1,2]]\n\tActual=[[1,2]]");
+		test(x1).doesNotEqual(null);
+		test(empty()).doesNotEqual(x1);
+		test(x1).doesNotEqual(x2);
+		assertThrown(()->test(empty()).doesNotEqual(null)).is("Unexpected value.\n\tExpected not=[null]\n\tActual=[null]");
+		assertThrown(()->test(x1).doesNotEqual(x1)).is("Unexpected value.\n\tExpected not=[[1,2]]\n\tActual=[[1,2]]");
 
-		assertObject(x1).passes(x->x != null);
-		assertThrown(()->assertObject(x1).passes(x->x == null)).is("Value did not pass predicate test.\n\tValue=[[1,2]]");
+		test(x1).passes(x->x != null);
+		assertThrown(()->test(x1).passes(x->x == null)).is("Value did not pass predicate test.\n\tValue=[[1,2]]");
 
-		assertObject(x1).passes(x->x[0] == 1);
-		assertThrown(()->assertObject(x1).passes(x->x[0]==2)).is("Value did not pass predicate test.\n\tValue=[[1,2]]");
+		test(x1).passes(x->x[0] == 1);
+		assertThrown(()->test(x1).passes(x->x[0]==2)).is("Value did not pass predicate test.\n\tValue=[[1,2]]");
 
-		assertObject(x1).isNot(null);
+		test(x1).isNot(null);
 
-		assertObject(x1).isAny(x1,x2);
-		assertThrown(()->assertObject(x1).isAny(x2)).is("Expected value not found.\n\tExpect=[[[2,1]]]\n\tActual=[[1,2]]");
+		test(x1).isAny(x1,x2);
+		assertThrown(()->test(x1).isAny(x2)).is("Expected value not found.\n\tExpect=[[[2,1]]]\n\tActual=[[1,2]]");
 
-		assertObject(x1).isNotAny(x2);
-		assertThrown(()->assertObject(x1).isNotAny(x1,x2)).is("Unexpected value found.\n\tUnexpected=[[1,2]]\n\tActual=[[1,2]]");
+		test(x1).isNotAny(x2);
+		assertThrown(()->test(x1).isNotAny(x1,x2)).is("Unexpected value found.\n\tUnexpected=[[1,2]]\n\tActual=[[1,2]]");
 
 		Date d1 = new Date(0), d2 = new Date(0);
-		assertObject(d1).is(d2);
+		test(d1).is(d2);
 
-		assertObject(123).asString().is("123");
-		assertObject((Object)null).asString().isNull();
+		test(123).asString().is("123");
+		test((Object)null).asString().isNull();
 
-		assertObject(123).asString(x -> x.toString()).is("123");
-		assertObject(123).asString(Integer.class, x -> String.valueOf(x.intValue())).is("123");
+		test(123).asString(x -> x.toString()).is("123");
+		test(123).asString(Integer.class, x -> String.valueOf(x.intValue())).is("123");
 	}
 
 	@Test
 	public void a02_other() throws Exception {
-		assertThrown(()->ObjectAssertion.create(null).msg("Foo {0}", 1).exists()).is("Foo 1");
-		ObjectAssertion.create(null).stdout().silent();
+		assertThrown(()->test((Object)null).msg("Foo {0}", 1).exists()).is("Foo 1");
+		test((Object)null).stdout();
 	}
 
 	@Test
 	public void a03_conversions() throws Exception {
-		assertObject(new String[]{"foo"}).asArray().item(0).is("foo");
-		assertThrown(()->assertObject("foo").asArray()).contains("Object was not an array");
-
-		assertObject(true).asBoolean().isTrue();
-		assertThrown(()->assertObject("foo").asBoolean()).contains("Object was not type 'java.lang.Boolean'.  Actual='java.lang.String'");
-
-		assertObject(new byte[]{123}).asByteArray().asJson().is("[123]");
-		assertObject(AList.of(123)).asCollection().asJson().is("[123]");
-		assertObject(123).asComparable().asJson().is("123");
-		assertObject(new Date()).asDate().isType(Date.class);
-		assertObject(123).asInteger().asJson().is("123");
-		assertObject(AList.of(123)).asList().asJson().is("[123]");
-		assertObject(123l).asLong().asJson().is("123");
-		assertObject(AMap.create()).asMap().asJson().is("{}");
-		assertObject(ZonedDateTime.now()).asZonedDateTime().isType(ZonedDateTime.class);
+		test(new String[]{"foo"}).asArray().item(0).is("foo");
+		assertThrown(()->test("foo").asArray()).contains("Object was not an array");
+
+		test(true).asBoolean().isTrue();
+		assertThrown(()->test("foo").asBoolean()).contains("Object was not type 'java.lang.Boolean'.  Actual='java.lang.String'");
+
+		test(new byte[]{123}).asByteArray().asJson().is("[123]");
+		test(AList.of(123)).asCollection().asJson().is("[123]");
+		test(123).asComparable().asJson().is("123");
+		test(new Date()).asDate().isType(Date.class);
+		test(123).asInteger().asJson().is("123");
+		test(AList.of(123)).asList().asJson().is("[123]");
+		test(123l).asLong().asJson().is("123");
+		test(AMap.create()).asMap().asJson().is("{}");
+		test(ZonedDateTime.now()).asZonedDateTime().isType(ZonedDateTime.class);
 	}
 }
diff --git a/juneau-utest/src/test/java/org/apache/juneau/assertions/StringAssertion_Test.java b/juneau-utest/src/test/java/org/apache/juneau/assertions/StringAssertion_Test.java
index b63ef07..ebad9f5 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/assertions/StringAssertion_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/assertions/StringAssertion_Test.java
@@ -14,6 +14,9 @@ package org.apache.juneau.assertions;
 
 import static org.apache.juneau.assertions.Assertions.*;
 import static org.junit.runners.MethodSorters.*;
+
+import java.util.*;
+
 import static java.util.Optional.*;
 
 import org.junit.*;
@@ -21,121 +24,129 @@ import org.junit.*;
 @FixMethodOrder(NAME_ASCENDING)
 public class StringAssertion_Test {
 
+	private StringAssertion test(Object value) {
+		return assertString(value).silent();
+	}
+
+	private StringAssertion test(Optional<Object> value) {
+		return assertString(value).silent();
+	}
+
 	@Test
 	public void a01_basic() throws Exception {
-		assertString((String)null).doesNotExist();
-		assertString(empty()).doesNotExist();
-		assertString(1).exists();
-
-		assertString("foobar").replaceAll("fo+","bar").is("barbar").is("foobar");
-		assertString(of("foobar")).replaceAll("fo+","bar").is("barbar").is("foobar");
-		assertString(empty()).replaceAll("fo+","bar").isNull();
-		assertThrown(()->assertString("foobar").replaceAll(null,"")).is("Parameter 'regex' cannot be null.");
-		assertThrown(()->assertString("foobar").replaceAll("",null)).is("Parameter 'replacement' cannot be null.");
-
-		assertString("foobar").replace("foo","bar").is("barbar").is("foobar");
-		assertString(empty()).replace("foo","bar").isNull();
-		assertThrown(()->assertString("").replace(null,"bar").isNull()).is("Parameter 'target' cannot be null.");
-		assertThrown(()->assertString("").replace("foo",null).isNull()).is("Parameter 'replacement' cannot be null.");
-
-		assertString("foo%20bar").urlDecode().is("foo bar").is("foo%20bar");
-		assertString(empty()).urlDecode().isNull();
-
-		assertString("foo\nbar\nbaz").sort().is("bar\nbaz\nfoo").is("foo\nbar\nbaz");
-		assertString(empty()).sort().doesNotExist();
-
-		assertString("FOOBAR").lc().is("foobar").is("FOOBAR");
-		assertString(empty()).lc().isNull();
-
-		assertString("foobar").uc().is("FOOBAR").is("foobar");
-		assertString(empty()).uc().isNull();
-
-		assertString("foo\nbar\nbaz").isEqualLinesTo("foo","bar","baz");
-		assertThrown(()->assertString(empty()).isEqualLinesTo((String[])null)).is("Parameter 'lines' cannot be null.");
-		assertThrown(()->assertString(empty()).isEqualLinesTo((String)null)).is("Text differed at position -1.\n\tExpect=[]\n\tActual=[null]");
-		assertThrown(()->assertString("foo\nbar\nbaz").javaStrings().isEqualLinesTo("foo","bar","bar")).is("Text differed at position 10.\n\tExpect=[foo\\nbar\\nbar]\n\tActual=[foo\\nbar\\nbaz]");
-
-		assertString("foo\nbar\nbaz").isEqualSortedLinesTo("bar","foo","baz");
-		assertThrown(()->assertString(empty()).isEqualSortedLinesTo((String[])null)).is("Parameter 'lines' cannot be null.");
-		assertString("").isEqualSortedLinesTo((String)null);
-		assertThrown(()->assertString(empty()).isEqualSortedLinesTo()).is("Value was null.");
-		assertThrown(()->assertString("foo\nbar\nbaz").isEqualSortedLinesTo("bar","foo","bar")).is("Expected text had different values at line 2.\n\tExpect=[bar]\n\tActual=[baz]");
-		assertThrown(()->assertString("foo\nbar\nbaz").isEqualSortedLinesTo("bar","foo")).is("Expected text had different numbers of lines.\n\tExpect=[2]\n\tActual=[3]");
-		assertThrown(()->assertString(empty()).isEqualSortedLinesTo("foo")).is("Value was null.");
-		assertThrown(()->assertString("foo").isEqualSortedLinesTo((String)null)).is("Expected text had different values at line 1.\n\tExpect=[]\n\tActual=[foo]");
-
-		assertString("foo\nbar\nbaz").isEqualLinesTo("foo","bar","baz");
-
-		assertString("foobar").isEqualIgnoreCaseTo("FOOBAR");
-		assertString(empty()).isEqualIgnoreCaseTo(null);
-		assertThrown(()->assertString("foobar").isEqualIgnoreCaseTo("FOOBAZ")).is("Text differed at position 5.\n\tExpect=[FOOBAZ]\n\tActual=[foobar]");
-		assertThrown(()->assertString(empty()).isEqualIgnoreCaseTo("FOOBAZ")).is("Text differed at position 0.\n\tExpect=[FOOBAZ]\n\tActual=[null]");
-		assertThrown(()->assertString("foobar").isEqualIgnoreCaseTo(null)).is("Text differed at position 0.\n\tExpect=[null]\n\tActual=[foobar]");
-
-		assertString("foobar").doesNotEqual("foobaz");
-		assertThrown(()->assertString("foobar").doesNotEqual("foobar")).is("Text equaled unexpected.\n\tText=[foobar]");
-
-		assertThrown(()->assertString("foobar").isEqualTo("foobaz")).is("Text differed at position 5.\n\tExpect=[foobaz]\n\tActual=[foobar]");
-
-		assertString("foobar").isNot("foobaz");
-		assertThrown(()->assertString("foobar").isNot("foobar")).is("Text equaled unexpected.\n\tText=[foobar]");
-		assertThrown(()->assertString(empty()).isNot(null)).is("Text equaled unexpected.\n\tText=[null]");
-		assertString("foobar").isNot(null);
-		assertString(empty()).isNot("foobar");
-
-		assertString("foobar").doesNotEqualIc("foobaz");
-		assertThrown(()->assertString("foobar").doesNotEqualIc("Foobar")).is("Text equaled unexpected.\n\tText=[foobar]");
-		assertThrown(()->assertString(empty()).doesNotEqualIc(null)).is("Text equaled unexpected.\n\tText=[null]");
-		assertString("foobar").doesNotEqualIc(null);
-		assertString(empty()).doesNotEqualIc("foobar");
-
-		assertString("foobar").contains("foo","bar");
-		assertThrown(()->assertString("foobar").contains("foo","baz")).is("Text did not contain expected substring.\n\tSubstring=[baz]\n\tText=[foobar]");
-		assertString(empty()).contains();
-		assertThrown(()->assertString("foobar").contains((String[])null)).is("Parameter 'values' cannot be null.");
-		assertString("foobar").contains((String)null);
-		assertThrown(()->assertString(empty()).contains("foobar")).is("Text did not contain expected substring.\n\tSubstring=[foobar]\n\tText=[null]");
-
-		assertString("foobar").doesNotContain("baz","qux");
-		assertThrown(()->assertString("foobar").doesNotContain("foo","baz")).is("Text contained unexpected substring.\n\tSubstring=[foo]\n\tText=[foobar]");
-		assertString(empty()).doesNotContain();
-		assertThrown(()->assertString("foobar").doesNotContain((String[])null)).is("Parameter 'values' cannot be null.");
-		assertString("foobar").doesNotContain((String)null);
-		assertString(empty()).doesNotContain("foobar");
-
-		assertString("").isEmpty();
-		assertString(empty()).isEmpty();
-		assertThrown(()->assertString("foo").isEmpty()).is("Text was not empty.\n\tText=[foo]");
-
-		assertString("foo").isNotEmpty();
-		assertThrown(()->assertString("").isNotEmpty()).is("Text was empty.");
-		assertThrown(()->assertString(empty()).isNotEmpty()).is("Text was null.");
-
-		assertString("foo").matches("fo+");
-		assertThrown(()->assertString("foo").matches("bar")).is("Text did not match expected pattern.\n\tPattern=[bar]\n\tText=[foo]");
-		assertThrown(()->assertString(empty()).matches("fo+")).is("Value was null.");
-		assertThrown(()->assertString("").matches((String)null)).is("Parameter 'regex' cannot be null.");
-
-		assertString("foo").matchesSimple("fo*");
-		assertThrown(()->assertString("foo").matchesSimple("b*")).is("Text did not match expected pattern.\n\tPattern=[\\Qb\\E.*\\Q\\E]\n\tText=[foo]");
-		assertThrown(()->assertString(empty()).matchesSimple("b*")).is("Value was null.");
-		assertThrown(()->assertString("").matchesSimple(null)).is("Parameter 'searchPattern' cannot be null.");
-
-		assertString("foo").doesNotMatch("b.*");
-		assertThrown(()->assertString("foo").doesNotMatch("fo+")).is("Text matched unexpected pattern.\n\tPattern=[fo+]\n\tText=[foo]");
-		assertString(empty()).doesNotMatch("fo+");
-		assertThrown(()->assertString("").doesNotMatch((String)null)).is("Parameter 'regex' cannot be null.");
-
-		assertString("foo").startsWith("fo");
-		assertThrown(()->assertString("foo").startsWith("x")).is("Text did not start with expected string.\n\tString=[x]\n\tText=[foo]");
-
-		assertString("foo").endsWith("oo");
-		assertThrown(()->assertString("foo").endsWith("x")).is("Text did not end with expected string.\n\tString=[x]\n\tText=[foo]");
+		test((String)null).doesNotExist();
+		test(empty()).doesNotExist();
+		test(1).exists();
+
+		test("foobar").replaceAll("fo+","bar").is("barbar").is("foobar");
+		test(of("foobar")).replaceAll("fo+","bar").is("barbar").is("foobar");
+		test(empty()).replaceAll("fo+","bar").isNull();
+		assertThrown(()->test("foobar").replaceAll(null,"")).is("Parameter 'regex' cannot be null.");
+		assertThrown(()->test("foobar").replaceAll("",null)).is("Parameter 'replacement' cannot be null.");
+
+		test("foobar").replace("foo","bar").is("barbar").is("foobar");
+		test(empty()).replace("foo","bar").isNull();
+		assertThrown(()->test("").replace(null,"bar").isNull()).is("Parameter 'target' cannot be null.");
+		assertThrown(()->test("").replace("foo",null).isNull()).is("Parameter 'replacement' cannot be null.");
+
+		test("foo%20bar").urlDecode().is("foo bar").is("foo%20bar");
+		test(empty()).urlDecode().isNull();
+
+		test("foo\nbar\nbaz").sort().is("bar\nbaz\nfoo").is("foo\nbar\nbaz");
+		test(empty()).sort().doesNotExist();
+
+		test("FOOBAR").lc().is("foobar").is("FOOBAR");
+		test(empty()).lc().isNull();
+
+		test("foobar").uc().is("FOOBAR").is("foobar");
+		test(empty()).uc().isNull();
+
+		test("foo\nbar\nbaz").isEqualLinesTo("foo","bar","baz");
+		assertThrown(()->test(empty()).isEqualLinesTo((String[])null)).is("Parameter 'lines' cannot be null.");
+		assertThrown(()->test(empty()).isEqualLinesTo((String)null)).is("Text differed at position -1.\n\tExpect=[]\n\tActual=[null]");
+		assertThrown(()->test("foo\nbar\nbaz").javaStrings().isEqualLinesTo("foo","bar","bar")).is("Text differed at position 10.\n\tExpect=[foo\\nbar\\nbar]\n\tActual=[foo\\nbar\\nbaz]");
+
+		test("foo\nbar\nbaz").isEqualSortedLinesTo("bar","foo","baz");
+		assertThrown(()->test(empty()).isEqualSortedLinesTo((String[])null)).is("Parameter 'lines' cannot be null.");
+		test("").isEqualSortedLinesTo((String)null);
+		assertThrown(()->test(empty()).isEqualSortedLinesTo()).is("Value was null.");
+		assertThrown(()->test("foo\nbar\nbaz").isEqualSortedLinesTo("bar","foo","bar")).is("Expected text had different values at line 2.\n\tExpect=[bar]\n\tActual=[baz]");
+		assertThrown(()->test("foo\nbar\nbaz").isEqualSortedLinesTo("bar","foo")).is("Expected text had different numbers of lines.\n\tExpect=[2]\n\tActual=[3]");
+		assertThrown(()->test(empty()).isEqualSortedLinesTo("foo")).is("Value was null.");
+		assertThrown(()->test("foo").isEqualSortedLinesTo((String)null)).is("Expected text had different values at line 1.\n\tExpect=[]\n\tActual=[foo]");
+
+		test("foo\nbar\nbaz").isEqualLinesTo("foo","bar","baz");
+
+		test("foobar").isEqualIgnoreCaseTo("FOOBAR");
+		test(empty()).isEqualIgnoreCaseTo(null);
+		assertThrown(()->test("foobar").isEqualIgnoreCaseTo("FOOBAZ")).is("Text differed at position 5.\n\tExpect=[FOOBAZ]\n\tActual=[foobar]");
+		assertThrown(()->test(empty()).isEqualIgnoreCaseTo("FOOBAZ")).is("Text differed at position 0.\n\tExpect=[FOOBAZ]\n\tActual=[null]");
+		assertThrown(()->test("foobar").isEqualIgnoreCaseTo(null)).is("Text differed at position 0.\n\tExpect=[null]\n\tActual=[foobar]");
+
+		test("foobar").doesNotEqual("foobaz");
+		assertThrown(()->test("foobar").doesNotEqual("foobar")).is("Text equaled unexpected.\n\tText=[foobar]");
+
+		assertThrown(()->test("foobar").isEqualTo("foobaz")).is("Text differed at position 5.\n\tExpect=[foobaz]\n\tActual=[foobar]");
+
+		test("foobar").isNot("foobaz");
+		assertThrown(()->test("foobar").isNot("foobar")).is("Text equaled unexpected.\n\tText=[foobar]");
+		assertThrown(()->test(empty()).isNot(null)).is("Text equaled unexpected.\n\tText=[null]");
+		test("foobar").isNot(null);
+		test(empty()).isNot("foobar");
+
+		test("foobar").doesNotEqualIc("foobaz");
+		assertThrown(()->test("foobar").doesNotEqualIc("Foobar")).is("Text equaled unexpected.\n\tText=[foobar]");
+		assertThrown(()->test(empty()).doesNotEqualIc(null)).is("Text equaled unexpected.\n\tText=[null]");
+		test("foobar").doesNotEqualIc(null);
+		test(empty()).doesNotEqualIc("foobar");
+
+		test("foobar").contains("foo","bar");
+		assertThrown(()->test("foobar").contains("foo","baz")).is("Text did not contain expected substring.\n\tSubstring=[baz]\n\tText=[foobar]");
+		test(empty()).contains();
+		assertThrown(()->test("foobar").contains((String[])null)).is("Parameter 'values' cannot be null.");
+		test("foobar").contains((String)null);
+		assertThrown(()->test(empty()).contains("foobar")).is("Text did not contain expected substring.\n\tSubstring=[foobar]\n\tText=[null]");
+
+		test("foobar").doesNotContain("baz","qux");
+		assertThrown(()->test("foobar").doesNotContain("foo","baz")).is("Text contained unexpected substring.\n\tSubstring=[foo]\n\tText=[foobar]");
+		test(empty()).doesNotContain();
+		assertThrown(()->test("foobar").doesNotContain((String[])null)).is("Parameter 'values' cannot be null.");
+		test("foobar").doesNotContain((String)null);
+		test(empty()).doesNotContain("foobar");
+
+		test("").isEmpty();
+		test(empty()).isEmpty();
+		assertThrown(()->test("foo").isEmpty()).is("Text was not empty.\n\tText=[foo]");
+
+		test("foo").isNotEmpty();
+		assertThrown(()->test("").isNotEmpty()).is("Text was empty.");
+		assertThrown(()->test(empty()).isNotEmpty()).is("Text was null.");
+
+		test("foo").matches("fo+");
+		assertThrown(()->test("foo").matches("bar")).is("Text did not match expected pattern.\n\tPattern=[bar]\n\tText=[foo]");
+		assertThrown(()->test(empty()).matches("fo+")).is("Value was null.");
+		assertThrown(()->test("").matches((String)null)).is("Parameter 'regex' cannot be null.");
+
+		test("foo").matchesSimple("fo*");
+		assertThrown(()->test("foo").matchesSimple("b*")).is("Text did not match expected pattern.\n\tPattern=[\\Qb\\E.*\\Q\\E]\n\tText=[foo]");
+		assertThrown(()->test(empty()).matchesSimple("b*")).is("Value was null.");
+		assertThrown(()->test("").matchesSimple(null)).is("Parameter 'searchPattern' cannot be null.");
+
+		test("foo").doesNotMatch("b.*");
+		assertThrown(()->test("foo").doesNotMatch("fo+")).is("Text matched unexpected pattern.\n\tPattern=[fo+]\n\tText=[foo]");
+		test(empty()).doesNotMatch("fo+");
+		assertThrown(()->test("").doesNotMatch((String)null)).is("Parameter 'regex' cannot be null.");
+
+		test("foo").startsWith("fo");
+		assertThrown(()->test("foo").startsWith("x")).is("Text did not start with expected string.\n\tString=[x]\n\tText=[foo]");
+
+		test("foo").endsWith("oo");
+		assertThrown(()->test("foo").endsWith("x")).is("Text did not end with expected string.\n\tString=[x]\n\tText=[foo]");
 	}
 
 	@Test
 	public void a02_other() throws Exception {
-		assertThrown(()->StringAssertion.create(null).msg("Foo {0}", 1).exists()).is("Foo 1");
-		StringAssertion.create(null).stdout().silent().javaStrings();
+		assertThrown(()->test((String)null).msg("Foo {0}", 1).exists()).is("Foo 1");
+		test((String)null).stdout().javaStrings();
 	}
 }
diff --git a/juneau-utest/src/test/java/org/apache/juneau/assertions/ThrowableAssertion_Test.java b/juneau-utest/src/test/java/org/apache/juneau/assertions/ThrowableAssertion_Test.java
index 0454e1a..be1bd1a 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/assertions/ThrowableAssertion_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/assertions/ThrowableAssertion_Test.java
@@ -22,64 +22,68 @@ import org.junit.*;
 @FixMethodOrder(NAME_ASCENDING)
 public class ThrowableAssertion_Test {
 
+	private <V extends Throwable> ThrowableAssertion<V> test(V value) {
+		return assertThrowable(value).silent();
+	}
+
 	@Test
 	public void a01_basic() throws Exception {
 		RuntimeException x1 = new RuntimeException("foo");
 
-		assertThrowable(x1).isType(Exception.class).isType(RuntimeException.class);
-		assertThrown(()->assertThrowable(x1).isType(IOException.class)).is("Exception was not expected type.\n\tExpect=[java.io.IOException]\n\tActual=[java.lang.RuntimeException]");
-		assertThrown(()->assertThrowable(null).isType(IOException.class)).is("Exception was not expected type.\n\tExpect=[java.io.IOException]\n\tActual=[null]");
-		assertThrown(()->assertThrowable(x1).isType(null)).is("Parameter 'type' cannot be null.");
+		test(x1).isType(Exception.class).isType(RuntimeException.class);
+		assertThrown(()->test(x1).isType(IOException.class)).is("Exception was not expected type.\n\tExpect=[java.io.IOException]\n\tActual=[java.lang.RuntimeException]");
+		assertThrown(()->test(null).isType(IOException.class)).is("Exception was not expected type.\n\tExpect=[java.io.IOException]\n\tActual=[null]");
+		assertThrown(()->test(x1).isType(null)).is("Parameter 'type' cannot be null.");
 
-		assertThrowable(x1).contains("foo");
-		assertThrown(()->assertThrowable(x1).contains("bar")).is("Exception message did not contain expected substring.\n\tSubstring=[bar]\n\tText=[foo]");
-		assertThrown(()->assertThrowable(null).contains("foo")).is("Exception was not thrown.");
-		assertThrown(()->assertThrowable(x1).contains((String[])null)).is("Parameter 'substrings' cannot be null.");
-		assertThrowable(x1).contains((String)null);
+		test(x1).contains("foo");
+		assertThrown(()->test(x1).contains("bar")).is("Exception message did not contain expected substring.\n\tSubstring=[bar]\n\tText=[foo]");
+		assertThrown(()->test(null).contains("foo")).is("Exception was not thrown.");
+		assertThrown(()->test(x1).contains((String[])null)).is("Parameter 'substrings' cannot be null.");
+		test(x1).contains((String)null);
 
-		assertThrowable(null).doesNotExist();
-		assertThrown(()->assertThrowable(x1).doesNotExist()).is("Exception was thrown.");
+		test(null).doesNotExist();
+		assertThrown(()->test(x1).doesNotExist()).is("Exception was thrown.");
 
-		assertThrowable(x1).passes(x->x.getMessage().equals("foo"));
-		assertThrown(()->assertThrowable(x1).passes(x->x.getMessage().equals("bar"))).is("Value did not pass predicate test.\n\tValue=[java.lang.RuntimeException: foo]");
+		test(x1).passes(x->x.getMessage().equals("foo"));
+		assertThrown(()->test(x1).passes(x->x.getMessage().equals("bar"))).is("Value did not pass predicate test.\n\tValue=[java.lang.RuntimeException: foo]");
 
-		assertThrowable(x1).passes(x->x.getMessage().equals("foo"));
-		assertThrown(()->assertThrowable(x1).passes(x->x.getMessage().equals("bar"))).is("Value did not pass predicate test.\n\tValue=[java.lang.RuntimeException: foo]");
+		test(x1).passes(x->x.getMessage().equals("foo"));
+		assertThrown(()->test(x1).passes(x->x.getMessage().equals("bar"))).is("Value did not pass predicate test.\n\tValue=[java.lang.RuntimeException: foo]");
 
-		assertThrowable(x1).passes(x->x.getMessage().equals("foo"));
-		assertThrown(()->assertThrowable(x1).passes(x->x.getMessage().equals("bar"))).is("Value did not pass predicate test.\n\tValue=[java.lang.RuntimeException: foo]");
+		test(x1).passes(x->x.getMessage().equals("foo"));
+		assertThrown(()->test(x1).passes(x->x.getMessage().equals("bar"))).is("Value did not pass predicate test.\n\tValue=[java.lang.RuntimeException: foo]");
 
-		assertThrowable(x1).passes(x->x.getMessage().equals("foo"));
-		assertThrown(()->assertThrowable(x1).passes(x->x.getMessage().equals("bar"))).is("Value did not pass predicate test.\n\tValue=[java.lang.RuntimeException: foo]");
+		test(x1).passes(x->x.getMessage().equals("foo"));
+		assertThrown(()->test(x1).passes(x->x.getMessage().equals("bar"))).is("Value did not pass predicate test.\n\tValue=[java.lang.RuntimeException: foo]");
 
-		assertThrowable(x1).message().is("foo");
-		assertThrowable(new RuntimeException()).message().doesNotExist();
-		assertThrowable(null).message().doesNotExist();
+		test(x1).message().is("foo");
+		test(new RuntimeException()).message().doesNotExist();
+		test(null).message().doesNotExist();
 
-		assertThrowable(x1).localizedMessage().is("foo");
-		assertThrowable(new RuntimeException()).localizedMessage().doesNotExist();
-		assertThrowable(null).localizedMessage().doesNotExist();
+		test(x1).localizedMessage().is("foo");
+		test(new RuntimeException()).localizedMessage().doesNotExist();
+		test(null).localizedMessage().doesNotExist();
 
-		assertThrowable(x1).stackTrace().contains("RuntimeException");
-		assertThrowable(new RuntimeException()).stackTrace().contains("RuntimeException");
-		assertThrowable(null).stackTrace().doesNotExist();
+		test(x1).stackTrace().contains("RuntimeException");
+		test(new RuntimeException()).stackTrace().contains("RuntimeException");
+		test(null).stackTrace().doesNotExist();
 
-		assertThrowable(new RuntimeException(x1)).causedBy().message().is("foo");
-		assertThrowable(new RuntimeException()).message().doesNotExist();
-		assertThrowable(null).causedBy().message().doesNotExist();
+		test(new RuntimeException(x1)).causedBy().message().is("foo");
+		test(new RuntimeException()).message().doesNotExist();
+		test(null).causedBy().message().doesNotExist();
 
-		assertThrowable(new RuntimeException(new IOException())).find(RuntimeException.class).exists();
-		assertThrowable(new RuntimeException(new IOException())).find(IOException.class).exists();
-		assertThrowable(new RuntimeException(new IOException())).find(Exception.class).exists();
-		assertThrowable(new RuntimeException(new IOException())).find(FileNotFoundException.class).doesNotExist();
-		assertThrowable(new RuntimeException()).find(RuntimeException.class).exists();
-		assertThrowable(new RuntimeException()).find(IOException.class).doesNotExist();
-		assertThrowable(null).find(RuntimeException.class).doesNotExist();
+		test(new RuntimeException(new IOException())).find(RuntimeException.class).exists();
+		test(new RuntimeException(new IOException())).find(IOException.class).exists();
+		test(new RuntimeException(new IOException())).find(Exception.class).exists();
+		test(new RuntimeException(new IOException())).find(FileNotFoundException.class).doesNotExist();
+		test(new RuntimeException()).find(RuntimeException.class).exists();
+		test(new RuntimeException()).find(IOException.class).doesNotExist();
+		test(null).find(RuntimeException.class).doesNotExist();
 	}
 
 	@Test
 	public void a02_other() throws Exception {
-		assertThrown(()->ThrowableAssertion.create(null).msg("Foo {0}", 1).exists()).is("Foo 1");
-		ThrowableAssertion.create(null).stdout().silent();
+		assertThrown(()->test(null).msg("Foo {0}", 1).exists()).is("Foo 1");
+		test(null).stdout();
 	}
 }
diff --git a/juneau-utest/src/test/java/org/apache/juneau/assertions/Verify_Test.java b/juneau-utest/src/test/java/org/apache/juneau/assertions/Verify_Test.java
index 8b43a40..f280fc2 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/assertions/Verify_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/assertions/Verify_Test.java
@@ -24,36 +24,40 @@ import org.junit.*;
 @FixMethodOrder(NAME_ASCENDING)
 public class Verify_Test {
 
+	private StringAssertion test(Object value) {
+		return assertString(value).silent();
+	}
+
 	@Test
 	public void a01_basic() {
 		Verify x1 = verify("foo"), x2 = verify(null), x3 = verify(new Date(0));
 
-		assertString(x1.is("foo")).doesNotExist();
-		assertString(x1.is("bar")).is("Expected [bar] but was [foo].");
-		assertString(x1.is(null)).is("Expected [null] but was [foo].");
-		assertString(x2.is(null)).doesNotExist();
-		assertString(x2.is("foo")).is("Expected [foo] but was [null].");
-		assertString(x3.is(new Date(0))).doesNotExist();
-
-		assertString(x1.isType(String.class)).doesNotExist();
-		assertString(x1.isType(Integer.class)).is("Expected type [java.lang.Integer] but was [java.lang.String].");
-		assertString(x2.isType(null)).doesNotExist();
-		assertString(x2.isType(String.class)).is("Expected type [java.lang.String] but was [null].");
-		assertString(x1.isType(null)).is("Expected type [null] but was [java.lang.String].");
-
-
-		assertString(verify(true).isTrue()).doesNotExist();
-		assertString(verify(false).isFalse()).doesNotExist();
-		assertString(verify(null).isTrue()).is("Expected [true] but was [null].");
-		assertString(verify(null).isFalse()).is("Expected [false] but was [null].");
-		assertString(verify(Boolean.TRUE).isTrue()).doesNotExist();
-		assertString(verify(Boolean.FALSE).isFalse()).doesNotExist();
-		assertString(x1.is("foo")).doesNotExist();
-
-		assertString(verify("foo").msg("bar{0}", "baz").is("foo")).doesNotExist();
-		assertString(verify("foo").msg("bar{0}", "baz").is("bar")).is("barbaz");
-		assertString(verify("foo").msg("bar{0}", "baz").isType(Integer.class)).is("barbaz");
-		assertString(verify(null).msg("bar{0}", "baz").is("bar")).is("barbaz");
-		assertString(verify("foo").msg("bar{0}", "baz").is(null)).is("barbaz");
+		test(x1.is("foo")).doesNotExist();
+		test(x1.is("bar")).is("Expected [bar] but was [foo].");
+		test(x1.is(null)).is("Expected [null] but was [foo].");
+		test(x2.is(null)).doesNotExist();
+		test(x2.is("foo")).is("Expected [foo] but was [null].");
+		test(x3.is(new Date(0))).doesNotExist();
+
+		test(x1.isType(String.class)).doesNotExist();
+		test(x1.isType(Integer.class)).is("Expected type [java.lang.Integer] but was [java.lang.String].");
+		test(x2.isType(null)).doesNotExist();
+		test(x2.isType(String.class)).is("Expected type [java.lang.String] but was [null].");
+		test(x1.isType(null)).is("Expected type [null] but was [java.lang.String].");
+
+
+		test(verify(true).isTrue()).doesNotExist();
+		test(verify(false).isFalse()).doesNotExist();
+		test(verify(null).isTrue()).is("Expected [true] but was [null].");
+		test(verify(null).isFalse()).is("Expected [false] but was [null].");
+		test(verify(Boolean.TRUE).isTrue()).doesNotExist();
+		test(verify(Boolean.FALSE).isFalse()).doesNotExist();
+		test(x1.is("foo")).doesNotExist();
+
+		test(verify("foo").msg("bar{0}", "baz").is("foo")).doesNotExist();
+		test(verify("foo").msg("bar{0}", "baz").is("bar")).is("barbaz");
+		test(verify("foo").msg("bar{0}", "baz").isType(Integer.class)).is("barbaz");
+		test(verify(null).msg("bar{0}", "baz").is("bar")).is("barbaz");
+		test(verify("foo").msg("bar{0}", "baz").is(null)).is("barbaz");
 	}
 }
diff --git a/juneau-utest/src/test/java/org/apache/juneau/assertions/ZonedDateTimeAssertion_Test.java b/juneau-utest/src/test/java/org/apache/juneau/assertions/ZonedDateTimeAssertion_Test.java
index 8d04bd4..0dacc5e 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/assertions/ZonedDateTimeAssertion_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/assertions/ZonedDateTimeAssertion_Test.java
@@ -18,65 +18,74 @@ import static java.util.Optional.*;
 
 import java.time.*;
 import java.time.temporal.*;
+import java.util.*;
 
 import org.junit.*;
 
 @FixMethodOrder(NAME_ASCENDING)
 public class ZonedDateTimeAssertion_Test {
 
+	private ZonedDateTimeAssertion test(ZonedDateTime value) {
+		return assertZonedDateTime(value).silent();
+	}
+
+	private ZonedDateTimeAssertion test(Optional<ZonedDateTime> value) {
+		return assertZonedDateTime(value).silent();
+	}
+
 	@Test
 	public void a01_basic() throws Exception {
 		ZonedDateTime x1 = ZonedDateTime.parse("1950-01-01T12:34:56Z"), x2 = ZonedDateTime.parse("2050-01-01T12:34:56Z");
 		ZonedDateTime now = ZonedDateTime.now();
 
-		assertThrown(()->assertZonedDateTime((ZonedDateTime)null).exists()).is("Value was null.");
-		assertZonedDateTime(x1).exists();
-		assertThrown(()->assertZonedDateTime(empty()).exists()).is("Value was null.");
-		assertZonedDateTime(x1).exists();
-
-		assertZonedDateTime(empty()).doesNotExist();
-		assertThrown(()->assertZonedDateTime(x1).doesNotExist()).is("Value was not null.");
-
-		assertZonedDateTime(empty()).isEqual(null);
-		assertZonedDateTime(x1).isEqual(x1);
-		assertZonedDateTime(of(x1)).isEqual(x1);
-		assertZonedDateTime(x1).isEqual(x1, ChronoUnit.DAYS);
-		assertThrown(()->assertZonedDateTime(x2).isEqual(x1, ChronoUnit.DAYS)).contains("Unexpected value.");
-
-		assertZonedDateTime(empty()).isEqual(null);
-		assertZonedDateTime(x1).isEqual(x1);
-		assertZonedDateTime(x1).isEqual(x1, ChronoUnit.DAYS);
-		assertThrown(()->assertZonedDateTime(x2).isEqual(x1, ChronoUnit.DAYS)).contains("Unexpected value.");
-
-		assertThrown(()->assertZonedDateTime(empty()).isBefore(x1)).is("Value was null.");
-		assertThrown(()->assertZonedDateTime(x1).isBefore(null)).is("Parameter 'value' cannot be null.");
-		assertZonedDateTime(x1).isBefore(x2);
-		assertThrown(()->assertZonedDateTime(x2).isBefore(x1)).contains("Value was not before expected.");
-
-		assertThrown(()->assertZonedDateTime(empty()).isAfter(x1)).is("Value was null.");
-		assertThrown(()->assertZonedDateTime(x1).isAfter(null)).is("Parameter 'value' cannot be null.");
-		assertZonedDateTime(x2).isAfter(x1);
-		assertThrown(()->assertZonedDateTime(x1).isAfter(x2)).contains("Value was not after expected.");
-
-		assertThrown(()->assertZonedDateTime(empty()).isBeforeNow()).is("Value was null.");
-		assertZonedDateTime(x1).isBeforeNow();
-		assertThrown(()->assertZonedDateTime(x2).isBeforeNow()).contains("Value was not before expected.");
-
-		assertThrown(()->assertZonedDateTime(empty()).isAfterNow()).is("Value was null.");
-		assertZonedDateTime(x2).isAfterNow();
-		assertThrown(()->assertZonedDateTime(x1).isAfterNow()).contains("Value was not after expected.");
-
-		assertThrown(()->assertZonedDateTime(empty()).isBetween(x1,x2)).is("Value was null.");
-		assertThrown(()->assertZonedDateTime(now).isBetween(null,x2)).is("Parameter 'lower' cannot be null.");
-		assertThrown(()->assertZonedDateTime(now).isBetween(x1,null)).is("Parameter 'upper' cannot be null.");
-		assertZonedDateTime(now).isBetween(x1, x2);
-		assertThrown(()->assertZonedDateTime(x1).isBetween(now,x2)).contains("Value was not after expected.");
-		assertThrown(()->assertZonedDateTime(x2).isBetween(x1,now)).contains("Value was not before expected.");
+		assertThrown(()->test((ZonedDateTime)null).exists()).is("Value was null.");
+		test(x1).exists();
+		assertThrown(()->test(empty()).exists()).is("Value was null.");
+		test(x1).exists();
+
+		test(empty()).doesNotExist();
+		assertThrown(()->test(x1).doesNotExist()).is("Value was not null.");
+
+		test(empty()).isEqual(null);
+		test(x1).isEqual(x1);
+		test(of(x1)).isEqual(x1);
+		test(x1).isEqual(x1, ChronoUnit.DAYS);
+		assertThrown(()->test(x2).isEqual(x1, ChronoUnit.DAYS)).contains("Unexpected value.");
+
+		test(empty()).isEqual(null);
+		test(x1).isEqual(x1);
+		test(x1).isEqual(x1, ChronoUnit.DAYS);
+		assertThrown(()->test(x2).isEqual(x1, ChronoUnit.DAYS)).contains("Unexpected value.");
+
+		assertThrown(()->test(empty()).isBefore(x1)).is("Value was null.");
+		assertThrown(()->test(x1).isBefore(null)).is("Parameter 'value' cannot be null.");
+		test(x1).isBefore(x2);
+		assertThrown(()->test(x2).isBefore(x1)).contains("Value was not before expected.");
+
+		assertThrown(()->test(empty()).isAfter(x1)).is("Value was null.");
+		assertThrown(()->test(x1).isAfter(null)).is("Parameter 'value' cannot be null.");
+		test(x2).isAfter(x1);
+		assertThrown(()->test(x1).isAfter(x2)).contains("Value was not after expected.");
+
+		assertThrown(()->test(empty()).isBeforeNow()).is("Value was null.");
+		test(x1).isBeforeNow();
+		assertThrown(()->test(x2).isBeforeNow()).contains("Value was not before expected.");
+
+		assertThrown(()->test(empty()).isAfterNow()).is("Value was null.");
+		test(x2).isAfterNow();
+		assertThrown(()->test(x1).isAfterNow()).contains("Value was not after expected.");
+
+		assertThrown(()->test(empty()).isBetween(x1,x2)).is("Value was null.");
+		assertThrown(()->test(now).isBetween(null,x2)).is("Parameter 'lower' cannot be null.");
+		assertThrown(()->test(now).isBetween(x1,null)).is("Parameter 'upper' cannot be null.");
+		test(now).isBetween(x1, x2);
+		assertThrown(()->test(x1).isBetween(now,x2)).contains("Value was not after expected.");
+		assertThrown(()->test(x2).isBetween(x1,now)).contains("Value was not before expected.");
 	}
 
 	@Test
 	public void a02_other() throws Exception {
-		assertThrown(()->ZonedDateTimeAssertion.create(null).msg("Foo {0}", 1).exists()).is("Foo 1");
-		ZonedDateTimeAssertion.create(null).stdout().silent();
+		assertThrown(()->test((ZonedDateTime)null).msg("Foo {0}", 1).exists()).is("Foo 1");
+		test((ZonedDateTime)null).stdout();
 	}
 }
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/exception/BadRequest_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/exception/BadRequest_Test.java
index b987d5a..683e6e2 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/exception/BadRequest_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/exception/BadRequest_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.exception;
 
 import static org.junit.runners.MethodSorters.*;
 import static org.apache.juneau.http.exception.BadRequest.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
@@ -43,7 +44,7 @@ public class BadRequest_Test {
 		}
 		@RestGet
 		public void f5() throws BadRequest {
-			throw new BadRequest().header("Foo", "bar");
+			throw badRequest().header("Foo", "bar").build();
 		}
 		@RestGet
 		public void f6() throws BadRequest {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/exception/Conflict_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/exception/Conflict_Test.java
index 199d758..559789c 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/exception/Conflict_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/exception/Conflict_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.exception;
 
 import static org.junit.runners.MethodSorters.*;
 import static org.apache.juneau.http.exception.Conflict.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
@@ -43,7 +44,7 @@ public class Conflict_Test {
 		}
 		@RestGet
 		public void f5() throws Conflict {
-			throw new Conflict().header("Foo", "bar");
+			throw conflict().header("Foo", "bar").build();
 		}
 		@RestGet
 		public void f6() throws Conflict {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/exception/ExpectationFailed_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/exception/ExpectationFailed_Test.java
index e86862a..7c54885 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/exception/ExpectationFailed_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/exception/ExpectationFailed_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.exception;
 
 import static org.junit.runners.MethodSorters.*;
 import static org.apache.juneau.http.exception.ExpectationFailed.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
@@ -43,7 +44,7 @@ public class ExpectationFailed_Test {
 		}
 		@RestGet
 		public void f5() throws ExpectationFailed {
-			throw new ExpectationFailed().header("Foo", "bar");
+			throw expectationFailed().header("Foo", "bar").build();
 		}
 		@RestGet
 		public void f6() throws ExpectationFailed {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/exception/FailedDependency_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/exception/FailedDependency_Test.java
index 3f78ae3..4f16f8d 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/exception/FailedDependency_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/exception/FailedDependency_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.exception;
 
 import static org.junit.runners.MethodSorters.*;
 import static org.apache.juneau.http.exception.FailedDependency.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
@@ -43,7 +44,7 @@ public class FailedDependency_Test {
 		}
 		@RestGet
 		public void f5() throws FailedDependency {
-			throw new FailedDependency().header("Foo", "bar");
+			throw failedDependency().header("Foo", "bar").build();
 		}
 		@RestGet
 		public void f6() throws FailedDependency {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/exception/Forbidden_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/exception/Forbidden_Test.java
index 31d9fba..9d27262 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/exception/Forbidden_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/exception/Forbidden_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.exception;
 
 import static org.junit.runners.MethodSorters.*;
 import static org.apache.juneau.http.exception.Forbidden.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
@@ -43,7 +44,7 @@ public class Forbidden_Test {
 		}
 		@RestGet
 		public void f5() throws Forbidden {
-			throw new Forbidden().header("Foo", "bar");
+			throw forbidden().header("Foo", "bar").build();
 		}
 		@RestGet
 		public void f6() throws Forbidden {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/exception/Gone_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/exception/Gone_Test.java
index 0e3dce6..53070dc 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/exception/Gone_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/exception/Gone_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.exception;
 
 import static org.junit.runners.MethodSorters.*;
 import static org.apache.juneau.http.exception.Gone.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
@@ -43,7 +44,7 @@ public class Gone_Test {
 		}
 		@RestGet
 		public void f5() throws Gone {
-			throw new Gone().header("Foo", "bar");
+			throw gone().header("Foo", "bar").build();
 		}
 		@RestGet
 		public void f6() throws Gone {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/exception/HttpException_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/exception/HttpException_Test.java
index 9771f25..067d5c1 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/exception/HttpException_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/exception/HttpException_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.exception;
 
 import static org.apache.juneau.assertions.Assertions.*;
 import static org.junit.runners.MethodSorters.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import java.lang.reflect.*;
 
@@ -29,15 +30,15 @@ public class HttpException_Test {
 	public static class A {
 		@RestGet
 		public void f1() throws HttpException {
-			throw new HttpException(new RuntimeException("foo"), 225, "bar {0}", "baz");
+			throw new HttpException(225, new RuntimeException("foo"), "bar {0}", "baz");
 		}
 		@RestGet
 		public void f2() throws HttpException {
-			throw new HttpException("foo").status(225);
+			throw new HttpException(225, "foo");
 		}
 		@RestGet
 		public void f3() throws HttpException {
-			throw new HttpException(new RuntimeException("baz"), 225);
+			throw new HttpException(225, new RuntimeException("baz"));
 		}
 		@RestGet
 		public void f4() throws HttpException {
@@ -45,7 +46,7 @@ public class HttpException_Test {
 		}
 		@RestGet
 		public void f5() throws HttpException {
-			throw new HttpException(null).status(225).header("Foo", "bar");
+			throw httpException().statusCode(225).header("Foo", "bar").build();
 		}
 	}
 
@@ -73,37 +74,37 @@ public class HttpException_Test {
 
 	@Test
 	public void a02_getRootCause() throws Exception {
-		HttpException x = new HttpException(null);
+		HttpException x = new HttpException(100, null);
 		assertObject(x.getRootCause()).doesNotExist();
 
-		x = new HttpException(new HttpException(100,"foo"),100);
+		x = new HttpException(100, new HttpException(100,"foo"));
 		assertObject(x.getRootCause()).doesNotExist();
 
-		x = new HttpException(new RuntimeException("foo"),100);
+		x = new HttpException(100, new RuntimeException("foo"));
 		assertObject(x.getRootCause()).isType(RuntimeException.class);
 
-		x = new HttpException(new HttpException(new RuntimeException("foo"),100),100);
+		x = new HttpException(100, new HttpException(100, new RuntimeException("foo")));
 		assertObject(x.getRootCause()).isType(RuntimeException.class);
 
-		x = new HttpException(new InvocationTargetException(new RuntimeException("foo")),100);
+		x = new HttpException(100, new InvocationTargetException(new RuntimeException("foo")));
 		assertObject(x.getRootCause()).isType(RuntimeException.class);
 	}
 
 	@Test
 	public void a03_getFullStackMessage() throws Exception {
-		HttpException x = new HttpException(null);
-		assertString(x.getFullStackMessage(false)).is("");
-		assertString(x.getFullStackMessage(true)).is("");
+		HttpException x = new HttpException(100, null);
+		assertString(x.getFullStackMessage(false)).is("Continue");
+		assertString(x.getFullStackMessage(true)).is("Continue");
 
-		x = new HttpException("foo<bar>&baz");
+		x = new HttpException(100, "foo<bar>&baz");
 		assertString(x.getFullStackMessage(false)).is("foo<bar>&baz");
 		assertString(x.getFullStackMessage(true)).is("foo bar  baz");
 
-		x = new HttpException(new RuntimeException("foo<bar>&qux"), 100, "foo{0}","<bar>&baz");
+		x = new HttpException(100, new RuntimeException("foo<bar>&qux"), "foo{0}","<bar>&baz");
 		assertString(x.getFullStackMessage(false)).is("foo<bar>&baz\nCaused by (RuntimeException): foo<bar>&qux");
 		assertString(x.getFullStackMessage(true)).is("foo bar  baz\nCaused by (RuntimeException): foo bar  qux");
 
-		x = new HttpException(new RuntimeException(), 100, "foo{0}","<bar>&baz");
+		x = new HttpException(100, new RuntimeException(), "foo{0}","<bar>&baz");
 		assertString(x.getFullStackMessage(false)).is("foo<bar>&baz\nCaused by (RuntimeException)");
 		assertString(x.getFullStackMessage(true)).is("foo bar  baz\nCaused by (RuntimeException)");
 
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/exception/HttpVersionNotSupported_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/exception/HttpVersionNotSupported_Test.java
index cb01ffd..221b557 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/exception/HttpVersionNotSupported_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/exception/HttpVersionNotSupported_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.exception;
 
 import static org.junit.runners.MethodSorters.*;
 import static org.apache.juneau.http.exception.HttpVersionNotSupported.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
@@ -43,7 +44,7 @@ public class HttpVersionNotSupported_Test {
 		}
 		@RestGet
 		public void f5() throws HttpVersionNotSupported {
-			throw new HttpVersionNotSupported().header("Foo", "bar");
+			throw httpVersionNotSupported().header("Foo", "bar").build();
 		}
 		@RestGet
 		public void f6() throws HttpVersionNotSupported {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/exception/InsufficentStorage_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/exception/InsufficentStorage_Test.java
index 31dc7a4..423b312 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/exception/InsufficentStorage_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/exception/InsufficentStorage_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.exception;
 
 import static org.junit.runners.MethodSorters.*;
 import static org.apache.juneau.http.exception.InsufficientStorage.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
@@ -43,7 +44,7 @@ public class InsufficentStorage_Test {
 		}
 		@RestGet
 		public void f5() throws InsufficientStorage {
-			throw new InsufficientStorage().header("Foo", "bar");
+			throw insufficientStorage().header("Foo", "bar").build();
 		}
 		@RestGet
 		public void f6() throws InsufficientStorage {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/exception/InternalServerError_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/exception/InternalServerError_Test.java
index adc31f1..4dc9b16 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/exception/InternalServerError_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/exception/InternalServerError_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.exception;
 
 import static org.junit.runners.MethodSorters.*;
 import static org.apache.juneau.http.exception.InternalServerError.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
@@ -43,7 +44,7 @@ public class InternalServerError_Test {
 		}
 		@RestGet
 		public void f5() throws InternalServerError {
-			throw new InternalServerError().header("Foo", "bar");
+			throw internalServerError().header("Foo", "bar").build();
 		}
 		@RestGet
 		public void f6() throws InternalServerError {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/exception/LengthRequired_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/exception/LengthRequired_Test.java
index ad3b876..8be4c90 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/exception/LengthRequired_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/exception/LengthRequired_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.exception;
 
 import static org.junit.runners.MethodSorters.*;
 import static org.apache.juneau.http.exception.LengthRequired.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
@@ -43,7 +44,7 @@ public class LengthRequired_Test {
 		}
 		@RestGet
 		public void f5() throws LengthRequired {
-			throw new LengthRequired().header("Foo", "bar");
+			throw lengthRequired().header("Foo", "bar").build();
 		}
 		@RestGet
 		public void f6() throws LengthRequired {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/exception/Locked_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/exception/Locked_Test.java
index 624014f..3a76540 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/exception/Locked_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/exception/Locked_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.exception;
 
 import static org.junit.runners.MethodSorters.*;
 import static org.apache.juneau.http.exception.Locked.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
@@ -43,7 +44,7 @@ public class Locked_Test {
 		}
 		@RestGet
 		public void f5() throws Locked {
-			throw new Locked().header("Foo", "bar");
+			throw locked().header("Foo", "bar").build();
 		}
 		@RestGet
 		public void f6() throws Locked {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/exception/LoopDetected_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/exception/LoopDetected_Test.java
index ed5560f..d0a7549 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/exception/LoopDetected_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/exception/LoopDetected_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.exception;
 
 import static org.junit.runners.MethodSorters.*;
 import static org.apache.juneau.http.exception.LoopDetected.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
@@ -43,7 +44,7 @@ public class LoopDetected_Test {
 		}
 		@RestGet
 		public void f5() throws LoopDetected {
-			throw new LoopDetected().header("Foo", "bar");
+			throw loopDetected().header("Foo", "bar").build();
 		}
 		@RestGet
 		public void f6() throws LoopDetected {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/exception/MethodNotAllowed_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/exception/MethodNotAllowed_Test.java
index bdc03b1..40e83dd 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/exception/MethodNotAllowed_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/exception/MethodNotAllowed_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.exception;
 
 import static org.junit.runners.MethodSorters.*;
 import static org.apache.juneau.http.exception.MethodNotAllowed.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
@@ -43,7 +44,7 @@ public class MethodNotAllowed_Test {
 		}
 		@RestGet
 		public void f5() throws MethodNotAllowed {
-			throw new MethodNotAllowed().header("Foo", "bar");
+			throw methodNotAllowed().header("Foo", "bar").build();
 		}
 		@RestGet
 		public void f6() throws MethodNotAllowed {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/exception/MisdirectedRequest_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/exception/MisdirectedRequest_Test.java
index 5255a21..37b95a0 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/exception/MisdirectedRequest_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/exception/MisdirectedRequest_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.exception;
 
 import static org.junit.runners.MethodSorters.*;
 import static org.apache.juneau.http.exception.MisdirectedRequest.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
@@ -43,7 +44,7 @@ public class MisdirectedRequest_Test {
 		}
 		@RestGet
 		public void f5() throws MisdirectedRequest {
-			throw new MisdirectedRequest().header("Foo", "bar");
+			throw misdirectedRequest().header("Foo", "bar").build();
 		}
 		@RestGet
 		public void f6() throws MisdirectedRequest {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/exception/NetworkAuthenticationRequired_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/exception/NetworkAuthenticationRequired_Test.java
index 1383fb8..c591513 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/exception/NetworkAuthenticationRequired_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/exception/NetworkAuthenticationRequired_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.exception;
 
 import static org.junit.runners.MethodSorters.*;
 import static org.apache.juneau.http.exception.NetworkAuthenticationRequired.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
@@ -43,7 +44,7 @@ public class NetworkAuthenticationRequired_Test {
 		}
 		@RestGet
 		public void f5() throws NetworkAuthenticationRequired {
-			throw new NetworkAuthenticationRequired().header("Foo", "bar");
+			throw networkAuthenticationRequired().header("Foo", "bar").build();
 		}
 		@RestGet
 		public void f6() throws NetworkAuthenticationRequired {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/exception/NotAcceptable_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/exception/NotAcceptable_Test.java
index dbb6f2a..8f49725 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/exception/NotAcceptable_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/exception/NotAcceptable_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.exception;
 
 import static org.junit.runners.MethodSorters.*;
 import static org.apache.juneau.http.exception.NotAcceptable.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
@@ -43,7 +44,7 @@ public class NotAcceptable_Test {
 		}
 		@RestGet
 		public void f5() throws NotAcceptable {
-			throw new NotAcceptable().header("Foo", "bar");
+			throw notAcceptable().header("Foo", "bar").build();
 		}
 		@RestGet
 		public void f6() throws NotAcceptable {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/exception/NotExtended_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/exception/NotExtended_Test.java
index 62e27e1..ee6cb03 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/exception/NotExtended_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/exception/NotExtended_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.exception;
 
 import static org.junit.runners.MethodSorters.*;
 import static org.apache.juneau.http.exception.NotExtended.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
@@ -43,7 +44,7 @@ public class NotExtended_Test {
 		}
 		@RestGet
 		public void f5() throws NotExtended {
-			throw new NotExtended().header("Foo", "bar");
+			throw notExtended().header("Foo", "bar").build();
 		}
 		@RestGet
 		public void f6() throws NotExtended {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/exception/NotFound_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/exception/NotFound_Test.java
index 94693e6..4dd7b12 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/exception/NotFound_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/exception/NotFound_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.exception;
 
 import static org.junit.runners.MethodSorters.*;
 import static org.apache.juneau.http.exception.NotFound.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
@@ -43,7 +44,7 @@ public class NotFound_Test {
 		}
 		@RestGet
 		public void f5() throws NotFound {
-			throw new NotFound().header("Foo", "bar");
+			throw notFound().header("Foo", "bar").build();
 		}
 		@RestGet
 		public void f6() throws NotFound {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/exception/NotImplemented_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/exception/NotImplemented_Test.java
index 3816311..65d6d12 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/exception/NotImplemented_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/exception/NotImplemented_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.exception;
 
 import static org.junit.runners.MethodSorters.*;
 import static org.apache.juneau.http.exception.NotImplemented.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
@@ -43,7 +44,7 @@ public class NotImplemented_Test {
 		}
 		@RestGet
 		public void f5() throws NotImplemented {
-			throw new NotImplemented().header("Foo", "bar");
+			throw notImplemented().header("Foo", "bar").build();
 		}
 		@RestGet
 		public void f6() throws NotImplemented {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/exception/PayloadTooLarge_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/exception/PayloadTooLarge_Test.java
index b0097a7..f172ff2 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/exception/PayloadTooLarge_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/exception/PayloadTooLarge_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.exception;
 
 import static org.junit.runners.MethodSorters.*;
 import static org.apache.juneau.http.exception.PayloadTooLarge.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
@@ -43,7 +44,7 @@ public class PayloadTooLarge_Test {
 		}
 		@RestGet
 		public void f5() throws PayloadTooLarge {
-			throw new PayloadTooLarge().header("Foo", "bar");
+			throw payloadTooLarge().header("Foo", "bar").build();
 		}
 		@RestGet
 		public void f6() throws PayloadTooLarge {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/exception/PreconditionFailed_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/exception/PreconditionFailed_Test.java
index 52a93b3..21c37d8 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/exception/PreconditionFailed_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/exception/PreconditionFailed_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.exception;
 
 import static org.junit.runners.MethodSorters.*;
 import static org.apache.juneau.http.exception.PreconditionFailed.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
@@ -43,7 +44,7 @@ public class PreconditionFailed_Test {
 		}
 		@RestGet
 		public void f5() throws PreconditionFailed {
-			throw new PreconditionFailed().header("Foo", "bar");
+			throw preconditionFailed().header("Foo", "bar").build();
 		}
 		@RestGet
 		public void f6() throws PreconditionFailed {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/exception/PreconditionRequired_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/exception/PreconditionRequired_Test.java
index 77d1878..7e8ff5a 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/exception/PreconditionRequired_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/exception/PreconditionRequired_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.exception;
 
 import static org.junit.runners.MethodSorters.*;
 import static org.apache.juneau.http.exception.PreconditionRequired.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
@@ -43,7 +44,7 @@ public class PreconditionRequired_Test {
 		}
 		@RestGet
 		public void f5() throws PreconditionRequired {
-			throw new PreconditionRequired().header("Foo", "bar");
+			throw preconditionRequired().header("Foo", "bar").build();
 		}
 		@RestGet
 		public void f6() throws PreconditionRequired {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/exception/RangeNotSatisfiable_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/exception/RangeNotSatisfiable_Test.java
index 710c2fa..8f9b060 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/exception/RangeNotSatisfiable_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/exception/RangeNotSatisfiable_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.exception;
 
 import static org.junit.runners.MethodSorters.*;
 import static org.apache.juneau.http.exception.RangeNotSatisfiable.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
@@ -43,7 +44,7 @@ public class RangeNotSatisfiable_Test {
 		}
 		@RestGet
 		public void f5() throws RangeNotSatisfiable {
-			throw new RangeNotSatisfiable().header("Foo", "bar");
+			throw rangeNotSatisfiable().header("Foo", "bar").build();
 		}
 		@RestGet
 		public void f6() throws RangeNotSatisfiable {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/exception/RequestHeaderFieldsTooLarge_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/exception/RequestHeaderFieldsTooLarge_Test.java
index 3779f32..21fe6a3 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/exception/RequestHeaderFieldsTooLarge_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/exception/RequestHeaderFieldsTooLarge_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.exception;
 
 import static org.junit.runners.MethodSorters.*;
 import static org.apache.juneau.http.exception.RequestHeaderFieldsTooLarge.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
@@ -43,7 +44,7 @@ public class RequestHeaderFieldsTooLarge_Test {
 		}
 		@RestGet
 		public void f5() throws RequestHeaderFieldsTooLarge {
-			throw new RequestHeaderFieldsTooLarge().header("Foo", "bar");
+			throw requestHeaderFieldsTooLarge().header("Foo", "bar").build();
 		}
 		@RestGet
 		public void f6() throws RequestHeaderFieldsTooLarge {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/exception/ServiceUnavailable_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/exception/ServiceUnavailable_Test.java
index d107d7f..9b7d141 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/exception/ServiceUnavailable_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/exception/ServiceUnavailable_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.exception;
 
 import static org.junit.runners.MethodSorters.*;
 import static org.apache.juneau.http.exception.ServiceUnavailable.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
@@ -43,7 +44,7 @@ public class ServiceUnavailable_Test {
 		}
 		@RestGet
 		public void f5() throws ServiceUnavailable {
-			throw new ServiceUnavailable().header("Foo", "bar");
+			throw serviceUnavailable().header("Foo", "bar").build();
 		}
 		@RestGet
 		public void f6() throws ServiceUnavailable {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/exception/TooManyRequests_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/exception/TooManyRequests_Test.java
index b2a3e8e..b6dcb78 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/exception/TooManyRequests_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/exception/TooManyRequests_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.exception;
 
 import static org.junit.runners.MethodSorters.*;
 import static org.apache.juneau.http.exception.TooManyRequests.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
@@ -43,7 +44,7 @@ public class TooManyRequests_Test {
 		}
 		@RestGet
 		public void f5() throws TooManyRequests {
-			throw new TooManyRequests().header("Foo", "bar");
+			throw tooManyRequests().header("Foo", "bar").build();
 		}
 		@RestGet
 		public void f6() throws TooManyRequests {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/exception/Unauthorized_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/exception/Unauthorized_Test.java
index 54bccad..e34fa6c 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/exception/Unauthorized_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/exception/Unauthorized_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.exception;
 
 import static org.junit.runners.MethodSorters.*;
 import static org.apache.juneau.http.exception.Unauthorized.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
@@ -43,7 +44,7 @@ public class Unauthorized_Test {
 		}
 		@RestGet
 		public void f5() throws Unauthorized {
-			throw new Unauthorized().header("Foo", "bar");
+			throw unauthorized().header("Foo", "bar").build();
 		}
 		@RestGet
 		public void f6() throws Unauthorized {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/exception/UnavailableForLegalReasons_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/exception/UnavailableForLegalReasons_Test.java
index 32e6ea0..e0c341c 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/exception/UnavailableForLegalReasons_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/exception/UnavailableForLegalReasons_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.exception;
 
 import static org.junit.runners.MethodSorters.*;
 import static org.apache.juneau.http.exception.UnavailableForLegalReasons.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
@@ -43,7 +44,7 @@ public class UnavailableForLegalReasons_Test {
 		}
 		@RestGet
 		public void f5() throws UnavailableForLegalReasons {
-			throw new UnavailableForLegalReasons().header("Foo", "bar");
+			throw unavailableForLegalReasons().header("Foo", "bar").build();
 		}
 		@RestGet
 		public void f6() throws UnavailableForLegalReasons {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/exception/UnprocessableEntity_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/exception/UnprocessableEntity_Test.java
index 4625725..f3f6850 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/exception/UnprocessableEntity_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/exception/UnprocessableEntity_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.exception;
 
 import static org.junit.runners.MethodSorters.*;
 import static org.apache.juneau.http.exception.UnprocessableEntity.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
@@ -43,7 +44,7 @@ public class UnprocessableEntity_Test {
 		}
 		@RestGet
 		public void f5() throws UnprocessableEntity {
-			throw new UnprocessableEntity().header("Foo", "bar");
+			throw unprocessableEntity().header("Foo", "bar").build();
 		}
 		@RestGet
 		public void f6() throws UnprocessableEntity {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/exception/UnsupportedMediaType_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/exception/UnsupportedMediaType_Test.java
index 0ab49d2..ed23ddb 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/exception/UnsupportedMediaType_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/exception/UnsupportedMediaType_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.exception;
 
 import static org.junit.runners.MethodSorters.*;
 import static org.apache.juneau.http.exception.UnsupportedMediaType.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
@@ -43,7 +44,7 @@ public class UnsupportedMediaType_Test {
 		}
 		@RestGet
 		public void f5() throws UnsupportedMediaType {
-			throw new UnsupportedMediaType().header("Foo", "bar");
+			throw unsupportedMediaType().header("Foo", "bar").build();
 		}
 		@RestGet
 		public void f6() throws UnsupportedMediaType {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/exception/UpgradeRequired_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/exception/UpgradeRequired_Test.java
index 6942975..cb40f9f 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/exception/UpgradeRequired_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/exception/UpgradeRequired_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.exception;
 
 import static org.junit.runners.MethodSorters.*;
 import static org.apache.juneau.http.exception.UpgradeRequired.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
@@ -43,7 +44,7 @@ public class UpgradeRequired_Test {
 		}
 		@RestGet
 		public void f5() throws UpgradeRequired {
-			throw new UpgradeRequired().header("Foo", "bar");
+			throw upgradeRequired().header("Foo", "bar").build();
 		}
 		@RestGet
 		public void f6() throws UpgradeRequired {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/exception/UriTooLong_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/exception/UriTooLong_Test.java
index 58a6a13..7eb77d9 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/exception/UriTooLong_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/exception/UriTooLong_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.exception;
 
 import static org.junit.runners.MethodSorters.*;
 import static org.apache.juneau.http.exception.UriTooLong.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
@@ -43,7 +44,7 @@ public class UriTooLong_Test {
 		}
 		@RestGet
 		public void f5() throws UriTooLong {
-			throw new UriTooLong().header("Foo", "bar");
+			throw uriTooLong().header("Foo", "bar").build();
 		}
 		@RestGet
 		public void f6() throws UriTooLong {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/exception/VariantAlsoNegotiates_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/exception/VariantAlsoNegotiates_Test.java
index fcdf4b9..5eba302 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/exception/VariantAlsoNegotiates_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/exception/VariantAlsoNegotiates_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.exception;
 
 import static org.junit.runners.MethodSorters.*;
 import static org.apache.juneau.http.exception.VariantAlsoNegotiates.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
@@ -43,7 +44,7 @@ public class VariantAlsoNegotiates_Test {
 		}
 		@RestGet
 		public void f5() throws VariantAlsoNegotiates {
-			throw new VariantAlsoNegotiates().header("Foo", "bar");
+			throw variantAlsoNegotiates().header("Foo", "bar").build();
 		}
 		@RestGet
 		public void f6() throws VariantAlsoNegotiates {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_CommonInterfaces_Test.java b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_CommonInterfaces_Test.java
index 930721e..4f4251d 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_CommonInterfaces_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_CommonInterfaces_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.http.remote;
 
 import static org.apache.juneau.assertions.Assertions.*;
 import static org.apache.juneau.http.response.StandardResponses.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 import static org.junit.Assert.*;
 import static org.junit.runners.MethodSorters.*;
 
@@ -264,135 +265,135 @@ public class Remote_CommonInterfaces_Test {
 	public static class E1 implements E {
 		@Override
 		public void badRequest() throws BadRequest {
-			throw new BadRequest();
+			throw BAD_REQUEST;
 		}
 		@Override
 		public void conflict() throws Conflict {
-			throw new Conflict();
+			throw CONFLICT;
 		}
 		@Override
 		public void expectationFailed() throws ExpectationFailed {
-			throw new ExpectationFailed();
+			throw EXPECTATION_FAILED;
 		}
 		@Override
 		public void failedDependency() throws FailedDependency {
-			throw new FailedDependency();
+			throw FAILED_DEPENDENCY;
 		}
 		@Override
 		public void forbidden() throws Forbidden {
-			throw new Forbidden();
+			throw FORBIDDEN;
 		}
 		@Override
 		public void gone() throws Gone {
-			throw new Gone();
+			throw GONE;
 		}
 		@Override
 		public void httpVersionNotSupported() throws HttpVersionNotSupported {
-			throw new HttpVersionNotSupported();
+			throw HTTP_VERSION_NOT_SUPPORTED;
 		}
 		@Override
 		public void insufficientStorage() throws InsufficientStorage {
-			throw new InsufficientStorage();
+			throw INSUFFICIENT_STORAGE;
 		}
 		@Override
 		public void internalServerError() throws InternalServerError {
-			throw new InternalServerError();
+			throw INTERNAL_SERVER_ERROR;
 		}
 		@Override
 		public void lengthRequired() throws LengthRequired {
-			throw new LengthRequired();
+			throw LENGTH_REQUIRED;
 		}
 		@Override
 		public void locked() throws Locked {
-			throw new Locked();
+			throw LOCKED;
 		}
 		@Override
 		public void loopDetected() throws LoopDetected {
-			throw new LoopDetected();
+			throw LOOP_DETECTED;
 		}
 		@Override
 		public void methodNotAllowed() throws MethodNotAllowed {
-			throw new MethodNotAllowed();
+			throw METHOD_NOT_ALLOWED;
 		}
 		@Override
 		public void misdirectedRequest() throws MisdirectedRequest {
-			throw new MisdirectedRequest();
+			throw MISDIRECTED_REQUEST;
 		}
 		@Override
 		public void networkAuthenticationRequired() throws NetworkAuthenticationRequired {
-			throw new NetworkAuthenticationRequired();
+			throw NETWORK_AUTHENTICATION_REQUIRED;
 		}
 		@Override
 		public void notAcceptable() throws NotAcceptable {
-			throw new NotAcceptable();
+			throw NOT_ACCEPTABLE;
 		}
 		@Override
 		public void notExtended() throws NotExtended {
-			throw new NotExtended();
+			throw NOT_EXTENDED;
 		}
 		@Override
 		public void notFound() throws NotFound {
-			throw new NotFound();
+			throw NOT_FOUND;
 		}
 		@Override
 		public void notImplemented() throws NotImplemented {
-			throw new NotImplemented();
+			throw NOT_IMPLEMENTED;
 		}
 		@Override
 		public void payloadTooLarge() throws PayloadTooLarge {
-			throw new PayloadTooLarge();
+			throw PAYLOAD_TOO_LARGE;
 		}
 		@Override
 		public void preconditionFailed() throws PreconditionFailed {
-			throw new PreconditionFailed();
+			throw PRECONDITION_FAILED;
 		}
 		@Override
 		public void preconditionRequired() throws PreconditionRequired {
-			throw new PreconditionRequired();
+			throw PRECONDITION_REQUIRED;
 		}
 		@Override
 		public void rangeNotSatisfiable() throws RangeNotSatisfiable {
-			throw new RangeNotSatisfiable();
+			throw RANGE_NOT_SATISFIABLE;
 		}
 		@Override
 		public void requestHeaderFieldsTooLarge() throws RequestHeaderFieldsTooLarge {
-			throw new RequestHeaderFieldsTooLarge();
+			throw REQUEST_HEADER_FIELDS_TOO_LARGE;
 		}
 		@Override
 		public void serviceUnavailable() throws ServiceUnavailable {
-			throw new ServiceUnavailable();
+			throw SERVICE_UNAVAILABLE;
 		}
 		@Override
 		public void tooManyRequests() throws TooManyRequests {
-			throw new TooManyRequests();
+			throw TOO_MANY_REQUESTS;
 		}
 		@Override
 		public void unauthorized() throws Unauthorized {
-			throw new Unauthorized();
+			throw UNAUTHORIZED;
 		}
 		@Override
 		public void unavailableForLegalReasons() throws UnavailableForLegalReasons {
-			throw new UnavailableForLegalReasons();
+			throw UNAVAILABLE_FOR_LEGAL_REASONS;
 		}
 		@Override
 		public void unprocessableEntity() throws UnprocessableEntity {
-			throw new UnprocessableEntity();
+			throw UNPROCESSABLE_ENTITIY;
 		}
 		@Override
 		public void unsupportedMediaType() throws UnsupportedMediaType {
-			throw new UnsupportedMediaType();
+			throw UNSUPPORTED_MEDIA_TYPE;
 		}
 		@Override
 		public void upgradeRequired() throws UpgradeRequired {
-			throw new UpgradeRequired();
+			throw UPGRADE_REQUIRED;
 		}
 		@Override
 		public void uriTooLong() throws UriTooLong {
-			throw new UriTooLong();
+			throw URI_TOO_LONG;
 		}
 		@Override
 		public void variantAlsoNegotiates() throws VariantAlsoNegotiates {
-			throw new VariantAlsoNegotiates();
+			throw VARIANT_ALSO_NEGOTIATES;
 		}
 	}
 
diff --git a/juneau-utest/src/test/java/org/apache/juneau/rest/RestOp_Throws_Test.java b/juneau-utest/src/test/java/org/apache/juneau/rest/RestOp_Throws_Test.java
index fe53fb6..7a5e447 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/rest/RestOp_Throws_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/rest/RestOp_Throws_Test.java
@@ -762,7 +762,7 @@ public class RestOp_Throws_Test {
 			.json()
 			.run()
 			.assertCode().is(400)
-			.assertBody().is("'foo bar'");
+			.assertBody().is("foo bar");
 	}
 
 	//-----------------------------------------------------------------------------------------------------------------
diff --git a/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Test.java b/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Test.java
index 855af7f..aee2de0 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Test.java
@@ -16,6 +16,7 @@ import static org.junit.Assert.*;
 import static org.junit.runners.MethodSorters.*;
 import static org.apache.juneau.assertions.Assertions.*;
 import static org.apache.juneau.rest.client.RestClient.*;
+import static org.apache.juneau.http.exception.StandardExceptions.*;
 
 import java.io.*;
 import java.util.concurrent.*;
@@ -34,7 +35,6 @@ import org.apache.http.params.*;
 import org.apache.http.protocol.*;
 import org.apache.juneau.*;
 import org.apache.juneau.collections.*;
-import org.apache.juneau.http.exception.*;
 import org.apache.juneau.http.header.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.parser.*;
@@ -335,7 +335,7 @@ public class RestClient_Test {
 		@RestGet
 		public String echo(@org.apache.juneau.http.annotation.Header("Authorization") String auth, org.apache.juneau.rest.RestResponse res) throws IOException {
 			if (auth == null) {
-				throw new Unauthorized().header("WWW-Authenticate","BASIC realm=\"foo\"");
+				throw unauthorized().header("WWW-Authenticate","BASIC realm=\"foo\"").build();
 			} else {
 				assertEquals("Basic dXNlcjpwdw==",auth);
 				return "OK";