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 2017/06/07 00:27:48 UTC

[5/5] incubator-juneau git commit: Enhancements to HTML Doc rendering.

Enhancements to HTML Doc rendering.

Project: http://git-wip-us.apache.org/repos/asf/incubator-juneau/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-juneau/commit/f4812b7c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-juneau/tree/f4812b7c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-juneau/diff/f4812b7c

Branch: refs/heads/master
Commit: f4812b7ce2d5f6115f62b0045f8f7983f406c597
Parents: 3bdc0d8
Author: JamesBognar <ja...@apache.org>
Authored: Tue Jun 6 20:27:36 2017 -0400
Committer: JamesBognar <ja...@apache.org>
Committed: Tue Jun 6 20:27:36 2017 -0400

----------------------------------------------------------------------
 .../apache/juneau/jena/RdfParserBuilder.java    |   4 +-
 .../juneau/jena/RdfSerializerBuilder.java       |   4 +-
 .../java/org/apache/juneau/jena/package.html    |   4 +-
 .../org/apache/juneau/CoreObjectBuilder.java    |   5 +-
 .../main/java/org/apache/juneau/ObjectMap.java  |   7 +-
 .../java/org/apache/juneau/PropertyStore.java   |  34 ++
 .../org/apache/juneau/csv/CsvParserBuilder.java |   4 +-
 .../apache/juneau/csv/CsvSerializerBuilder.java |   4 +-
 .../apache/juneau/dto/jsonschema/package.html   |   4 +-
 .../juneau/encoders/EncoderGroupBuilder.java    |   2 +-
 .../juneau/html/HtmlBeanPropertyMeta.java       |   3 +-
 .../org/apache/juneau/html/HtmlClassMeta.java   |  12 +
 .../apache/juneau/html/HtmlDocSerializer.java   | 101 +-----
 .../juneau/html/HtmlDocSerializerContext.java   | 289 +++++++++++++--
 .../juneau/html/HtmlDocSerializerSession.java   | 126 +++++--
 .../org/apache/juneau/html/HtmlDocTemplate.java | 164 +++++++++
 .../juneau/html/HtmlDocTemplateBasic.java       | 188 ++++++++++
 .../apache/juneau/html/HtmlParserBuilder.java   |   4 +-
 .../java/org/apache/juneau/html/HtmlRender.java |   2 +-
 .../org/apache/juneau/html/HtmlSerializer.java  |  17 +-
 .../juneau/html/HtmlSerializerBuilder.java      |   4 +-
 .../java/org/apache/juneau/html/HtmlWriter.java |   1 -
 .../org/apache/juneau/html/annotation/Html.java |   2 +-
 .../java/org/apache/juneau/http/MediaType.java  |   7 +-
 .../org/apache/juneau/internal/ClassUtils.java  |  36 +-
 .../org/apache/juneau/internal/ObjectUtils.java |   3 +
 .../org/apache/juneau/jso/JsoParserBuilder.java |   4 +-
 .../apache/juneau/jso/JsoSerializerBuilder.java |   4 +-
 .../apache/juneau/json/JsonParserBuilder.java   |   4 +-
 .../json/JsonSchemaSerializerBuilder.java       |   4 +-
 .../juneau/json/JsonSerializerBuilder.java      |   4 +-
 .../java/org/apache/juneau/json/package.html    |   4 +-
 .../juneau/msgpack/MsgPackParserBuilder.java    |   4 +-
 .../msgpack/MsgPackSerializerBuilder.java       |   4 +-
 .../org/apache/juneau/parser/ParserBuilder.java |   4 +-
 .../juneau/parser/ParserGroupBuilder.java       |   5 +-
 .../plaintext/PlainTextParserBuilder.java       |   4 +-
 .../plaintext/PlainTextSerializerBuilder.java   |   4 +-
 .../juneau/remoteable/RemoteMethodArg.java      |   2 +-
 .../juneau/serializer/SerializerBuilder.java    |   4 +-
 .../serializer/SerializerGroupBuilder.java      |   7 +-
 .../apache/juneau/soap/SoapXmlSerializer.java   |   4 +-
 .../juneau/soap/SoapXmlSerializerBuilder.java   |   4 +-
 .../org/apache/juneau/uon/UonParserBuilder.java |   4 +-
 .../apache/juneau/uon/UonSerializerBuilder.java |   4 +-
 .../java/org/apache/juneau/uon/package.html     |   4 +-
 .../urlencoding/UrlEncodingParserBuilder.java   |   4 +-
 .../UrlEncodingSerializerBuilder.java           |   4 +-
 .../org/apache/juneau/urlencoding/package.html  |   4 +-
 .../org/apache/juneau/xml/XmlParserBuilder.java |   4 +-
 .../juneau/xml/XmlSchemaSerializerBuilder.java  |   4 +-
 .../apache/juneau/xml/XmlSerializerBuilder.java |   4 +-
 .../java/org/apache/juneau/xml/package.html     |   4 +-
 .../main/javadoc/doc-files/NewExamplesPage.png  | Bin 0 -> 426946 bytes
 juneau-core/src/main/javadoc/overview.html      | 221 +++++++++---
 .../juneau/examples/rest/AtomFeedResource.java  |  14 +-
 .../examples/rest/CodeFormatterResource.java    |  57 ++-
 .../juneau/examples/rest/DirectoryResource.java |   4 +-
 .../examples/rest/DockerRegistryResource.java   |   9 +-
 .../juneau/examples/rest/FileSpaceResource.java |   8 +-
 .../examples/rest/HelloWorldResource.java       |  13 +-
 .../examples/rest/JsonSchemaResource.java       |  13 +-
 .../examples/rest/MethodExampleResource.java    |   9 +-
 .../juneau/examples/rest/PhotosResource.java    |  41 ++-
 .../examples/rest/RequestEchoResource.java      |  12 +-
 .../juneau/examples/rest/RootResources.java     |  21 +-
 .../examples/rest/SampleRemoteableServlet.java  |  13 +-
 .../juneau/examples/rest/SqlQueryResource.java  |  15 +-
 .../examples/rest/SystemPropertiesResource.java | 155 ++++----
 .../juneau/examples/rest/TempDirResource.java   |   9 +-
 .../examples/rest/TumblrParserResource.java     |  15 +-
 .../examples/rest/UrlEncodedFormResource.java   |   9 +-
 .../rest/addressbook/AddressBookResource.java   |  49 ++-
 .../examples/rest/CodeFormatterResource.html    |  68 ----
 .../juneau/examples/rest/RootResourcesTest.java |  14 +-
 .../apache/juneau/microservice/Resource.java    |   4 +-
 .../juneau/microservice/ResourceGroup.java      |   4 +-
 .../juneau/microservice/ResourceJena.java       |   4 +-
 .../microservice/resources/ConfigResource.java  |  60 ++--
 .../resources/DirectoryResource.java            |   4 +-
 .../microservice/resources/LogsResource.java    |  47 ++-
 .../org/apache/juneau/rest/client/RestCall.java |   5 +-
 .../juneau/rest/client/RestClientBuilder.java   |   8 +-
 .../org/apache/juneau/rest/client/package.html  |   2 +-
 .../rest/test/HtmlPropertiesResource.java       | 103 ++++--
 .../apache/juneau/rest/test/NlsResource.java    |  76 ++--
 .../juneau/rest/test/HtmlPropertiesTest.java    |  24 --
 .../apache/juneau/rest/test/RestTestcase.java   |   2 +-
 .../java/org/apache/juneau/rest/CallMethod.java | 111 ++++--
 .../java/org/apache/juneau/rest/RestConfig.java | 352 ++++++++++++++++--
 .../org/apache/juneau/rest/RestContext.java     | 200 +++++++++--
 .../apache/juneau/rest/RestInfoProvider.java    |  37 +-
 .../org/apache/juneau/rest/RestRequest.java     |  73 +---
 .../org/apache/juneau/rest/RestResponse.java    | 355 +++++++++++++++++--
 .../apache/juneau/rest/RestServletDefault.java  |  11 +-
 .../apache/juneau/rest/annotation/HtmlDoc.java  | 339 ++++++++++++++++++
 .../juneau/rest/annotation/MethodSwagger.java   | 161 +++++++++
 .../juneau/rest/annotation/Parameter.java       |  10 +-
 .../juneau/rest/annotation/ResourceSwagger.java | 177 +++++++++
 .../apache/juneau/rest/annotation/Response.java |  22 +-
 .../juneau/rest/annotation/RestMethod.java      | 159 +--------
 .../juneau/rest/annotation/RestResource.java    | 314 ++++------------
 .../rest/jena/RestServletJenaDefault.java       |   7 +-
 .../java/org/apache/juneau/rest/package.html    |  41 ++-
 .../juneau/rest/response/DefaultHandler.java    |  21 +-
 .../org/apache/juneau/rest/vars/UrlVar.java     |  59 +++
 .../org/apache/juneau/rest/vars/WidgetVar.java  |  63 ++++
 .../rest/widget/ContentTypeLinksWidget.java     |  48 +++
 .../rest/widget/PoweredByJuneauWidget.java      |  35 ++
 .../org/apache/juneau/rest/widget/Widget.java   |  44 +++
 .../org/apache/juneau/rest/styles/devops.css    | 151 ++++----
 111 files changed, 3726 insertions(+), 1317 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserBuilder.java b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserBuilder.java
index f5ddfdc..05687fa 100644
--- a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserBuilder.java
+++ b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserBuilder.java
@@ -680,8 +680,8 @@ public class RdfParserBuilder extends ParserBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public RdfParserBuilder debug(boolean value) {
-		super.debug(value);
+	public RdfParserBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerBuilder.java b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerBuilder.java
index 6bc1a50..f254734 100644
--- a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerBuilder.java
+++ b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerBuilder.java
@@ -855,8 +855,8 @@ public class RdfSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public RdfSerializerBuilder debug(boolean value) {
-		super.debug(value);
+	public RdfSerializerBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core-rdf/src/main/java/org/apache/juneau/jena/package.html
----------------------------------------------------------------------
diff --git a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/package.html b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/package.html
index c3073ec..c81d3fd 100644
--- a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/package.html
+++ b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/package.html
@@ -1064,7 +1064,9 @@
 		messages=<js>"nls/AddressBookResource"</js>,
 		title=<js>"$L{title}"</js>,
 		description=<js>"$L{description}"</js>,
-		pageLinks=<js>"{options:'?method=OPTIONS',doc:'doc'}"</js>,
+		htmldoc=<ja>@HtmlDoc</ja>(
+			links=<js>"{options:'?method=OPTIONS',doc:'doc'}"</js>
+		),
 		properties={
 			<ja>@Property</ja>(name=RdfProperties.<jsf>RDF_rdfxml_tab</jsf>, value=<js>"3"</js>),
 			<ja>@Property</ja>(name=RdfSerializerContext.<jsf>RDF_addRootProperty</jsf>, value=<js>"true"</js>),

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/CoreObjectBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/CoreObjectBuilder.java b/juneau-core/src/main/java/org/apache/juneau/CoreObjectBuilder.java
index f1fb525..5c67e6d 100644
--- a/juneau-core/src/main/java/org/apache/juneau/CoreObjectBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/CoreObjectBuilder.java
@@ -1406,12 +1406,11 @@ public abstract class CoreObjectBuilder {
 	 * 	<li>This is equivalent to calling <code>property(<jsf>BEAN_debug</jsf>, value)</code>.
 	 * </ul>
 	 *
-	 * @param value The new value for this property.
 	 * @return This object (for method chaining).
 	 * @see BeanContext#BEAN_debug
 	 */
-	public CoreObjectBuilder debug(boolean value) {
-		return property(BEAN_debug, value);
+	public CoreObjectBuilder debug() {
+		return property(BEAN_debug, true);
 	}
 
 	/**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/ObjectMap.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/ObjectMap.java b/juneau-core/src/main/java/org/apache/juneau/ObjectMap.java
index 8b057ed..3f6fe6f 100644
--- a/juneau-core/src/main/java/org/apache/juneau/ObjectMap.java
+++ b/juneau-core/src/main/java/org/apache/juneau/ObjectMap.java
@@ -376,11 +376,16 @@ public class ObjectMap extends LinkedHashMap<String,Object> {
 	 * @param def The default value if the entry doesn't exist.
 	 * @return The value, or the default value if the entry doesn't exist.
 	 */
+	@SuppressWarnings("unchecked")
 	public <T> T get(Class<T> type, String key, T def) {
 		Object o = get(key);
 		if (o == null)
 			return def;
-		T t = session.convertToType(o, type);
+		T t = null;
+		if (session != null)
+			t = session.convertToType(o, type);
+		else if (ClassUtils.isParentClass(type, o.getClass()))
+			t = (T)o;
 		if (t == null)
 			return def;
 		return t;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/PropertyStore.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/PropertyStore.java b/juneau-core/src/main/java/org/apache/juneau/PropertyStore.java
index dc5f064..9e2a33c 100644
--- a/juneau-core/src/main/java/org/apache/juneau/PropertyStore.java
+++ b/juneau-core/src/main/java/org/apache/juneau/PropertyStore.java
@@ -645,6 +645,40 @@ public final class PropertyStore {
 	}
 
 	/**
+	 * Returns a property value either cast to the specified type, or a new instance of the specified type.
+	 * <p>
+	 * It's assumed that the current property value is either an instance of that type, or a <code>Class</code> that's
+	 * a subclass of the type to be instantiated.
+	 *
+	 * @param name The full name of the property (e.g. <js>"BeanContext.sortProperties"</js>)
+	 * @param type The class type to convert the property value to.
+	 * @param def The type to instantiate if the property is not set.
+	 * @param args The arguments to pass to the default type constructor.
+	 *
+	 * @return The property either cast to the specified type, or instantiated from a <code>Class</code> object.
+	 * @throws ConfigException If property has a value that cannot be converted to a boolean.
+	 */
+	@SuppressWarnings("unchecked")
+	public <T> T getTypedProperty(String name, Class<T> type, Class<? extends T> def, Object...args) {
+		rl.lock();
+		try {
+			Object o = null;
+			PropertyMap pm = getPropertyMap(prefix(name));
+			if (pm != null)
+				o = pm.get(name, type, null);
+			if (o == null && def != null)
+				o = ClassUtils.newInstance(type, def, args);
+			if (o == null)
+				return null;
+			if (ClassUtils.isParentClass(type, o.getClass()))
+				return (T)o;
+			throw new FormattedRuntimeException("Invalid object of type {0} found in call to PropertyStore.getTypeProperty({1},{2},{3},...)", o.getClass(), name, type, def);
+		} finally {
+			rl.unlock();
+		}
+	}
+
+	/**
 	 * Returns a property value converted to a {@link LinkedHashMap} with the specified
 	 * 	key and value types.
 	 *

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserBuilder.java
index a33f9d6..6124708 100644
--- a/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserBuilder.java
@@ -408,8 +408,8 @@ public class CsvParserBuilder extends ParserBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public CsvParserBuilder debug(boolean value) {
-		super.debug(value);
+	public CsvParserBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java
index e752a82..098e9df 100644
--- a/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java
@@ -493,8 +493,8 @@ public class CsvSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public CsvSerializerBuilder debug(boolean value) {
-		super.debug(value);
+	public CsvSerializerBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/package.html
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/package.html b/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/package.html
index 8353a46..1551244 100644
--- a/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/package.html
+++ b/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/package.html
@@ -407,7 +407,9 @@
 		path=<js>"/jsonSchema"</js>,
 		messages=<js>"nls/JsonSchemaResource"</js>,
 		title=<js>"Sample JSON-Schema document"</js>,
-		pageLinks=<js>"{options:'?method=OPTIONS'}"</js>
+		htmldoc=<ja>@HtmlDoc</ja>(
+			links=<js>"{options:'?method=OPTIONS'}"</js>
+		)
 	)
 	<jk>public class</jk> JsonSchemaResource <jk>extends</jk> RestServletJenaDefault {
 	

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderGroupBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderGroupBuilder.java b/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderGroupBuilder.java
index 4f4de06..2d9a8ed 100644
--- a/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderGroupBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderGroupBuilder.java
@@ -95,7 +95,7 @@ public class EncoderGroupBuilder {
 	public EncoderGroup build() {
 		List<Encoder> l = new ArrayList<Encoder>();
 		for (Object e : encoders)
-			l.add(e instanceof Class ? newInstance(Encoder.class, (Class<?>)e) : (Encoder)e);
+			l.add(newInstance(Encoder.class, e));
 		Collections.reverse(l);
 		return new EncoderGroup(l.toArray(new Encoder[l.size()]));
 	}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/html/HtmlBeanPropertyMeta.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlBeanPropertyMeta.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlBeanPropertyMeta.java
index 63ecbb4..ce0be74 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlBeanPropertyMeta.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlBeanPropertyMeta.java
@@ -14,6 +14,7 @@ package org.apache.juneau.html;
 
 import org.apache.juneau.*;
 import org.apache.juneau.html.annotation.*;
+import org.apache.juneau.internal.*;
 
 /**
  * Metadata on bean properties specific to the HTML serializers and parsers pulled from the {@link Html @Html} annotation on the bean property.
@@ -45,7 +46,7 @@ public final class HtmlBeanPropertyMeta extends BeanPropertyMetaExtended {
 		this.noTables = b.noTables;
 		this.noTableHeaders = b.noTableHeaders;
 		this.asPlainText = b.asPlainText;
-		this.render = b.render.newInstance();
+		this.render = ClassUtils.newInstance(HtmlRender.class, b.render);
 		this.link = b.link;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/html/HtmlClassMeta.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlClassMeta.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlClassMeta.java
index 0ea336e..5442a2d 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlClassMeta.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlClassMeta.java
@@ -23,6 +23,7 @@ public class HtmlClassMeta extends ClassMetaExtended {
 
 	private final Html html;
 	private final boolean asXml, noTables, noTableHeaders, asPlainText;
+	private final HtmlRender<?> render;
 
 	/**
 	 * Constructor.
@@ -37,11 +38,13 @@ public class HtmlClassMeta extends ClassMetaExtended {
 			noTables = html.noTables();
 			noTableHeaders = html.noTableHeaders();
 			asPlainText = html.asPlainText();
+			render = ClassUtils.newInstance(HtmlRender.class, html.render());
 		} else {
 			asXml = false;
 			noTables = false;
 			noTableHeaders = false;
 			asPlainText = false;
+			render = null;
 		}
 	}
 
@@ -89,4 +92,13 @@ public class HtmlClassMeta extends ClassMetaExtended {
 	public boolean isNoTableHeaders() {
 		return noTableHeaders;
 	}
+
+	/**
+	 * Returns the {@link Html#render()} annotation defined on the class.
+	 *
+	 * @return The value of the {@link Html#render()} annotation.
+	 */
+	public HtmlRender<?> getRender() {
+		return render;
+	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
index b51c8d6..65c980a 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
@@ -17,7 +17,6 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
-import org.apache.juneau.dto.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.serializer.*;
 
@@ -47,10 +46,6 @@ import org.apache.juneau.serializer.*;
 @SuppressWarnings("hiding")
 public class HtmlDocSerializer extends HtmlStrippedDocSerializer {
 
-	// Properties defined in RestServletProperties
-	private static final String
-		REST_method = "RestServlet.method";
-
 	/** Default serializer, all default settings. */
 	public static final HtmlDocSerializer DEFAULT = new HtmlDocSerializer(PropertyStore.create());
 
@@ -81,89 +76,25 @@ public class HtmlDocSerializer extends HtmlStrippedDocSerializer {
 
 		HtmlDocSerializerSession s = (HtmlDocSerializerSession)session;
 		HtmlWriter w = s.getWriter();
-		UriResolver uriResolver = s.getUriResolver();
-
-		boolean isOptionsPage = session.getProperty(REST_method, "").equalsIgnoreCase("OPTIONS");
+		HtmlDocTemplate t = s.getTemplate();
 
-		// Render the header.
 		w.sTag("html").nl();
-		w.sTag("head").nl();
-
-		String cssUrl = s.getCssUrl();
-		if (cssUrl == null)
-			cssUrl = "servlet:/style.css";
-		cssUrl = uriResolver.resolve(cssUrl);
-
-		w.oTag(1, "style")
-			.attr("type", "text/css")
-			.appendln(">")
-			.append(2, "@import ").q().append(cssUrl).q().appendln(";");
-		if (s.isNoWrap())
-			w.appendln("\n* {white-space:nowrap;}");
-		if (s.getCssImports() != null)
-			for (String cssImport : s.getCssImports())
-				w.append(2, "@import ").q().append(cssImport).q().appendln(";");
-		w.eTag(1, "style").nl();
-		w.eTag("head").nl();
-		w.sTag("body").nl();
-		// Write the title of the page.
-		String title = s.getTitle();
-		if (title == null && isOptionsPage)
-			title = "Options";
-		String description = s.getText();
-		if (title != null)
-			w.oTag(1, "h3").attr("class", "title").append('>').text(title).eTag("h3").nl();
-		if (description != null)
-			w.oTag(1, "h5").attr("class", "description").append('>').text(description).eTag("h5").nl();
-
-		// Write the action links that render above the results.
-		List<Link> actions = new LinkedList<Link>();
-
-		// If this is an OPTIONS request, provide a 'back' link to return to the GET request page.
-		if (! isOptionsPage) {
-			Map<String,String> htmlLinks = s.getLinks();
-			if (htmlLinks != null) {
-				for (Map.Entry<String,String> e : htmlLinks.entrySet()) {
-					String uri = uriResolver.resolve(e.getValue());
-					actions.add(new Link(e.getKey(), uri));
-				}
-			}
-		}
-
-		if (actions.size() > 0) {
-			w.oTag(1, "p").attr("class", "links").append('>').nl();
-			for (Iterator<Link> i = actions.iterator(); i.hasNext();) {
-				Link h = i.next();
-				w.oTag(2, "a").attr("class", "link").attr("href", h.getHref(), true).append('>').append(h.getName()).eTag("a").nl();
-				if (i.hasNext())
-					w.append(3, " - ").nl();
-			}
-			w.eTag(1, "p").nl();
-		}
-
-		s.indent = 3;
-
-		// To allow for page formatting using CSS, we encapsulate the data inside two div tags:
-		// <div class='outerdata'><div class='data' id='data'>...</div></div>
-		w.oTag(1, "div").attr("class","outerdata").append('>').nl();
-		w.oTag(2, "div").attr("class","data").attr("id", "data").append('>').nl();
-		if (isEmptyList(o))
-			w.oTag(3, "p").append('>').append("no results").eTag("p");
-		else
-			super.doSerialize(s, o);
-		w.eTag(2, "div").nl();
-		w.eTag(1, "div").nl();
-
-		w.eTag("body").nl().eTag("html").nl();
+		w.sTag(1, "head").nl();
+		t.head(s, w, this, o);
+		w.eTag(1, "head").nl();
+		w.sTag(1, "body").nl();
+		t.body(s, w, this, o);
+		w.eTag(1, "body").nl();
+		w.eTag("html").nl();
 	}
 
-	private static boolean isEmptyList(Object o) {
-		if (o == null)
-			return false;
-		if (o instanceof Collection && ((Collection<?>)o).size() == 0)
-			return true;
-		if (o.getClass().isArray() && Array.getLength(o) == 0)
-			return true;
-		return false;
+	/**
+	 * Calls the parent {@link #doSerialize(SerializerSession, Object)} method which invokes just the HTML serializer.
+	 * @param session The serializer session.
+	 * @param o The object being serialized.
+	 * @throws Exception
+	 */
+	public void parentSerialize(SerializerSession session, Object o) throws Exception {
+		super.doSerialize(session, o);
 	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerContext.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerContext.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerContext.java
index f2dc494..3d7616a 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerContext.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerContext.java
@@ -39,11 +39,12 @@ import org.apache.juneau.*;
  * <p class='bcode'>
  * 	<ja>@RestResource</ja>(
  * 		messages=<js>"nls/AddressBookResource"</js>,
- * 		title=<js>"$L{title}"</js>,  <jc>// or pageTitle</jc>
- * 		description=<js>"$L{description}"</js>,  <jc>// or pageText</jc>
- * 		pageLinks=<js>"{options:'?method=OPTIONS',doc:'doc'}"</js>
+ * 		htmldoc=<ja>@HtmlDoc</ja>(
+ * 			title=<js>"$L{title}"</js>,
+ * 			description=<js>"$L{description}"</js>,
+ * 			links=<js>"{options:'?method=OPTIONS',doc:'doc'}"</js>
+ * 		)
  * 	)
- * 	<jk>public class</jk> AddressBookResource <jk>extends</jk> RestServletJenaDefault {
  * </p>
  *
  * <p>
@@ -101,12 +102,23 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext {
 	 * <p>
 	 * Shortcuts on <ja>@RestResource</ja> are also provided for this setting:
 	 * <p class='bcode'>
+	 * 	<jc>// Example if you want the swagger doc and HTML doc to share the same title.</jc>
 	 * 	<ja>@RestResource</ja>(
 	 * 		messages=<js>"nls/AddressBookResource"</js>,
-	 * 		title=<js>"My title"</js>,  <jc>// or pageTitle</jc>
+	 * 		title=<js>"My title"</js>
+	 * 	)
+	 *
+	 * 	<jc>// Example if you want the swagger doc and HTML doc to share the same title.</jc>
+	 * 	<ja>@RestResource</ja>(
+	 * 		messages=<js>"nls/AddressBookResource"</js>,
+	 * 		title=<js>"My title in Swagger"</js>,
+	 * 		htmldoc=<ja>@HtmlDoc</ja>(
+	 * 			title=<js>"My title in HTML"</js>
+	 * 		)
 	 * 	)
-	 * 	<jk>public class</jk> AddressBookResource <jk>extends</jk> RestServletJenaDefault {
 	 * </p>
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to represent no value to differentiate it from an empty string.
 	 */
 	public static final String HTMLDOC_title = "HtmlSerializer.title";
 
@@ -147,14 +159,54 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext {
 	 * <p>
 	 * Shortcuts on <ja>@RestResource</ja> are also provided for this setting:
 	 * <p class='bcode'>
+	 * 	<jc>// Example if you want the swagger doc and HTML doc to share the same description.</jc>
 	 * 	<ja>@RestResource</ja>(
 	 * 		messages=<js>"nls/AddressBookResource"</js>,
-	 * 		description=<js>"My description"</js>,  <jc>// or pageText</jc>
+	 * 		description=<js>"My description"</js>
+	 * 	)
+	 *
+	 * 	<jc>// Example if you want the swagger doc and HTML doc to share the same description.</jc>
+	 * 	<ja>@RestResource</ja>(
+	 * 		messages=<js>"nls/AddressBookResource"</js>,
+	 * 		description=<js>"My description in Swagger"</js>,
+	 * 		htmldoc=<ja>@HtmlDoc</ja>(
+	 * 			description=<js>"My description in HTML"</js>
+	 * 		)
+	 * 	)
+	 * </p>
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to represent no value to differentiate it from an empty string.
+	 */
+	public static final String HTMLDOC_description = "HtmlSerializer.description";
+
+	/**
+	 * <b>Configuration property:</b>  Header section contents.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"HtmlDocSerializer.header"</js>
+	 * 	<li><b>Data type:</b> <code>String</code>
+	 * 	<li><b>Default:</b> <jk>null</jk>
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <p>
+	 * Allows you to override the contents of the header section on the HTML page.
+	 * The header section normally contains the title and description at the top of the page.
+	 * <p>
+	 *
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<ja>@RestResource</ja>(
+	 * 		htmldoc=<ja>@HtmlDoc</ja>(
+	 * 			nav=<js>"&lt:p class='special-navigation'&gt;This is my special navigation content&lt:/p&gt;"</js>
+	 * 		)
 	 * 	)
-	 * 	<jk>public class</jk> AddressBookResource <jk>extends</jk> RestServletJenaDefault {
 	 * </p>
+	 * <p>
+	 * When this property is specified, the {@link #HTMLDOC_title} and {@link #HTMLDOC_description} properties are ignored.
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to represent no value to differentiate it from an empty string.
 	 */
-	public static final String HTMLDOC_text = "HtmlSerializer.description";
+	public static final String HTMLDOC_header = "HtmlDocSerializer.header";
 
 	/**
 	 * <b>Configuration property:</b>  Page links.
@@ -184,7 +236,6 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext {
 	 * </p>
 	 * <p class='bcode'>
 	 * 	<ja>@RestResource</ja>(
-	 * 		messages=<js>"nls/AddressBookResource"</js>,
 	 * 		properties={
 	 * 			<ja>@Property</ja>(name=HtmlDocSerializerContext.<jsf>HTMLDOC_links</jsf>, value=<js>"{options:'?method=OPTIONS',doc:'doc'}"</js>)
 	 * 		}
@@ -199,8 +250,9 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext {
 	 * A shortcut on <ja>@RestResource</ja> is also provided for this setting:
 	 * <p class='bcode'>
 	 * 	<ja>@RestResource</ja>(
-	 * 		messages=<js>"nls/AddressBookResource"</js>,
-	 * 		pageLinks=<js>"{options:'?method=OPTIONS',doc:'doc'}"</js>
+	 * 		htmldoc=@HtmlDoc(
+	 * 			links=<js>"{options:'?method=OPTIONS',doc:'doc'}"</js>
+	 * 		)
 	 * 	)
 	 * 	<jk>public class</jk> AddressBookResource <jk>extends</jk> RestServletJenaDefault {
 	 * </p>
@@ -213,6 +265,133 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext {
 	public static final String HTMLDOC_links_put = "HtmlDocSerializer.links.map.put";
 
 	/**
+	 * <b>Configuration property:</b>  Nav section contents.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"HtmlDocSerializer.nav"</js>
+	 * 	<li><b>Data type:</b> <code>String</code>
+	 * 	<li><b>Default:</b> <jk>null</jk>
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <p>
+	 * Allows you to override the contents of the nav section on the HTML page.
+	 * The nav section normally contains the page links at the top of the page.
+	 * <p>
+	 *
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<ja>@RestResource</ja>(
+	 * 		htmldoc=<ja>@HtmlDoc</ja>(
+	 * 			nav=<js>"&lt:p class='special-navigation'&gt;This is my special navigation content&lt:/p&gt;"</js>
+	 * 		)
+	 * 	)
+	 * </p>
+	 * <p>
+	 * When this property is specified, the {@link #HTMLDOC_links} property is ignored.
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to represent no value to differentiate it from an empty string.
+	 */
+	public static final String HTMLDOC_nav = "HtmlDocSerializer.nav";
+
+	/**
+	 * <b>Configuration property:</b>  Aside section contents.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"HtmlDocSerializer.aside"</js>
+	 * 	<li><b>Data type:</b> <code>String</code>
+	 * 	<li><b>Default:</b> <jk>null</jk>
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <p>
+	 * Allows you to specifigy the contents of the aside section on the HTML page.
+	 * The aside section floats on the right of the page for providing content supporting the serialized content of
+	 * 	the page.
+	 * <p>
+	 * By default, the aside section is empty.
+	 * <p>
+	 *
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<ja>@RestResource</ja>(
+	 * 		htmldoc=<ja>@HtmlDoc</ja>(
+	 * 			aside=<js>"&lt:ul&gt;&lt:li&gt;Item 1&lt:li&gt;Item 2&lt:li&gt;Item 3&lt:/ul&gt;"</js>
+	 * 		)
+	 * 	)
+	 * </p>
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to represent no value to differentiate it from an empty string.
+	 */
+	public static final String HTMLDOC_aside = "HtmlDocSerializer.aside";
+
+	/**
+	 * <b>Configuration property:</b>  Footer section contents.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"HtmlDocSerializer.footer"</js>
+	 * 	<li><b>Data type:</b> <code>String</code>
+	 * 	<li><b>Default:</b> <jk>null</jk>
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <p>
+	 * Allows you to specify the contents of the footer section on the HTML page.
+	 * <p>
+	 * By default, the footer section is empty.
+	 * <p>
+	 *
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<ja>@RestResource</ja>(
+	 * 		htmldoc=<ja>@HtmlDoc</ja>(
+	 * 			footer=<js>"&lt;b&gt;This interface is great!&lt;/b&gt;"</js>
+	 * 		)
+	 * 	)
+	 * </p>
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to represent no value to differentiate it from an empty string.
+	 */
+	public static final String HTMLDOC_footer = "HtmlDocSerializer.footer";
+
+	/**
+	 * <b>Configuration property:</b>  No-results message.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"HtmlDocSerializer.noResultsMessage"</js>
+	 * 	<li><b>Data type:</b> <code>String</code>
+	 * 	<li><b>Default:</b> <js>"&lt;p&gt;no results&lt;/p&gt;"</js>
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <p>
+	 * Allows you to specify the string message used when trying to serialize an empty array or empty list.
+	 * <p>
+	 *
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<ja>@RestResource</ja>(
+	 * 		htmldoc=<ja>@HtmlDoc</ja>(
+	 * 			=<js>"&lt;b&gt;This interface is great!&lt;/b&gt;"</js>
+	 * 		)
+	 * 	)
+	 * </p>
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to represent no value to differentiate it from an empty string.
+	 */
+	public static final String HTMLDOC_noResultsMessage = "HtmlDocSerializer.noResultsMessage";
+
+	/**
+	 * <b>Configuration property:</b>  Prevent word wrap on page.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"HtmlDocSerializer.nowrap"</js>
+	 * 	<li><b>Data type:</b> <code>Boolean</code>
+	 * 	<li><b>Default:</b> <jk>false</jk>
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <p>
+	 * Adds <js>"* {white-space:nowrap}"</js> to the CSS instructions on the page to prevent word wrapping.
+	 */
+	public static final String HTMLDOC_nowrap = "HtmlDocSerializer.nowrap";
+
+	/**
 	 * <b>Configuration property:</b>  Stylesheet URL.
 	 * <p>
 	 * <ul>
@@ -226,46 +405,80 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext {
 	 * <p>
 	 * If not specified, defaults to the built-in stylesheet located at <js>"style.css"</js>.
 	 * Note that this stylesheet is controlled by the <code><ja>@RestResource</ja>.stylesheet()</code> annotation.
+	 * <p>
+	 * A value of <js>"NONE"</js> can be used to represent no value to differentiate it from an empty string.
 	 */
 	public static final String HTMLDOC_cssUrl = "HtmlDocSerializer.cssUrl";
 
 	/**
-	 * <b>Configuration property:</b>  CSS imports.
+	 * <b>Configuration property:</b>  CSS code.
 	 * <p>
 	 * <ul>
-	 * 	<li><b>Name:</b> <js>"HtmlDocSerializer.cssImports.list"</js>
+	 * 	<li><b>Name:</b> <js>"HtmlDocSerializer.css.list"</js>
 	 * 	<li><b>Data type:</b> <code>List&lt;String&gt;</code>
 	 * 	<li><b>Default:</b> empty list
 	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
 	 * </ul>
 	 * <p>
-	 * Imports the specified CSS page URLs into the page.
+	 * Adds the specified CSS instructions to the HTML page.
+	 *
+	 * <h5 class='section'>Example:</h5>
+	 * </p>
+	 * <p class='bcode'>
+	 * 	<ja>@RestResource</ja>(
+	 * 		properties={
+	 * 			<ja>@Property</ja>(name=HtmlDocSerializerContext.<jsf>HTMLDOC_css</jsf>, value=<js>"h3 { color: red; }\nh5 { font-weight: bold; }"</js>)
+	 * 		}
+	 * 	)
+	 * </p>
+	 * A shortcut on <ja>@RestResource</ja> is also provided for this setting:
+	 * <p class='bcode'>
+	 * 	<ja>@RestResource</ja>(
+	 * 		htmldoc=@HtmlDoc(
+	 * 			css=<js>"h3 { color: red; }\nh5 { font-weight: bold; }"</js>
+	 * 		)
+	 * 	)
+	 * </p>
 	 */
-	public static final String HTMLDOC_cssImports = "HtmlDocSerializer.cssImports.list";
+	public static final String HTMLDOC_css = "HtmlDocSerializer.css.list";
 
 	/**
-	 * <b>Configuration property:</b>  Add to the {@link #HTMLDOC_cssImports} property.
+	 * <b>Configuration property:</b>  Add to the {@link #HTMLDOC_css} property.
 	 */
-	public static final String HTMLDOC_cssImports_add = "HtmlDocSerializer.cssImports.list.add";
+	public static final String HTMLDOC_css_add = "HtmlDocSerializer.css.list.add";
 
 	/**
-	 * <b>Configuration property:</b>  Prevent word wrap on page.
+	 * <b>Configuration property:</b>  HTML document template.
 	 * <p>
 	 * <ul>
-	 * 	<li><b>Name:</b> <js>"HtmlDocSerializer.nowrap"</js>
-	 * 	<li><b>Data type:</b> <code>Boolean</code>
-	 * 	<li><b>Default:</b> <jk>false</jk>
+	 * 	<li><b>Name:</b> <js>"HtmlDocSerializer.template"</js>
+	 * 	<li><b>Data type:</b> <code>Class&lt;? <jk>extends</jk> HtmlDocTemplate&gt;</code> or {@link HtmlDocTemplate}
+	 * 	<li><b>Default:</b> <code>HtmlDocTemplateBasic.<jk>class</jk></code>
 	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
 	 * </ul>
 	 * <p>
-	 * Adds <js>"* {white-space:nowrap}"</js> to the style header to prevent word wrapping.
+	 * Specifies the template to use for serializing the page.
+	 * <p>
+	 * By default, the {@link HtmlDocTemplateBasic} class is used to construct the contents of the HTML page, but
+	 * can be overridden with your own custom implementation class.
+	 *
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<ja>@RestResource</ja>(
+	 * 		htmldoc=@HtmlDoc(
+	 * 			template=MySpecialDocTemplate.<jk>class</jk>
+	 * 		)
+	 * 	)
+	 * </p>
 	 */
-	public static final String HTMLDOC_nowrap = "HtmlDocSerializer.nowrap";
+	public static final String HTMLDOC_template = "HtmlDocSerializer.template";
+
 
-	final String[] cssImports;
+	final String[] css;
 	final Map<String,String> links;
-	final String title, text, cssUrl;
+	final String title, description, header, nav, aside, footer, cssUrl, noResultsMessage;
 	final boolean nowrap;
+	final HtmlDocTemplate template;
 
 	/**
 	 * Constructor.
@@ -276,24 +489,36 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext {
 	 */
 	public HtmlDocSerializerContext(PropertyStore ps) {
 		super(ps);
-		cssImports = ps.getProperty(HTMLDOC_cssImports, String[].class, new String[0]);
+		css = ps.getProperty(HTMLDOC_css, String[].class, new String[0]);
 		title = ps.getProperty(HTMLDOC_title, String.class, null);
-		text = ps.getProperty(HTMLDOC_text, String.class, null);
+		description = ps.getProperty(HTMLDOC_description, String.class, null);
+		header = ps.getProperty(HTMLDOC_header, String.class, null);
+		nav = ps.getProperty(HTMLDOC_nav, String.class, null);
+		aside = ps.getProperty(HTMLDOC_aside, String.class, null);
+		footer = ps.getProperty(HTMLDOC_footer, String.class, null);
 		cssUrl = ps.getProperty(HTMLDOC_cssUrl, String.class, null);
 		nowrap = ps.getProperty(HTMLDOC_nowrap, boolean.class, false);
-		links = ps.getMap(HTMLDOC_links, String.class, String.class, Collections.<String,String>emptyMap());
+		links = ps.getMap(HTMLDOC_links, String.class, String.class, null);
+		noResultsMessage = ps.getProperty(HTMLDOC_noResultsMessage, String.class, "<p>no results</p>");
+		template = ps.getTypedProperty(HTMLDOC_template, HtmlDocTemplate.class, HtmlDocTemplateBasic.class);
 	}
 
 	@Override /* Context */
 	public ObjectMap asMap() {
 		return super.asMap()
 			.append("HtmlDocSerializerContext", new ObjectMap()
-				.append("cssImports", cssImports)
+				.append("cssImports", css)
 				.append("title", title)
-				.append("text", text)
+				.append("text", description)
+				.append("header", header)
+				.append("nav", nav)
+				.append("links", links)
+				.append("aside", aside)
+				.append("footer", footer)
 				.append("cssUrl", cssUrl)
 				.append("nowrap", nowrap)
-				.append("links", links)
+				.append("template", template)
+				.append("noResultsMessage", noResultsMessage)
 			);
 	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
index c9c69b7..5cb8d91 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
@@ -20,6 +20,7 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.http.*;
+import org.apache.juneau.internal.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.serializer.*;
 
@@ -32,10 +33,11 @@ import org.apache.juneau.serializer.*;
  */
 public final class HtmlDocSerializerSession extends HtmlSerializerSession {
 
-	private final String title, text, cssUrl;
-	private final String[] cssImports;
+	private final String title, description, header, nav, aside, footer, cssUrl, noResultsMessage;
+	private final String[] css;
 	private final Map<String,String> links;
 	private final boolean nowrap;
+	private final HtmlDocTemplate template;
 
 	/**
 	 * Create a new session using properties specified in the context.
@@ -59,73 +61,139 @@ public final class HtmlDocSerializerSession extends HtmlSerializerSession {
 		super(ctx, op, output, javaMethod, locale, timeZone, mediaType, uriContext);
 		if (op == null || op.isEmpty()) {
 			title = ctx.title;
-			text = ctx.text;
+			description = ctx.description;
+			header = ctx.header;
+			nav = ctx.nav;
+			aside = ctx.aside;
+			footer = ctx.footer;
 			links = ctx.links;
 			cssUrl = ctx.cssUrl;
-			cssImports = ctx.cssImports;
+			css = ctx.css;
 			nowrap = ctx.nowrap;
+			noResultsMessage = ctx.noResultsMessage;
+			template = ClassUtils.newInstance(HtmlDocTemplate.class, ctx.template);
 		} else {
 			title = op.getString(HTMLDOC_title, ctx.title);
-			text = op.getString(HTMLDOC_text, ctx.text);
-			links = new LinkedHashMap(op.getMap(HTMLDOC_links, ctx.links));
+			description = op.getString(HTMLDOC_description, ctx.description);
+			header = op.getString(HTMLDOC_header, ctx.nav);
+			nav = op.getString(HTMLDOC_nav, ctx.nav);
+			aside = op.getString(HTMLDOC_aside, ctx.aside);
+			footer = op.getString(HTMLDOC_footer, ctx.footer);
+			Map m = op.getMap(HTMLDOC_links, ctx.links);
+			links = ObjectUtils.isEmpty(m) ? null : new LinkedHashMap(m);
 			cssUrl = op.getString(HTMLDOC_cssUrl, ctx.cssUrl);
-			cssImports = split(op.getString(HTMLDOC_cssImports, null), ',');
+			css = split(op.getString(HTMLDOC_css, null), ',');
 			nowrap = op.getBoolean(HTMLDOC_cssUrl, ctx.nowrap);
+			noResultsMessage = op.getString(HTMLDOC_noResultsMessage, ctx.noResultsMessage);
+			template = ClassUtils.newInstance(HtmlDocTemplate.class, op.get(HTMLDOC_template, ctx.template));
 		}
 	}
 
 	/**
+	 * Returns the {@link HtmlDocSerializerContext#HTMLDOC_cssUrl} setting value in this context.
+	 * @return The {@link HtmlDocSerializerContext#HTMLDOC_cssUrl} setting value in this context.
+	 * 	<jk>null</jk> if not specified.  Never an empty string.
+	 */
+	public final String getCssUrl() {
+		return cssUrl;
+	}
+
+	/**
+	 * Returns the {@link HtmlDocSerializerContext#HTMLDOC_css} setting value in this context.
+	 * @return The {@link HtmlDocSerializerContext#HTMLDOC_css} setting value in this context.
+	 * 	<jk>null</jk> if not specified.  Never an empty array.
+	 */
+	public final String[] getCss() {
+		return css;
+	}
+
+	/**
+	 * Returns the {@link HtmlDocSerializerContext#HTMLDOC_nowrap} setting value in this context.
+	 * @return The {@link HtmlDocSerializerContext#HTMLDOC_nowrap} setting value in this context.
+	 */
+	public final boolean isNoWrap() {
+		return nowrap;
+	}
+
+	/**
 	 * Returns the {@link HtmlDocSerializerContext#HTMLDOC_title} setting value in this context.
-	 *
 	 * @return The {@link HtmlDocSerializerContext#HTMLDOC_title} setting value in this context.
+	 * 	<jk>null</jk> if not specified.  Never an empty string.
 	 */
 	public final String getTitle() {
 		return title;
 	}
 
 	/**
-	 * Returns the {@link HtmlDocSerializerContext#HTMLDOC_text} setting value in this context.
-	 *
-	 * @return The {@link HtmlDocSerializerContext#HTMLDOC_text} setting value in this context.
+	 * Returns the {@link HtmlDocSerializerContext#HTMLDOC_description} setting value in this context.
+	 * @return The {@link HtmlDocSerializerContext#HTMLDOC_description} setting value in this context.
+	 * 	<jk>null</jk> if not specified.  Never an empty string.
+	 */
+	public final String getDescription() {
+		return description;
+	}
+
+	/**
+	 * Returns the {@link HtmlDocSerializerContext#HTMLDOC_header} setting value in this context.
+	 * @return The {@link HtmlDocSerializerContext#HTMLDOC_header} setting value in this context.
+	 * 	<jk>null</jk> if not specified.  Never an empty string.
 	 */
-	public final String getText() {
-		return text;
+	public final String getHeader() {
+		return header;
 	}
 
 	/**
 	 * Returns the {@link HtmlDocSerializerContext#HTMLDOC_links} setting value in this context.
-	 *
 	 * @return The {@link HtmlDocSerializerContext#HTMLDOC_links} setting value in this context.
+	 * 	<jk>null</jk> if not specified.  Never an empty map.
 	 */
 	public final Map<String,String> getLinks() {
 		return links;
 	}
 
 	/**
-	 * Returns the {@link HtmlDocSerializerContext#HTMLDOC_cssUrl} setting value in this context.
-	 *
-	 * @return The {@link HtmlDocSerializerContext#HTMLDOC_cssUrl} setting value in this context.
+	 * Returns the template to use for generating the HTML page.
+	 * @return The HTML page generator.
+	 * 	Never <jk>null</jk>.
 	 */
-	public final String getCssUrl() {
-		return cssUrl;
+	public final HtmlDocTemplate getTemplate() {
+		return template;
 	}
 
 	/**
-	 * Returns the {@link HtmlDocSerializerContext#HTMLDOC_cssImports} setting value in this context.
-	 *
-	 * @return The {@link HtmlDocSerializerContext#HTMLDOC_cssImports} setting value in this context.
+	 * Returns the {@link HtmlDocSerializerContext#HTMLDOC_nav} setting value in this context.
+	 * @return The {@link HtmlDocSerializerContext#HTMLDOC_nav} setting value in this context.
+	 * 	<jk>null</jk> if not specified.  Never an empty string.
 	 */
-	public final String[] getCssImports() {
-		return cssImports;
+	public final String getNav() {
+		return nav;
 	}
 
 	/**
-	 * Returns the {@link HtmlDocSerializerContext#HTMLDOC_nowrap} setting value in this context.
-	 *
-	 * @return The {@link HtmlDocSerializerContext#HTMLDOC_nowrap} setting value in this context.
+	 * Returns the {@link HtmlDocSerializerContext#HTMLDOC_aside} setting value in this context.
+	 * @return The {@link HtmlDocSerializerContext#HTMLDOC_aside} setting value in this context.
+	 * 	<jk>null</jk> if not specified.  Never an empty string.
 	 */
-	public final boolean isNoWrap() {
-		return nowrap;
+	public final String getAside() {
+		return aside;
+	}
+
+	/**
+	 * Returns the {@link HtmlDocSerializerContext#HTMLDOC_footer} setting value in this context.
+	 * @return The {@link HtmlDocSerializerContext#HTMLDOC_footer} setting value in this context.
+	 * 	<jk>null</jk> if not specified.  Never an empty string.
+	 */
+	public final String getFooter() {
+		return footer;
+	}
+
+	/**
+	 * Returns the {@link HtmlDocSerializerContext#HTMLDOC_noResultsMessage} setting value in this context.
+	 * @return The {@link HtmlDocSerializerContext#HTMLDOC_noResultsMessage} setting value in this context.
+	 * 	<jk>null</jk> if not specified.  Never an empty string.
+	 */
+	public final String getNoResultsMessage() {
+		return noResultsMessage;
 	}
 
 	@Override /* XmlSerializerSession */

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocTemplate.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocTemplate.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocTemplate.java
new file mode 100644
index 0000000..f850b6b
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocTemplate.java
@@ -0,0 +1,164 @@
+// ***************************************************************************************************************************
+// * 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.html;
+
+/**
+ * Defines the interface for rendering the contents of an HTML page produced by the {@link HtmlDocSerializer} serializer.
+ * <p>
+ * The HTML doc serializer produces the following document structure with the typical contents:
+ * <p class='bcode'>
+ * 	<xt>&lt;html&gt;
+ * 		&lt;head&gt;
+ * 			&lt;style <xa>type</xa>=<xs>'text/css'</xs>&gt;
+ * 				<xv>CSS styles and links to stylesheets</xv>
+ * 			&lt/style&gt;
+ * 		&lt;/head&gt;
+ * 		&lt;body&gt;
+ * 			&lt;header&gt;
+ * 				<xv>Page title and description</xv>
+ * 			&lt;/header&gt;
+ * 			&lt;nav&gt;
+ * 				<xv>Page links</xv>
+ * 			&lt;/nav&gt;
+ * 			&lt;aside&gt;
+ * 				<xv>Side-bar page links</xv>
+ * 			&lt;/aside&gt;
+ * 			&lt;article&gt;
+ * 				<xv>Contents of serialized object</xv>
+ * 			&lt;/article&gt;
+ * 			&lt;footer&gt;
+ * 				<xv>Footer message</xv>
+ * 			&lt;/footer&gt;
+ * 		&lt;/body&gt;
+ * 	&lt;/html&gt;</xt>
+ * </p>
+ * <p>
+ * This interface allows you to control how these sections get rendered.
+ */
+public interface HtmlDocTemplate {
+
+	/**
+	 * Renders the contents of the <code><xt>&lt;head&gt;</xt></code> element.
+	 * @param session The current serializer session.
+	 * @param w The writer being written to.
+	 * @param s The serializer calling this method.
+	 * @param o The object being serialized.
+	 * @throws Exception Any exception can be thrown.
+	 */
+	public void head(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception;
+
+	/**
+	 * Renders the contents of the <code><xt>&lt;head&gt;</xt> / <xt>&lt;style</xt> <xa>type</xa>=<xs>"text/css"</xs><xt>&gt;</xt></code> element.
+	 * @param session The current serializer session.
+	 * @param w The writer being written to.
+	 * @param s The serializer calling this method.
+	 * @param o The object being serialized.
+	 * @throws Exception Any exception can be thrown.
+	 */
+	public void css(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception;
+
+	/**
+	 * Renders the contents of the <code><xt>&lt;body&gt;</xt></code> element.
+	 * @param session The current serializer session.
+	 * @param w The writer being written to.
+	 * @param s The serializer calling this method.
+	 * @param o The object being serialized.
+	 * @throws Exception Any exception can be thrown.
+	 */
+	public void body(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception;
+
+	/**
+	 * Renders the contents of the <code><xt>&lt;body&gt;</xt> / <xt>&lt;header&gt;</xt></code> element.
+	 * @param session The current serializer session.
+	 * @param w The writer being written to.
+	 * @param s The serializer calling this method.
+	 * @param o The object being serialized.
+	 * @throws Exception Any exception can be thrown.
+	 */
+	public void header(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception;
+
+	/**
+	 * Renders the contents of the <code><xt>&lt;body&gt;</xt> / <xt>&lt;nav&gt;</xt></code> element.
+	 * @param session The current serializer session.
+	 * @param w The writer being written to.
+	 * @param s The serializer calling this method.
+	 * @param o The object being serialized.
+	 * @throws Exception Any exception can be thrown.
+	 */
+	public void nav(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception;
+
+	/**
+	 * Renders the contents of the <code><xt>&lt;body&gt;</xt> / <xt>&lt;article&gt;</xt></code> element.
+	 * @param session The current serializer session.
+	 * @param w The writer being written to.
+	 * @param s The serializer calling this method.
+	 * @param o The object being serialized.
+	 * @throws Exception Any exception can be thrown.
+	 */
+	public void article(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception;
+
+	/**
+	 * Renders the contents of the <code><xt>&lt;body&gt;</xt> / <xt>&lt;aside&gt;</xt></code> element.
+	 * @param session The current serializer session.
+	 * @param w The writer being written to.
+	 * @param s The serializer calling this method.
+	 * @param o The object being serialized.
+	 * @throws Exception Any exception can be thrown.
+	 */
+	public void aside(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception;
+
+	/**
+	 * Renders the contents of the <code><xt>&lt;body&gt;</xt> / <xt>&lt;footer&gt;</xt></code> element.
+	 * @param session The current serializer session.
+	 * @param w The writer being written to.
+	 * @param s The serializer calling this method.
+	 * @param o The object being serialized.
+	 * @throws Exception Any exception can be thrown.
+	 */
+	public void footer(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception;
+
+	/**
+	 * Returns <jk>true</jk> if this page should render a <code><xt>&lt;head&gt;</xt> / <xt>&lt;style</xt> <xa>type</xa>=<xs>"text/css"</xs><xt>&gt;</xt></code> element.
+	 * @param session The current serializer session.
+	 * @return A boolean flag.
+	 */
+	public boolean hasCss(HtmlDocSerializerSession session);
+
+	/**
+	 * Returns <jk>true</jk> if this page should render a <code><xt>&lt;body&gt;</xt> / <xt>header</xt></code> element.
+	 * @param session The current serializer session.
+	 * @return A boolean flag.
+	 */
+	public boolean hasHeader(HtmlDocSerializerSession session);
+
+	/**
+	 * Returns <jk>true</jk> if this page should render a <code><xt>&lt;body&gt;</xt> / <xt>nav</xt></code> element.
+	 * @param session The current serializer session.
+	 * @return A boolean flag.
+	 */
+	public boolean hasNav(HtmlDocSerializerSession session);
+
+	/**
+	 * Returns <jk>true</jk> if this page should render a <code><xt>&lt;body&gt;</xt> / <xt>aside</xt></code> element.
+	 * @param session The current serializer session.
+	 * @return A boolean flag.
+	 */
+	public boolean hasAside(HtmlDocSerializerSession session);
+
+	/**
+	 * Returns <jk>true</jk> if this page should render a <code><xt>&lt;body&gt;</xt> / <xt>footer</xt></code> element.
+	 * @param session The current serializer session.
+	 * @return A boolean flag.
+	 */
+	public boolean hasFooter(HtmlDocSerializerSession session);
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocTemplateBasic.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocTemplateBasic.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocTemplateBasic.java
new file mode 100644
index 0000000..6553fdb
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocTemplateBasic.java
@@ -0,0 +1,188 @@
+// ***************************************************************************************************************************
+// * 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.html;
+
+import java.util.Map;
+
+import org.apache.juneau.internal.*;
+
+/**
+ * A basic template for the HTML doc serializer.
+ * <p>
+ * This class can be subclassed to customize page rendering.
+ */
+public class HtmlDocTemplateBasic implements HtmlDocTemplate {
+
+	@Override /* HtmlDocTemplate */
+	public void head(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception {
+		if (hasCss(session)) {
+			w.oTag(1, "style").attr("type", "text/css").appendln(">").nl();
+			css(session, w, s, o);
+			w.eTag(1, "style").nl();
+		}
+	}
+
+	@Override /* HtmlDocTemplate */
+	public void css(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception {
+
+		String cssUrl = session.getCssUrl();
+		if (cssUrl == null)
+			cssUrl = "servlet:/style.css";
+		cssUrl = session.resolveUri(cssUrl);
+
+		w.append(2, "@import ").q().append(cssUrl).q().appendln(";");
+		if (session.isNoWrap())
+			w.appendln("\n* {white-space:nowrap;}");
+		if (session.getCss() != null)
+			for (String css : session.getCss())
+				w.appendln(css);
+	}
+
+	@Override /* HtmlDocTemplate */
+	public void body(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception {
+
+		if (hasHeader(session)) {
+			w.sTag(1, "header").nl();
+			header(session, w, s, o);
+			w.eTag(1, "header").nl();
+		}
+
+		if (hasNav(session)) {
+			w.sTag(1, "nav").nl();
+			nav(session, w, s, o);
+			w.eTag(1, "nav").nl();
+		}
+
+		w.sTag(1, "section").nl();
+
+		w.sTag(2, "article").nl();
+		article(session, w, s, o);
+		w.eTag(2, "article").nl();
+
+		if (hasAside(session)) {
+			w.sTag(2, "aside").nl();
+			aside(session, w, s, o);
+			w.eTag(2, "aside").nl();
+		}
+
+		w.eTag(1, "section").nl();
+
+		if (hasFooter(session)) {
+			w.sTag(1, "footer").nl();
+			footer(session, w, s, o);
+			w.eTag(1, "footer").nl();
+		}
+	}
+
+	@Override /* HtmlDocTemplate */
+	public void header(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception {
+		// Write the title of the page.
+		String header = session.getHeader();
+		if (header != null) {
+			if (exists(header))
+				w.append(header).nl();
+		} else {
+			String title = session.getTitle();
+			String description = session.getDescription();
+			if (exists(title))
+				w.oTag(1, "h3").attr("class", "title").append('>').text(title).eTag("h3").nl();
+			if (exists(description))
+				w.oTag(1, "h5").attr("class", "description").append('>').text(description).eTag("h5").nl();
+		}
+	}
+
+
+	@Override /* HtmlDocTemplate */
+	public void nav(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception {
+		String nav = session.getNav();
+		if (nav != null) {
+			if (exists(nav))
+				w.append(nav).nl();
+		} else {
+			Map<String,String> htmlLinks = session.getLinks();
+			boolean first = true;
+			if (htmlLinks != null) {
+				for (Map.Entry<String,String> e : htmlLinks.entrySet()) {
+					if (! first)
+						w.append(3, " - ").nl();
+					first = false;
+					w.oTag("a").attr("class", "link").attr("href", session.resolveUri(e.getValue()), true).cTag().text(e.getKey(), true).eTag("a");
+				}
+			}
+		}
+	}
+
+	@Override /* HtmlDocTemplate */
+	public void aside(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception {
+		String aside = session.getAside();
+		if (exists(aside))
+			w.append(aside);
+	}
+
+	@Override /* HtmlDocTemplate */
+	public void article(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception {
+		// To allow for page formatting using CSS, we encapsulate the data inside two div tags:
+		// <div class='outerdata'><div class='data' id='data'>...</div></div>
+		w.oTag(3, "div").attr("class","outerdata").append('>').nl();
+		w.oTag(4, "div").attr("class","data").attr("id", "data").append('>').nl();
+
+		if (o == null) {
+			w.append("<null/>").nl();
+		} else if (ObjectUtils.isEmpty(o)){
+			String m = session.getNoResultsMessage();
+			if (exists(m))
+				w.append(m).nl();
+		} else {
+			s.parentSerialize(session, o);
+		}
+
+		w.eTag(4, "div").nl();
+		w.eTag(3, "div").nl();
+	}
+
+	@Override /* HtmlDocTemplate */
+	public void footer(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception {
+		String footer = session.getFooter();
+		if (exists(footer))
+			w.append(footer);
+	}
+
+	@Override /* HtmlDocTemplate */
+	public boolean hasCss(HtmlDocSerializerSession session) {
+		return true;
+	}
+
+	@Override /* HtmlDocTemplate */
+	public boolean hasHeader(HtmlDocSerializerSession session) {
+		return exists(session.getHeader()) || exists(session.getTitle()) || exists(session.getDescription());
+	}
+
+	@Override /* HtmlDocTemplate */
+	public boolean hasNav(HtmlDocSerializerSession session) {
+		return exists(session.getNav()) || session.getLinks() != null;
+	}
+
+	@Override /* HtmlDocTemplate */
+	public boolean hasAside(HtmlDocSerializerSession session) {
+		return exists(session.getAside());
+	}
+
+	@Override /* HtmlDocTemplate */
+	public boolean hasFooter(HtmlDocSerializerSession session) {
+		return exists(session.getFooter());
+	}
+
+	private static boolean exists(String s) {
+		return s != null && ! "NONE".equals(s);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/html/HtmlParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlParserBuilder.java
index 4c2c283..7418e1b 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlParserBuilder.java
@@ -437,8 +437,8 @@ public class HtmlParserBuilder extends XmlParserBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public HtmlParserBuilder debug(boolean value) {
-		super.debug(value);
+	public HtmlParserBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/html/HtmlRender.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlRender.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlRender.java
index b30c67e..b31fea7 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlRender.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlRender.java
@@ -118,7 +118,7 @@ import org.apache.juneau.serializer.*;
  * </p>
  * @param <T> The bean property type.
  */
-public class HtmlRender<T> {
+public abstract class HtmlRender<T> {
 
 	/**
 	 * Returns the CSS style of the element containing the bean property value.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java
index 0bb39b8..f17f7d7 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java
@@ -424,6 +424,8 @@ public class HtmlSerializer extends XmlSerializer {
 			HtmlBeanPropertyMeta hbpMeta = pMeta.getExtendedMeta(HtmlBeanPropertyMeta.class);
 			String link = hbpMeta.getLink();
 			HtmlRender render = hbpMeta.getRender();
+			if (render == null)
+				render = cMeta.getExtendedMeta(HtmlClassMeta.class).getRender();
 
 			String key = p.getName();
 			Object value = p.getValue();
@@ -437,7 +439,7 @@ public class HtmlSerializer extends XmlSerializer {
 			out.sTag(i+1, "tr").nl();
 			out.sTag(i+2, "td").text(key).eTag("td").nl();
 			out.oTag(i+2, "td");
-			String style = render.getStyle(session, value);
+			String style = render == null ? null : render.getStyle(session, value);
 			if (style != null)
 				out.attr("style", style);
 			out.cTag();
@@ -445,7 +447,7 @@ public class HtmlSerializer extends XmlSerializer {
 			try {
 				if (link != null)
 					out.oTag(i+3, "a").attrUri("href", m.resolveVars(link)).cTag();
-				ContentResult cr = serializeAnything(session, out, render.getContent(session, value), cMeta, key, 2, pMeta, false);
+				ContentResult cr = serializeAnything(session, out, render == null ? value : render.getContent(session, value), cMeta, key, 2, pMeta, false);
 				if (cr == CR_NORMAL)
 					out.i(i+2);
 				if (link != null)
@@ -548,17 +550,22 @@ public class HtmlSerializer extends XmlSerializer {
 						BeanPropertyMeta pMeta = p.getMeta();
 						HtmlBeanPropertyMeta hpMeta = pMeta.getExtendedMeta(HtmlBeanPropertyMeta.class);
 						String link = hpMeta.getLink();
-						HtmlRender render = hpMeta.getRender();
 
 						Object value = p.getValue();
+						ClassMeta<?> cMeta = session.getClassMetaForObject(value);
+
+						HtmlRender render = hpMeta.getRender();
+						if (render == null)
+							render = cMeta.getExtendedMeta(HtmlClassMeta.class).getRender();
+
 						out.oTag(i+2, "td");
-						String style = render.getStyle(session, value);
+						String style = render == null ? null : render.getStyle(session, value);
 						if (style != null)
 							out.attr("style", style);
 						out.cTag();
 						if (link != null)
 							out.oTag(i+3, "a").attrUri("href", m2.resolveVars(link)).cTag();
-						ContentResult cr = serializeAnything(session, out, render.getContent(session, value), pMeta.getClassMeta(), p.getKey().toString(), 2, pMeta, false);
+						ContentResult cr = serializeAnything(session, out, render == null ? value : render.getContent(session, value), pMeta.getClassMeta(), p.getKey().toString(), 2, pMeta, false);
 						if (cr == CR_NORMAL)
 							out.i(i+2);
 						if (link != null)

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerBuilder.java
index c2f4112..13aa762 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerBuilder.java
@@ -671,8 +671,8 @@ public class HtmlSerializerBuilder extends XmlSerializerBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public HtmlSerializerBuilder debug(boolean value) {
-		super.debug(value);
+	public HtmlSerializerBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/html/HtmlWriter.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlWriter.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlWriter.java
index d8648b4..192a73b 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlWriter.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlWriter.java
@@ -347,5 +347,4 @@ public class HtmlWriter extends XmlWriter {
 		super.append(c);
 		return this;
 	}
-
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/html/annotation/Html.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/annotation/Html.java b/juneau-core/src/main/java/org/apache/juneau/html/annotation/Html.java
index dcfc53c..3ada90e 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/annotation/Html.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/annotation/Html.java
@@ -57,7 +57,7 @@ public @interface Html {
 	/**
 	 * Associates an {@link HtmlRender} with a bean property for custom HTML rendering of the property.
 	 * <p>
-	 * This annotation applies to bean properties only.
+	 * This annotation applies to bean properties and classes.
 	 */
 	@SuppressWarnings("rawtypes")
 	Class<? extends HtmlRender> render() default HtmlRender.class;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/http/MediaType.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/http/MediaType.java b/juneau-core/src/main/java/org/apache/juneau/http/MediaType.java
index a11d658..fc6452a 100644
--- a/juneau-core/src/main/java/org/apache/juneau/http/MediaType.java
+++ b/juneau-core/src/main/java/org/apache/juneau/http/MediaType.java
@@ -32,7 +32,7 @@ import org.apache.juneau.json.*;
  */
 @BeanIgnore
 @SuppressWarnings("unchecked")
-public class MediaType {
+public class MediaType implements Comparable<MediaType> {
 
 	private static final boolean nocache = Boolean.getBoolean("juneau.nocache");
 	private static final ConcurrentHashMap<String,MediaType> cache = new ConcurrentHashMap<String,MediaType>();
@@ -280,4 +280,9 @@ public class MediaType {
 	public boolean equals(Object o) {
 		return this == o;
 	}
+
+	@Override
+	public int compareTo(MediaType o) {
+		return mediaType.compareTo(o.mediaType);
+	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/internal/ClassUtils.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/internal/ClassUtils.java b/juneau-core/src/main/java/org/apache/juneau/internal/ClassUtils.java
index ef46ffc..f4ebf10 100644
--- a/juneau-core/src/main/java/org/apache/juneau/internal/ClassUtils.java
+++ b/juneau-core/src/main/java/org/apache/juneau/internal/ClassUtils.java
@@ -301,6 +301,16 @@ public final class ClassUtils {
 	}
 
 	/**
+	 * Returns <jk>true</jk> if the specified class is abstract.
+	 *
+	 * @param c The class.
+	 * @return <jk>true</jk> if the specified class is abstract.
+	 */
+	public static boolean isAbstract(Class<?> c) {
+		return Modifier.isAbstract(c.getModifiers());
+	}
+
+	/**
 	 * Returns <jk>true</jk> if the specified method is public.
 	 *
 	 * @param m The method.
@@ -745,20 +755,30 @@ public final class ClassUtils {
 	 *
 	 * @param c The class to cast to.
 	 * @param c2 The class to instantiate.
+	 * 	Can also be an instance of the class.
 	 * @param args The arguments to pass to the constructor.
-	 * @return The new class instance, or <jk>null</jk> if the class was <jk>null</jk>.
+	 * @return The new class instance, or <jk>null</jk> if the class was <jk>null</jk> or is abstract or an interface.
 	 * @throws RuntimeException if constructor could not be found or called.
 	 */
 	@SuppressWarnings("unchecked")
-	public static <T> T newInstance(Class<T> c, Class<?> c2, Object...args) {
+	public static <T> T newInstance(Class<T> c, Object c2, Object...args) {
 		if (c2 == null)
 			return null;
-		try {
-			if (args.length == 0)
-				return (T)c2.newInstance();
-			return (T)c2.getConstructor(getClasses(args)).newInstance(args);
-		} catch (Exception e) {
-			throw new RuntimeException("Could not instantiate class " + c.getName(), e);
+		if (c2 instanceof Class) {
+			try {
+				Class<?> c3 = (Class<?>)c2;
+				if (c3.isInterface() || isAbstract(c3))
+					return null;
+				if (args.length == 0)
+					return (T)c3.newInstance();
+				return (T)c3.getConstructor(getClasses(args)).newInstance(args);
+			} catch (Exception e) {
+				throw new FormattedRuntimeException(e, "Could not instantiate class {0}", c.getName());
+			}
+		} else if (isParentClass(c, c2.getClass())) {
+			return (T)c2;
+		} else {
+			throw new FormattedRuntimeException("Object of type {0} found but was expecting {1}.", c2.getClass(), c.getClass());
 		}
 	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/internal/ObjectUtils.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/internal/ObjectUtils.java b/juneau-core/src/main/java/org/apache/juneau/internal/ObjectUtils.java
index 699b0fc..73f73d4 100644
--- a/juneau-core/src/main/java/org/apache/juneau/internal/ObjectUtils.java
+++ b/juneau-core/src/main/java/org/apache/juneau/internal/ObjectUtils.java
@@ -44,6 +44,7 @@ public class ObjectUtils {
 	 * <ul>
 	 * 	<li><jk>null</jk>
 	 * 	<li>An empty Collection
+	 * 	<li>An empty Map
 	 * 	<li>An empty array
 	 * 	<li>An empty CharSequence
 	 * 	<li>An empty String when serialized to a string using {@link Object#toString()}.
@@ -58,6 +59,8 @@ public class ObjectUtils {
 			return true;
 		if (o instanceof Collection)
 			return ((Collection)o).isEmpty();
+		if (o instanceof Map)
+			return ((Map)o).isEmpty();
 		if (o.getClass().isArray())
 			return (Array.getLength(o) == 0);
 		return o.toString().isEmpty();

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/jso/JsoParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/jso/JsoParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/jso/JsoParserBuilder.java
index aa5e448..2052f42 100644
--- a/juneau-core/src/main/java/org/apache/juneau/jso/JsoParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/jso/JsoParserBuilder.java
@@ -409,8 +409,8 @@ public class JsoParserBuilder extends ParserBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public JsoParserBuilder debug(boolean value) {
-		super.debug(value);
+	public JsoParserBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/jso/JsoSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/jso/JsoSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/jso/JsoSerializerBuilder.java
index 1da92e6..bd2e498 100644
--- a/juneau-core/src/main/java/org/apache/juneau/jso/JsoSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/jso/JsoSerializerBuilder.java
@@ -493,8 +493,8 @@ public class JsoSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public JsoSerializerBuilder debug(boolean value) {
-		super.debug(value);
+	public JsoSerializerBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/json/JsonParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/json/JsonParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/json/JsonParserBuilder.java
index 40cfd30..94b3340 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/JsonParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/json/JsonParserBuilder.java
@@ -409,8 +409,8 @@ public class JsonParserBuilder extends ParserBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public JsonParserBuilder debug(boolean value) {
-		super.debug(value);
+	public JsonParserBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/json/JsonSchemaSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/json/JsonSchemaSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/json/JsonSchemaSerializerBuilder.java
index d58aca2..e9ee47f 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/JsonSchemaSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/json/JsonSchemaSerializerBuilder.java
@@ -511,8 +511,8 @@ public class JsonSchemaSerializerBuilder extends JsonSerializerBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public JsonSchemaSerializerBuilder debug(boolean value) {
-		super.debug(value);
+	public JsonSchemaSerializerBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java
index 98ed08c..92adbd4 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java
@@ -558,8 +558,8 @@ public class JsonSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public JsonSerializerBuilder debug(boolean value) {
-		super.debug(value);
+	public JsonSerializerBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/json/package.html
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/json/package.html b/juneau-core/src/main/java/org/apache/juneau/json/package.html
index 960ea0b..c32bd3c 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/package.html
+++ b/juneau-core/src/main/java/org/apache/juneau/json/package.html
@@ -1004,7 +1004,9 @@
 		messages=<js>"nls/AddressBookResource"</js>,
 		title=<js>"$L{title}"</js>,
 		description=<js>"$L{description}"</js>,
-		pageLinks=<js>"{options:'?method=OPTIONS',doc:'doc'}"</js>,
+		htmldoc=<ja>@HtmlDoc</ja>(
+			links=<js>"{options:'?method=OPTIONS'}"</js>
+		),
 		properties={
 			<ja>@Property</ja>(name=SerializerContext.<jsf>SERIALIZER_quoteChar</jsf>, value=<js>"'"</js>),
 			<ja>@Property</ja>(name=HtmlSerializerContext.<jsf>HTML_uriAnchorText</jsf>, value=<jsf>TO_STRING</jsf>)

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParserBuilder.java
index 38d2841..de0744c 100644
--- a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParserBuilder.java
@@ -409,8 +409,8 @@ public class MsgPackParserBuilder extends ParserBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public MsgPackParserBuilder debug(boolean value) {
-		super.debug(value);
+	public MsgPackParserBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerBuilder.java
index fc4935f..d0e79b7 100644
--- a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerBuilder.java
@@ -493,8 +493,8 @@ public class MsgPackSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public MsgPackSerializerBuilder debug(boolean value) {
-		super.debug(value);
+	public MsgPackSerializerBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/parser/ParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/parser/ParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/parser/ParserBuilder.java
index dbc9d86..b15ab39 100644
--- a/juneau-core/src/main/java/org/apache/juneau/parser/ParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/parser/ParserBuilder.java
@@ -537,8 +537,8 @@ public class ParserBuilder extends CoreObjectBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public ParserBuilder debug(boolean value) {
-		super.debug(value);
+	public ParserBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroupBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroupBuilder.java b/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroupBuilder.java
index 0eb2e92..1731af9 100644
--- a/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroupBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroupBuilder.java
@@ -860,12 +860,11 @@ public class ParserGroupBuilder {
 	/**
 	 * Sets the {@link BeanContext#BEAN_debug} property on all parsers in this group.
 	 *
-	 * @param value The new value for this property.
 	 * @return This object (for method chaining).
 	 * @see BeanContext#BEAN_debug
 	 */
-	public ParserGroupBuilder debug(boolean value) {
-		return property(BEAN_debug, value);
+	public ParserGroupBuilder debug() {
+		return property(BEAN_debug, true);
 	}
 
 	/**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParserBuilder.java
index 9f9177d..3540188 100644
--- a/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParserBuilder.java
@@ -409,8 +409,8 @@ public class PlainTextParserBuilder extends ParserBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public PlainTextParserBuilder debug(boolean value) {
-		super.debug(value);
+	public PlainTextParserBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerBuilder.java
index 883053a..8995da2 100644
--- a/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerBuilder.java
@@ -493,8 +493,8 @@ public class PlainTextSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* CoreObjectBuilder */
-	public PlainTextSerializerBuilder debug(boolean value) {
-		super.debug(value);
+	public PlainTextSerializerBuilder debug() {
+		super.debug();
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/f4812b7c/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteMethodArg.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteMethodArg.java b/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteMethodArg.java
index cf2326b..140d9f8 100644
--- a/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteMethodArg.java
+++ b/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteMethodArg.java
@@ -55,6 +55,6 @@ public class RemoteMethodArg {
 		this.name = name.isEmpty() ? name2 : name;
 		this.index = index;
 		this.skipIfNE = skipIfNE;
-		this.serializer = (serializer == PartSerializer.class ? null : newInstance(PartSerializer.class, serializer));
+		this.serializer = newInstance(PartSerializer.class, serializer);
 	}
 }