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/12/26 19:07:01 UTC

[juneau] branch master updated: Javadocs and Config API modernization.

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 57babc4  Javadocs and Config API modernization.
57babc4 is described below

commit 57babc43e61fbd448cdcce53f046062ae28e76ca
Author: JamesBognar <ja...@salesforce.com>
AuthorDate: Sun Dec 26 14:06:25 2021 -0500

    Javadocs and Config API modernization.
---
 .../main/java/org/apache/juneau/config/Config.java |  621 +-----------
 .../java/org/apache/juneau/config/ConfigMod.java   |    6 +-
 .../main/java/org/apache/juneau/config/Entry.java  |  872 ++++++++++++++++
 .../apache/juneau/config/internal/ConfigEntry.java |    9 +
 .../juneau/config/internal/package-info.java       |   18 -
 .../org/apache/juneau/config/vars/ConfigVar.java   |    4 +-
 .../org/apache/juneau/internal/StringUtils.java    |   69 +-
 .../06.juneau-rest-server/05.jrs.Marshalling.html  |   25 +
 .../{09.jrs.Guards.html => 07.jrs.Guards.html}     |   40 +-
 .../06.juneau-rest-server/07.jrs.Transforms.html   |   72 --
 ....jrs.Converters.html => 08.jrs.Converters.html} |   64 +-
 ...Messages.html => 09.jrs.LocalizedMessages.html} |   12 +-
 .../{13.jrs.Encoders.html => 10.jrs.Encoders.html} |    6 +-
 .../06.juneau-rest-server/10.jrs.RoleGuards.html   |   81 --
 ...onFiles.html => 11.jrs.ConfigurationFiles.html} |   74 +-
 ....SvlVariables.html => 12.jrs.SvlVariables.html} |    0
 ...rs.StaticFiles.html => 13.jrs.StaticFiles.html} |    0
 ...ersioning.html => 14.jrs.ClientVersioning.html} |    0
 ....InfoProvider.html => 15.jrs.InfoProvider.html} |    0
 .../{19.jrs.Swagger.html => 16.jrs.Swagger.html}   |    0
 .../01.jrs.BasicRestServletSwagger.html            |    0
 .../02.jrs.BasicSwaggerInfo.html                   |    0
 .../03.jrs.SwaggerTags.html                        |    0
 .../04.jrs.SwaggerOperations.html                  |    0
 .../05.jrs.SwaggerParameters.html                  |    0
 .../06.jrs.SwaggerParameterExamples.html           |    0
 .../07.jrs.SwaggerResponses.html                   |    0
 .../08.jrs.SwaggerResponseExamples.html            |    0
 .../09.jrs.SwaggerModels.html                      |    0
 .../10.jrs.SwaggerStylesheet.html                  |    0
 .../doc-files/jrs.Swagger.Models.1.png             |  Bin
 .../doc-files/jrs.Swagger.Models.2.png             |  Bin
 .../doc-files/jrs.Swagger.Models.3.png             |  Bin
 .../doc-files/jrs.Swagger.Operations.1.png         |  Bin
 .../doc-files/jrs.Swagger.Operations.2.png         |  Bin
 .../doc-files/jrs.Swagger.Operations.3.png         |  Bin
 .../doc-files/jrs.Swagger.Parameters.1.png         |  Bin
 .../doc-files/jrs.Swagger.Parameters.2.png         |  Bin
 .../doc-files/jrs.Swagger.Parameters.3.png         |  Bin
 .../doc-files/jrs.Swagger.Parameters.4.png         |  Bin
 .../doc-files/jrs.Swagger.ResponseExamples.1.png   |  Bin
 .../doc-files/jrs.Swagger.ResponseExamples.2.png   |  Bin
 .../doc-files/jrs.Swagger.ResponseExamples.3.png   |  Bin
 .../doc-files/jrs.Swagger.ResponseExamples.4.png   |  Bin
 ...istics.html => 17.jrs.ExecutionStatistics.html} |    0
 ...notation.html => 18.jrs.HtmlDocAnnotation.html} |    0
 .../01.jrs.HtmlUIvsDI.html                         |    0
 .../02.jrs.HtmlWidgets.html                        |    0
 .../03.jrs.HtmlPredefinedWidgets.html              |    0
 .../04.jrs.HtmlUiCustomization.html                |    0
 .../05.jrs.HtmlStylesheets.html                    |    0
 .../jrs.HtmlDocAnnotation.PredefinedWidgets.1.png  |  Bin
 .../jrs.HtmlDocAnnotation.PredefinedWidgets.2.png  |  Bin
 .../jrs.HtmlDocAnnotation.PredefinedWidgets.3.png  |  Bin
 .../jrs.HtmlDocAnnotation.PredefinedWidgets.4.png  |  Bin
 ...aultHeaders.html => 19.jrs.DefaultHeaders.html} |    0
 ...ugging.html => 20.jrs.LoggingAndDebugging.html} |    0
 ...tatusCodes.html => 21.jrs.HttpStatusCodes.html} |    0
 ...ods.html => 22.jrs.OverloadingHttpMethods.html} |    0
 ...rameters.html => 23.jrs.BuiltInParameters.html} |    0
 ...tml => 24.jrs.CustomSerializersAndParsers.html} |    0
 ...singWithOsgi.html => 25.jrs.UsingWithOsgi.html} |    0
 ...29.jrs.Injection.html => 26.jrs.Injection.html} |    0
 ....jrs.OtherNotes.html => 27.jrs.OtherNotes.html} |    0
 ...rs.RestContext.html => 28.jrs.RestContext.html} |    0
 .../{32.jrs.RestRpc.html => 29.jrs.RestRpc.html}   |    0
 ...l => 30.jrs.CustomRestContextsAndBuilders.html} |    0
 ...rocessors.html => 31.jrs.FluentAssertions.html} |    0
 ....jrs.UtilityBeans.html => 32.jrs.Overview.html} |    0
 ...ertions.html => 33.jrs.ResponseProcessors.html} |    0
 ....jrs.Overview.html => 34.jrs.UtilityBeans.html} |    0
 ...ndlingUris.html => 35.jrs.SerializingUris.html} |    0
 juneau-doc/src/main/javadoc/overview.html          | 1062 +++++++++-----------
 juneau-doc/src/main/javadoc/resources/docs.txt     |    6 +-
 .../src/main/javadoc/resources/fragments/toc.html  |   14 +-
 .../apache/juneau/microservice/Microservice.java   |   33 +-
 .../juneau/microservice/console/ConfigCommand.java |    4 +-
 .../microservice/resources/DirectoryResource.java  |    8 +-
 .../microservice/resources/LogsResource.java       |   10 +-
 .../apache/juneau/rest/test/ConfigResource.java    |    2 +-
 .../apache/juneau/rest/test/TestMicroservice.java  |    2 +-
 .../microservice/jetty/JettyMicroservice.java      |   12 +-
 .../jetty/resources/DebugResource.java             |    2 +-
 .../rest/springboot/BasicSpringRestServlet.java    |    2 +-
 .../org/apache/juneau/rest/BasicRestObject.java    |    2 +-
 .../org/apache/juneau/rest/BasicRestServlet.java   |    2 +-
 .../server/config/repository/GetConfiguration.java |    4 +-
 .../apache/juneau/config/ConfigImportsTest.java    |   72 +-
 .../apache/juneau/config/ConfigInterfaceTest.java  |   94 +-
 .../java/org/apache/juneau/config/ConfigTest.java  |  592 +++++------
 90 files changed, 1941 insertions(+), 1955 deletions(-)

diff --git a/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/Config.java b/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/Config.java
index 2f2808b..33ce5f4 100644
--- a/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/Config.java
+++ b/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/Config.java
@@ -545,10 +545,10 @@ public final class Config extends Context implements ConfigEventListener {
 	final int binaryLineLength;
 	final BinaryFormat binaryFormat;
 	final boolean multiLineValuesOnSeparateLines, readOnly;
+	final BeanSession beanSession;
+	final VarResolverSession varSession;
 
-	private final VarResolverSession varSession;
 	private final ConfigMap configMap;
-	private final BeanSession beanSession;
 	private final List<ConfigEventListener> listeners = Collections.synchronizedList(new LinkedList<ConfigEventListener>());
 
 
@@ -640,7 +640,7 @@ public final class Config extends Context implements ConfigEventListener {
 	 * @param key The key.
 	 * @return The value, or <jk>null</jk> if the section or value doesn't exist.
 	 */
-	public String get(String key) {
+	private String getRaw(String key) {
 
 		String sname = sname(key);
 		String skey = skey(key);
@@ -651,7 +651,7 @@ public final class Config extends Context implements ConfigEventListener {
 			return null;
 
 		String val = ce.getValue();
-		for (ConfigMod m : ConfigMod.asModifiersReverse(ce.getModifiers())) {
+		for (ConfigMod m : ConfigMod.toReverse(ce.getModifiers())) {
 			if (m == ENCODED) {
 				if (encoder.isEncoded(val))
 					val = encoder.decode(key, val);
@@ -674,7 +674,7 @@ public final class Config extends Context implements ConfigEventListener {
 		for (String section : getSections()) {
 			for (String key : getKeys(section)) {
 				String k = (section.isEmpty() ? key : section + '/' + key);
-				System.setProperty(k, get(k));
+				System.setProperty(k, getRaw(k));
 			}
 		}
 		return this;
@@ -705,7 +705,7 @@ public final class Config extends Context implements ConfigEventListener {
 		String mod = ce == null ? "" : ce.getModifiers();
 
 		String s = stringify(value);
-		for (ConfigMod m : ConfigMod.asModifiers(mod)) {
+		for (ConfigMod m : ConfigMod.toModifiers(mod)) {
 			if (m == ENCODED) {
 				s = encoder.encode(key, s);
 			}
@@ -814,7 +814,7 @@ public final class Config extends Context implements ConfigEventListener {
 			}
 		}
 
-		configMap.setEntry(sname, skey, s, modifiers == null ? null : ConfigMod.asString(modifiers), comment, preLines);
+		configMap.setEntry(sname, skey, s, modifiers == null ? null : ConfigMod.toModString(modifiers), comment, preLines);
 		return this;
 	}
 
@@ -873,557 +873,14 @@ public final class Config extends Context implements ConfigEventListener {
 	 * 		<js>"section/key"</js> - A value from the specified section.
 	 * </ul>
 	 *
-	 * @param key The key.
-	 * @return The value, or <jk>null</jk> if the section or key does not exist.
-	 */
-	public String getString(String key) {
-		String s = get(key);
-		if (s == null)
-			return null;
-		if (varSession != null)
-			s = varSession.resolve(s);
-		return s;
-	}
-
-	/**
-	 * Gets the entry with the specified key.
-	 *
-	 * <p>
-	 * The key can be in one of the following formats...
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		<js>"key"</js> - A value in the default section (i.e. defined above any <c>[section]</c> header).
-	 * 	<li>
-	 * 		<js>"section/key"</js> - A value from the specified section.
-	 * </ul>
-	 *
-	 * @param key The key.
-	 * @param def The default value if the value does not exist.
-	 * @return The value, or the default value if the section or key does not exist.
-	 */
-	public String getString(String key, String def) {
-		String s = get(key);
-		if (isEmpty(s))
-			return def;
-		if (varSession != null)
-			s = varSession.resolve(s);
-		return s;
-	}
-
-	/**
-	 * Gets the entry with the specified key, splits the value on commas, and returns the values as trimmed strings.
-	 *
-	 * @param key The key.
-	 * @return The value, or an empty array if the section or key does not exist.
-	 */
-	public String[] getStringArray(String key) {
-		return getStringArray(key, new String[0]);
-	}
-
-	/**
-	 * Same as {@link #getStringArray(String)} but returns a default value if the value cannot be found.
-	 *
-	 * @param key The key.
-	 * @param def The default value if the value does not exist.
-	 * @return The value, or the default value if the section or key does not exist or is blank.
-	 */
-	public String[] getStringArray(String key, String[] def) {
-		String s = getString(key);
-		if (isEmpty(s))
-			return def;
-		String[] r = split(s);
-		return r.length == 0 ? def : r;
-	}
-
-	/**
-	 * Convenience method for getting int config values.
-	 *
-	 * <p>
-	 * <js>"K"</js>, <js>"M"</js>, and <js>"G"</js> can be used to identify kilo, mega, and giga.
-	 *
-	 * <h5 class='section'>Example:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		<code><js>"100K"</js> => 1024000</code>
-	 * 	<li>
-	 * 		<code><js>"100M"</js> => 104857600</code>
-	 * </ul>
-	 *
-	 * <p>
-	 * Uses {@link Integer#decode(String)} underneath, so any of the following integer formats are supported:
-	 * <ul>
-	 * 	<li><js>"0x..."</js>
-	 * 	<li><js>"0X..."</js>
-	 * 	<li><js>"#..."</js>
-	 * 	<li><js>"0..."</js>
-	 * </ul>
-	 *
-	 * @param key The key.
-	 * @return The value, or <c>0</c> if the value does not exist or the value is empty.
-	 */
-	public int getInt(String key) {
-		return getInt(key, 0);
-	}
-
-	/**
-	 * Same as {@link #getInt(String)} but returns a default value if not set.
-	 *
-	 * @param key The key.
-	 * @param def The default value if the value does not exist.
-	 * @return The value, or the default value if the value does not exist or the value is empty.
-	 */
-	public int getInt(String key, int def) {
-		String s = getString(key);
-		if (isEmpty(s))
-			return def;
-		return parseIntWithSuffix(s);
-	}
-
-	/**
-	 * Convenience method for getting boolean config values.
-	 *
-	 * @param key The key.
-	 * @return The value, or <jk>false</jk> if the section or key does not exist or cannot be parsed as a boolean.
-	 */
-	public boolean getBoolean(String key) {
-		return getBoolean(key, false);
-	}
-
-	/**
-	 * Convenience method for getting boolean config values.
-	 *
-	 * @param key The key.
-	 * @param def The default value if the value does not exist.
-	 * @return The value, or the default value if the section or key does not exist or cannot be parsed as a boolean.
-	 */
-	public boolean getBoolean(String key, boolean def) {
-		String s = getString(key);
-		return isEmpty(s) ? def : Boolean.parseBoolean(s);
-	}
-
-	/**
-	 * Convenience method for getting long config values.
-	 *
-	 * <p>
-	 * <js>"K"</js>, <js>"M"</js>, and <js>"G"</js> can be used to identify kilo, mega, and giga.
-	 *
-	 * <h5 class='section'>Example:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		<code><js>"100K"</js> => 1024000</code>
-	 * 	<li>
-	 * 		<code><js>"100M"</js> => 104857600</code>
-	 * </ul>
-	 *
-	 * <p>
-	 * Uses {@link Long#decode(String)} underneath, so any of the following number formats are supported:
-	 * <ul>
-	 * 	<li><js>"0x..."</js>
-	 * 	<li><js>"0X..."</js>
-	 * 	<li><js>"#..."</js>
-	 * 	<li><js>"0..."</js>
-	 * </ul>
-	 *
-	 * @param key The key.
-	 * @return The value, or <c>0</c> if the value does not exist or the value is empty.
-	 */
-	public long getLong(String key) {
-		return getLong(key, 0);
-	}
-
-	/**
-	 * Same as {@link #getLong(String)} but returns a default value if not set.
-	 *
-	 * @param key The key.
-	 * @param def The default value if the value does not exist.
-	 * @return The value, or the default value if the value does not exist or the value is empty.
-	 */
-	public long getLong(String key, long def) {
-		String s = getString(key);
-		if (isEmpty(s))
-			return def;
-		return parseLongWithSuffix(s);
-	}
-
-	/**
-	 * Convenience method for getting double config values.
-	 *
-	 * <p>
-	 * Uses {@link Double#valueOf(String)} underneath, so any of the following number formats are supported:
-	 * <ul>
-	 * 	<li><js>"0x..."</js>
-	 * 	<li><js>"0X..."</js>
-	 * 	<li><js>"#..."</js>
-	 * 	<li><js>"0..."</js>
-	 * </ul>
-	 *
-	 * @param key The key.
-	 * @return The value, or <c>0</c> if the value does not exist or the value is empty.
-	 */
-	public double getDouble(String key) {
-		return getDouble(key, 0);
-	}
-
-	/**
-	 * Same as {@link #getDouble(String)} but returns a default value if not set.
-	 *
-	 * @param key The key.
-	 * @param def The default value if the value does not exist.
-	 * @return The value, or the default value if the value does not exist or the value is empty.
-	 */
-	public double getDouble(String key, double def) {
-		String s = getString(key);
-		if (isEmpty(s))
-			return def;
-		return Double.valueOf(s);
-	}
-
-	/**
-	 * Convenience method for getting float config values.
-	 *
-	 * <p>
-	 * Uses {@link Float#valueOf(String)} underneath, so any of the following number formats are supported:
-	 * <ul>
-	 * 	<li><js>"0x..."</js>
-	 * 	<li><js>"0X..."</js>
-	 * 	<li><js>"#..."</js>
-	 * 	<li><js>"0..."</js>
-	 * </ul>
-	 *
-	 * @param key The key.
-	 * @return The value, or <c>0</c> if the value does not exist or the value is empty.
-	 */
-	public float getFloat(String key) {
-		return getFloat(key, 0);
-	}
-
-	/**
-	 * Same as {@link #getFloat(String)} but returns a default value if not set.
-	 *
-	 * @param key The key.
-	 * @param def The default value if the value does not exist.
-	 * @return The value, or the default value if the value does not exist or the value is empty.
-	 */
-	public float getFloat(String key, float def) {
-		String s = getString(key);
-		if (isEmpty(s))
-			return def;
-		return Float.valueOf(s);
-	}
-
-	/**
-	 * Convenience method for getting byte array config values.
-	 *
-	 * <p>
-	 * This is equivalent to calling the following:
-	 * <p class='bcode w800'>
-	 * 	<jk>byte</jk>[] b = config.getObject(key, <jk>byte</jk>[].<jk>class</jk>);
-	 * </p>
-	 *
-	 * <p>
-	 * Byte arrays are stored as encoded strings, typically BASE64, but dependent on the {@link Builder#binaryFormat(BinaryFormat)} setting.
-	 *
-	 * @param key The key.
-	 * @return The value, or <jk>null</jk> if the section or key does not exist.
-	 * @throws ParseException If value could not be converted to a byte array.
-	 */
-	public byte[] getBytes(String key) throws ParseException {
-		String s = get(key);
-		if (s == null)
-			return null;
-		if (s.isEmpty())
-			return new byte[0];
-		return getObject(key, byte[].class);
-	}
-
-	/**
-	 * Same as {@link #getBytes(String)} but with a default value if the entry doesn't exist.
-	 *
-	 * @param key The key.
-	 * @param def The default value if the value does not exist.
-	 * @return The value, or the default value if the section or key does not exist.
-	 * @throws ParseException If value could not be converted to a byte array.
-	 */
-	public byte[] getBytes(String key, byte[] def) throws ParseException {
-		String s = get(key);
-		if (s == null)
-			return def;
-		if (s.isEmpty())
-			return def;
-		return getObjectWithDefault(key, def, byte[].class);
-	}
-
-	/**
-	 * Gets the entry with the specified key and converts it to the specified value.
-	 *
-	 * <p>
-	 * The key can be in one of the following formats...
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		<js>"key"</js> - A value in the default section (i.e. defined above any <c>[section]</c> header).
-	 * 	<li>
-	 * 		<js>"section/key"</js> - A value from the specified section.
-	 * </ul>
-	 *
-	 * <p>
-	 * The type can be a simple type (e.g. beans, strings, numbers) or parameterized type (collections/maps).
-	 *
-	 * <h5 class='section'>Examples:</h5>
-	 * <p class='bcode w800'>
-	 * 	Config cf = Config.<jsm>create</jsm>().name(<js>"MyConfig.cfg"</js>).build();
-	 *
-	 * 	<jc>// Parse into a linked-list of strings.</jc>
-	 * 	List l = cf.getObject(<js>"MySection/myListOfStrings"</js>, LinkedList.<jk>class</jk>, String.<jk>class</jk>);
-	 *
-	 * 	<jc>// Parse into a linked-list of beans.</jc>
-	 * 	List l = cf.getObject(<js>"MySection/myListOfBeans"</js>, LinkedList.<jk>class</jk>, MyBean.<jk>class</jk>);
-	 *
-	 * 	<jc>// Parse into a linked-list of linked-lists of strings.</jc>
-	 * 	List l = cf.getObject(<js>"MySection/my2dListOfStrings"</js>, LinkedList.<jk>class</jk>,
-	 * 		LinkedList.<jk>class</jk>, String.<jk>class</jk>);
-	 *
-	 * 	<jc>// Parse into a map of string keys/values.</jc>
-	 * 	Map m = cf.getObject(<js>"MySection/myMap"</js>, TreeMap.<jk>class</jk>, String.<jk>class</jk>,
-	 * 		String.<jk>class</jk>);
-	 *
-	 * 	<jc>// Parse into a map containing string keys and values of lists containing beans.</jc>
-	 * 	Map m = cf.getObject(<js>"MySection/myMapOfListsOfBeans"</js>, TreeMap.<jk>class</jk>, String.<jk>class</jk>,
-	 * 		List.<jk>class</jk>, MyBean.<jk>class</jk>);
-	 * </p>
-	 *
-	 * <p>
-	 * <c>Collection</c> classes are assumed to be followed by zero or one objects indicating the element type.
-	 *
-	 * <p>
-	 * <c>Map</c> classes are assumed to be followed by zero or two meta objects indicating the key and value
-	 * types.
-	 *
-	 * <p>
-	 * The array can be arbitrarily long to indicate arbitrarily complex data structures.
-	 *
-	 * <ul class='notes'>
-	 * 	<li>
-	 * 		Use the {@link #getObject(String, Class)} method instead if you don't need a parameterized map/collection.
-	 * </ul>
-	 *
-	 * @param key The key.
-	 * @param type
-	 * 	The object type to create.
-	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
-	 * @param args
-	 * 	The type arguments of the class if it's a collection or map.
-	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
-	 * 	<br>Ignored if the main type is not a map or collection.
-	 * @throws ParseException If parser could not parse the value or if a parser is not registered with this config file.
-	 * @return The value, or <jk>null</jk> if the section or key does not exist.
-	 */
-	public <T> T getObject(String key, Type type, Type...args) throws ParseException {
-		return getObject(key, (Parser)null, type, args);
-	}
-
-	/**
-	 * Same as {@link #getObject(String, Type, Type...)} but allows you to specify the parser to use to parse the value.
-	 *
-	 * @param key The key.
-	 * @param parser
-	 * 	The parser to use for parsing the object.
-	 * 	If <jk>null</jk>, then uses the predefined parser on the config file.
-	 * @param type
-	 * 	The object type to create.
-	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
-	 * @param args
-	 * 	The type arguments of the class if it's a collection or map.
-	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
-	 * 	<br>Ignored if the main type is not a map or collection.
-	 * @throws ParseException If parser could not parse the value or if a parser is not registered with this config file.
-	 * @return The value, or <jk>null</jk> if the section or key does not exist.
-	 */
-	public <T> T getObject(String key, Parser parser, Type type, Type...args) throws ParseException {
-		assertArgNotNull("type", type);
-		return parse(getString(key), parser, type, args);
-	}
-
-	/**
-	 * Same as {@link #getObject(String, Type, Type...)} except optimized for a non-parameterized class.
-	 *
-	 * <p>
-	 * This is the preferred parse method for simple types since you don't need to cast the results.
-	 *
-	 * <h5 class='section'>Examples:</h5>
-	 * <p class='bcode w800'>
-	 * 	Config cf = Config.<jsm>create</jsm>().name(<js>"MyConfig.cfg"</js>).build();
-	 *
-	 * 	<jc>// Parse into a string.</jc>
-	 * 	String s = cf.getObject(<js>"MySection/mySimpleString"</js>, String.<jk>class</jk>);
-	 *
-	 * 	<jc>// Parse into a bean.</jc>
-	 * 	MyBean b = cf.getObject(<js>"MySection/myBean"</js>, MyBean.<jk>class</jk>);
-	 *
-	 * 	<jc>// Parse into a bean array.</jc>
-	 * 	MyBean[] b = cf.getObject(<js>"MySection/myBeanArray"</js>, MyBean[].<jk>class</jk>);
-	 *
-	 * 	<jc>// Parse into a linked-list of objects.</jc>
-	 * 	List l = cf.getObject(<js>"MySection/myList"</js>, LinkedList.<jk>class</jk>);
-	 *
-	 * 	<jc>// Parse into a map of object keys/values.</jc>
-	 * 	Map m = cf.getObject(<js>"MySection/myMap"</js>, TreeMap.<jk>class</jk>);
-	 * </p>
-	 *
-	 * @param <T> The class type of the object being created.
-	 * @param key The key.
-	 * @param type The object type to create.
-	 * @return The parsed object.
-	 * @throws ParseException Malformed input encountered.
-	 * @see BeanSession#getClassMeta(Type,Type...) for argument syntax for maps and collections.
-	 */
-	public <T> T getObject(String key, Class<T> type) throws ParseException {
-		return getObject(key, (Parser)null, type);
-	}
-
-	/**
-	 * Same as {@link #getObject(String, Class)} but allows you to specify the parser to use to parse the value.
-	 *
-	 * @param <T> The class type of the object being created.
-	 * @param key The key.
-	 * @param parser
-	 * 	The parser to use for parsing the object.
-	 * 	If <jk>null</jk>, then uses the predefined parser on the config file.
-	 * @param type The object type to create.
-	 * @return The parsed object.
-	 * @throws ParseException Malformed input encountered.
-	 * @see BeanSession#getClassMeta(Type,Type...) for argument syntax for maps and collections.
-	 */
-	public <T> T getObject(String key, Parser parser, Class<T> type) throws ParseException {
-		assertArgNotNull("c", type);
-		return parse(getString(key), parser, type);
-	}
-
-	/**
-	 * Gets the entry with the specified key and converts it to the specified value.
-	 *
-	 * <p>
-	 * Same as {@link #getObject(String, Class)}, but with a default value.
-	 *
-	 * @param key The key.
-	 * @param def The default value if the value does not exist.
-	 * @param type The class to convert the value to.
-	 * @throws ParseException If parser could not parse the value or if a parser is not registered with this config file.
-	 * @return The value, or <jk>null</jk> if the section or key does not exist.
-	 */
-	public <T> T getObjectWithDefault(String key, T def, Class<T> type) throws ParseException {
-		return getObjectWithDefault(key, null, def, type);
-	}
-
-	/**
-	 * Same as {@link #getObjectWithDefault(String, Object, Class)} but allows you to specify the parser to use to parse
-	 * the value.
-	 *
-	 * @param key The key.
-	 * @param parser
-	 * 	The parser to use for parsing the object.
-	 * 	If <jk>null</jk>, then uses the predefined parser on the config file.
-	 * @param def The default value if the value does not exist.
-	 * @param type The class to convert the value to.
-	 * @throws ParseException If parser could not parse the value or if a parser is not registered with this config file.
-	 * @return The value, or <jk>null</jk> if the section or key does not exist.
-	 */
-	public <T> T getObjectWithDefault(String key, Parser parser, T def, Class<T> type) throws ParseException {
-		assertArgNotNull("type", type);
-		T t = parse(getString(key), parser, type);
-		return (t == null ? def : t);
-	}
-
-	/**
-	 * Gets the entry with the specified key and converts it to the specified value.
-	 *
 	 * <p>
-	 * Same as {@link #getObject(String, Type, Type...)}, but with a default value.
+	 * If entry does not exist, returns an empty {@link Entry} object.
 	 *
 	 * @param key The key.
-	 * @param def The default value if the value does not exist.
-	 * @param type
-	 * 	The object type to create.
-	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
-	 * @param args
-	 * 	The type arguments of the class if it's a collection or map.
-	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
-	 * 	<br>Ignored if the main type is not a map or collection.
-	 * @throws ParseException If parser could not parse the value or if a parser is not registered with this config file.
-	 * @return The value, or <jk>null</jk> if the section or key does not exist.
+	 * @return The value, never <jk>null</jk>.
 	 */
-	public <T> T getObjectWithDefault(String key, T def, Type type, Type...args) throws ParseException {
-		return getObjectWithDefault(key, null, def, type, args);
-	}
-
-	/**
-	 * Same as {@link #getObjectWithDefault(String, Object, Type, Type...)} but allows you to specify the parser to use
-	 * to parse the value.
-	 *
-	 * @param key The key.
-	 * @param parser
-	 * 	The parser to use for parsing the object.
-	 * 	If <jk>null</jk>, then uses the predefined parser on the config file.
-	 * @param def The default value if the value does not exist.
-	 * @param type
-	 * 	The object type to create.
-	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
-	 * @param args
-	 * 	The type arguments of the class if it's a collection or map.
-	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
-	 * 	<br>Ignored if the main type is not a map or collection.
-	 * @throws ParseException If parser could not parse the value or if a parser is not registered with this config file.
-	 * @return The value, or <jk>null</jk> if the section or key does not exist.
-	 */
-	public <T> T getObjectWithDefault(String key, Parser parser, T def, Type type, Type...args) throws ParseException {
-		assertArgNotNull("type", type);
-		T t = parse(getString(key), parser, type, args);
-		return (t == null ? def : t);
-	}
-
-	/**
-	 * Convenience method for returning a config entry as an {@link OMap}.
-	 *
-	 * @param key The key.
-	 * @return The value, or <jk>null</jk> if the section or key does not exist.
-	 * @throws ParseException Malformed input encountered.
-	 */
-	public OMap getMap(String key) throws ParseException {
-		return getObject(key, OMap.class);
-	}
-
-	/**
-	 * Convenience method for returning a config entry as an {@link OMap}.
-	 *
-	 * @param key The key.
-	 * @param def The default value.
-	 * @return The value, or the default value if the section or key does not exist.
-	 * @throws ParseException Malformed input encountered.
-	 */
-	public OMap getMap(String key, OMap def) throws ParseException {
-		return getObjectWithDefault(key, def, OMap.class);
-	}
-
-	/**
-	 * Convenience method for returning a config entry as an {@link OList}.
-	 *
-	 * @param key The key.
-	 * @return The value, or <jk>null</jk> if the section or key does not exist.
-	 * @throws ParseException Malformed input encountered.
-	 */
-	public OList getList(String key) throws ParseException {
-		return getObject(key, OList.class);
-	}
-
-	/**
-	 * Convenience method for returning a config entry as an {@link OList}.
-	 *
-	 * @param key The key.
-	 * @param def The default value.
-	 * @return The value, or the default value if the section or key does not exist.
-	 * @throws ParseException Malformed input encountered.
-	 */
-	public OList getList(String key, OList def) throws ParseException {
-		return getObjectWithDefault(key, def, OList.class);
+	public Entry get(String key) {
+		return new Entry(this, configMap, sname(key), skey(key));
 	}
 
 	/**
@@ -1471,7 +928,7 @@ public final class Config extends Context implements ConfigEventListener {
 				if (! ignoreUnknownProperties)
 					throw new ParseException("Unknown property ''{0}'' encountered in configuration section ''{1}''.", k, section);
 			} else {
-				bm.put(k, getObject(section + '/' + k, bpm.getClassMeta().getInnerClass()));
+				bm.put(k, get(section + '/' + k).as(bpm.getClassMeta().getInnerClass()).orElse(null));
 			}
 		}
 
@@ -1551,7 +1008,7 @@ public final class Config extends Context implements ConfigEventListener {
 				if (! ignoreUnknownProperties)
 					throw new ParseException("Unknown property ''{0}'' encountered in configuration section ''{1}''.", k, section);
 			} else {
-				bm.put(k, getObject(section + '/' + k, bpm.getClassMeta().getInnerClass()));
+				bm.put(k, get(section + '/' + k).as(bpm.getClassMeta().getInnerClass()).orElse(null));
 			}
 		}
 
@@ -1578,7 +1035,7 @@ public final class Config extends Context implements ConfigEventListener {
 
 		OMap om = new OMap();
 		for (String k : keys)
-			om.put(k, getObject(section + '/' + k, Object.class));
+			om.put(k, get(section + '/' + k).as(Object.class).orElse(null));
 		return om;
 	}
 
@@ -1670,7 +1127,7 @@ public final class Config extends Context implements ConfigEventListener {
 				for (PropertyDescriptor pd : bi.getPropertyDescriptors()) {
 					Method rm = pd.getReadMethod(), wm = pd.getWriteMethod();
 					if (method.equals(rm))
-						return Config.this.getObject(section2 + '/' + pd.getName(), rm.getGenericReturnType());
+						return Config.this.get(section2 + '/' + pd.getName()).to(rm.getGenericReturnType());
 					if (method.equals(wm))
 						return Config.this.set(section2 + '/' + pd.getName(), args[0]);
 				}
@@ -1688,7 +1145,7 @@ public final class Config extends Context implements ConfigEventListener {
 	 * @return <jk>true</jk> if this section contains the specified key and the key has a non-blank value.
 	 */
 	public boolean exists(String key) {
-		return isNotEmpty(getString(key, null));
+		return isNotEmpty(get(key).as(String.class).orElse(null));
 	}
 
 	/**
@@ -2000,43 +1457,6 @@ public final class Config extends Context implements ConfigEventListener {
 		return s;
 	}
 
-	@SuppressWarnings({ "unchecked" })
-	private <T> T parse(String s, Parser parser, Type type, Type...args) throws ParseException {
-
-		if (isEmpty(s))
-			return null;
-
-		if (isSimpleType(type))
-			return (T)beanSession.convertToType(s, (Class<?>)type);
-
-		if (type == byte[].class) {
-			if (s.indexOf('\n') != -1)
-				s = s.replaceAll("\n", "");
-			try {
-				switch (binaryFormat) {
-					case HEX: return (T)fromHex(s);
-					case SPACED_HEX: return (T)fromSpacedHex(s);
-					default: return (T)base64Decode(s);
-				}
-			} catch (Exception e) {
-				throw new ParseException(e, "Value could not be converted to a byte array.");
-			}
-		}
-
-		if (parser == null)
-			parser = this.parser;
-
-		if (parser instanceof JsonParser) {
-			char s1 = firstNonWhitespaceChar(s);
-			if (isArray(type) && s1 != '[')
-				s = '[' + s + ']';
-			else if (s1 != '[' && s1 != '{' && ! "null".equals(s))
-				s = '\'' + s + '\'';
-		}
-
-		return parser.parse(s, type, args);
-	}
-
 	private boolean isSimpleType(Type t) {
 		if (! (t instanceof Class))
 			return false;
@@ -2044,13 +1464,6 @@ public final class Config extends Context implements ConfigEventListener {
 		return (c == String.class || c.isPrimitive() || c.isAssignableFrom(Number.class) || c == Boolean.class || c.isEnum());
 	}
 
-	private boolean isArray(Type t) {
-		if (! (t instanceof Class))
-			return false;
-		Class<?> c = (Class<?>)t;
-		return (c.isArray());
-	}
-
 	private String sname(String key) {
 		assertArgNotNull("key", key);
 		int i = key.indexOf('/');
@@ -2073,7 +1486,7 @@ public final class Config extends Context implements ConfigEventListener {
 		return section;
 	}
 
-	private void checkWrite() {
+	void checkWrite() {
 		if (readOnly)
 			throw unsupportedOperationException("Cannot call this method on a read-only configuration.");
 	}
diff --git a/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/ConfigMod.java b/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/ConfigMod.java
index b4be485..716091b 100644
--- a/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/ConfigMod.java
+++ b/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/ConfigMod.java
@@ -45,7 +45,7 @@ public enum ConfigMod {
 	 * @param mods The modifiers.
 	 * @return A modifier string, or an empty string if there are no modifiers.
 	 */
-	public static String asString(ConfigMod...mods) {
+	public static String toModString(ConfigMod...mods) {
 		if (mods.length == 0)
 			return "";
 		if (mods.length == 1)
@@ -69,7 +69,7 @@ public enum ConfigMod {
 	 * @param s The modifier string.
 	 * @return The list of modifiers, or an empty list if the string is empty or <jk>null</jk>.
 	 */
-	public static List<ConfigMod> asModifiersReverse(String s) {
+	public static List<ConfigMod> toReverse(String s) {
 		if (isEmpty(s))
 			return Collections.emptyList();
 		if (s.length() == 1) {
@@ -91,7 +91,7 @@ public enum ConfigMod {
 	 * @param s The modifier string.
 	 * @return The list of modifiers, or an empty list if the string is empty or <jk>null</jk>.
 	 */
-	public static List<ConfigMod> asModifiers(String s) {
+	public static List<ConfigMod> toModifiers(String s) {
 		if (isEmpty(s))
 			return Collections.emptyList();
 		if (s.length() == 1) {
diff --git a/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/Entry.java b/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/Entry.java
new file mode 100644
index 0000000..b6eba19
--- /dev/null
+++ b/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/Entry.java
@@ -0,0 +1,872 @@
+// ***************************************************************************************************************************
+// * 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.config;
+
+import static org.apache.juneau.config.ConfigMod.*;
+import static org.apache.juneau.internal.StringUtils.*;
+import static org.apache.juneau.BinaryFormat.*;
+import static java.util.Optional.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.function.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.collections.*;
+import org.apache.juneau.config.internal.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.json.*;
+import org.apache.juneau.parser.*;
+
+/**
+ * A single entry in a {@link Config} file.
+ */
+public class Entry {
+
+	private final ConfigEntry configEntry;
+	private final Config config;
+	private final String value;
+
+	/**
+	 * Constructor.
+	 *
+	 * @param config The config that this entry belongs to.
+	 * @param configMap The map that this belongs to.
+	 * @param sectionName The section name of this entry.
+	 * @param entryName The name of this entry.
+	 */
+	protected Entry(Config config, ConfigMap configMap, String sectionName, String entryName) {
+		this.configEntry = configMap.getEntry(sectionName, entryName);
+		this.config = config;
+
+		String v = null;
+		if (configEntry != null) {
+			v = configEntry.getValue();
+			if (! StringUtils.isEmpty(configEntry.getModifiers()))
+				for (ConfigMod m : ConfigMod.toReverse(configEntry.getModifiers()))
+					if (m == ENCODED)
+						if (config.encoder.isEncoded(v))
+							v = config.encoder.decode(configEntry.getKey(), v);
+		}
+		this.value = v;
+	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// Value retrievers
+	//-----------------------------------------------------------------------------------------------------------------
+
+	/**
+	 * Returns <jk>true</jk> if this entry exists in the config.
+	 *
+	 * @return <jk>true</jk> if this entry exists in the config.
+	 */
+	public boolean isPresent() {
+		return ! isNull();
+	}
+
+	/**
+	 * Returns <jk>true</jk> if this entry exists in the config and is not empty.
+	 *
+	 * @return <jk>true</jk> if this entry exists in the config and is not empty.
+	 */
+	public boolean isNotEmpty() {
+		return ! isEmpty();
+	}
+
+	/**
+	 * Returns this entry as a string.
+	 *
+	 * @return <jk>true</jk> if this entry exists in the config and is not empty.
+	 * @throws NullPointerException if value was <jk>null</jk>.
+	 */
+	public String get() {
+		if (isNull()) throw new NullPointerException("Value was null");
+		return toString();
+	}
+
+	/**
+	 * Returns this entry converted to the specified type.
+	 *
+	 * @param type The type to convert the value to.
+	 * @return This entry converted to the specified type.
+	 */
+	public <T> Optional<T> as(Class<T> type) {
+		return ofNullable(to((Type)type));
+	}
+
+	/**
+	 * Returns this entry converted to the specified type.
+	 *
+	 * @param parser The parser to use to parse the entry value.
+	 * @param type The type to convert the value to.
+	 * @return This entry converted to the specified type.
+	 */
+	public <T> Optional<T> as(Parser parser, Class<T> type) {
+		return ofNullable(to(parser, (Type)type));
+	}
+
+	/**
+	 * Returns this entry converted to the specified type or returns the default value.
+	 *
+	 * <p>
+	 * This is equivalent to calling <c>as(<jv>def</jv>.getClass()).orElse(<jv>def</jv>)</c> but is simpler and
+	 * avoids the creation of an {@link Optional} object.
+	 *
+	 * @param def The default value to return if value does not exist.
+	 * @return This entry converted to the specified type or returns the default value.
+	 */
+	public String orElse(String def) {
+		return isNull() ? def : get();
+	}
+
+	/**
+	 * Returns this entry converted to the specified type or returns the default value.
+	 *
+	 * <p>
+	 * This is equivalent to calling <c>as(<jv>def</jv>.getClass()).orElse(<jv>def</jv>)</c> but is simpler and
+	 * avoids the creation of an {@link Optional} object.
+	 *
+	 * @param def The default value to return if value does not exist.
+	 * @return This entry converted to the specified type or returns the default value.
+	 */
+	public String orElseGet(Supplier<String> def) {
+		return isNull() ? def.get() : get();
+	}
+
+	/**
+	 * Returns this entry converted to the specified type.
+	 *
+	 * @param type The type to convert the value to.
+	 * @return This entry converted to the specified type.
+	 */
+	public <T> T to(Class<T> type) {
+		return to((Type)type);
+	}
+
+	/**
+	 * Returns this entry converted to the specified value.
+	 *
+	 * <p>
+	 * The type can be a simple type (e.g. beans, strings, numbers) or parameterized type (collections/maps).
+	 *
+	 * <h5 class='section'>Examples:</h5>
+	 * <p class='bcode w800'>
+	 * 	Config cf = Config.<jsm>create</jsm>().name(<js>"MyConfig.cfg"</js>).build();
+	 *
+	 * 	<jc>// Parse into a linked-list of strings.</jc>
+	 * 	List l = cf.get(<js>"MySection/myListOfStrings"</js>).to(LinkedList.<jk>class</jk>, String.<jk>class</jk>);
+	 *
+	 * 	<jc>// Parse into a linked-list of beans.</jc>
+	 * 	List l = cf.get(<js>"MySection/myListOfBeans"</js>).to(LinkedList.<jk>class</jk>, MyBean.<jk>class</jk>);
+	 *
+	 * 	<jc>// Parse into a linked-list of linked-lists of strings.</jc>
+	 * 	List l = cf.get(<js>"MySection/my2dListOfStrings"</js>).to(LinkedList.<jk>class</jk>,
+	 * 		LinkedList.<jk>class</jk>, String.<jk>class</jk>);
+	 *
+	 * 	<jc>// Parse into a map of string keys/values.</jc>
+	 * 	Map m = cf.get(<js>"MySection/myMap"</js>).to(TreeMap.<jk>class</jk>, String.<jk>class</jk>,
+	 * 		String.<jk>class</jk>);
+	 *
+	 * 	<jc>// Parse into a map containing string keys and values of lists containing beans.</jc>
+	 * 	Map m = cf.get(<js>"MySection/myMapOfListsOfBeans"</js>).to(TreeMap.<jk>class</jk>, String.<jk>class</jk>,
+	 * 		List.<jk>class</jk>, MyBean.<jk>class</jk>);
+	 * </p>
+	 *
+	 * <p>
+	 * <c>Collection</c> classes are assumed to be followed by zero or one objects indicating the element type.
+	 *
+	 * <p>
+	 * <c>Map</c> classes are assumed to be followed by zero or two meta objects indicating the key and value
+	 * types.
+	 *
+	 * <p>
+	 * The array can be arbitrarily long to indicate arbitrarily complex data structures.
+	 *
+	 * <ul class='notes'>
+	 * 	<li>
+	 * 		Use the {@link #to(Class)} method instead if you don't need a parameterized map/collection.
+	 * </ul>
+	 *
+	 * @param type
+	 * 	The object type to create.
+	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
+	 * @param args
+	 * 	The type arguments of the class if it's a collection or map.
+	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
+	 * 	<br>Ignored if the main type is not a map or collection.
+	 * @return The value, or <jk>null</jk> if the section or key does not exist.
+	 */
+	public <T> T to(Type type, Type...args) {
+		return to(config.parser, type, args);
+	}
+
+	/**
+	 * Returns this entry converted to the specified value.
+	 *
+	 * <p>
+	 * The type can be a simple type (e.g. beans, strings, numbers) or parameterized type (collections/maps).
+	 *
+	 * <h5 class='section'>Examples:</h5>
+	 * <p class='bcode w800'>
+	 * 	Config cf = Config.<jsm>create</jsm>().name(<js>"MyConfig.cfg"</js>).build();
+	 *
+	 * 	<jc>// Parse into a linked-list of strings.</jc>
+	 * 	List l = cf.get(<js>"MySection/myListOfStrings"</js>).to(LinkedList.<jk>class</jk>, String.<jk>class</jk>);
+	 *
+	 * 	<jc>// Parse into a linked-list of beans.</jc>
+	 * 	List l = cf.get(<js>"MySection/myListOfBeans"</js>).to(LinkedList.<jk>class</jk>, MyBean.<jk>class</jk>);
+	 *
+	 * 	<jc>// Parse into a linked-list of linked-lists of strings.</jc>
+	 * 	List l = cf.get(<js>"MySection/my2dListOfStrings"</js>).to(LinkedList.<jk>class</jk>,
+	 * 		LinkedList.<jk>class</jk>, String.<jk>class</jk>);
+	 *
+	 * 	<jc>// Parse into a map of string keys/values.</jc>
+	 * 	Map m = cf.get(<js>"MySection/myMap"</js>).to(TreeMap.<jk>class</jk>, String.<jk>class</jk>,
+	 * 		String.<jk>class</jk>);
+	 *
+	 * 	<jc>// Parse into a map containing string keys and values of lists containing beans.</jc>
+	 * 	Map m = cf.get(<js>"MySection/myMapOfListsOfBeans"</js>).to(TreeMap.<jk>class</jk>, String.<jk>class</jk>,
+	 * 		List.<jk>class</jk>, MyBean.<jk>class</jk>);
+	 * </p>
+	 *
+	 * <p>
+	 * <c>Collection</c> classes are assumed to be followed by zero or one objects indicating the element type.
+	 *
+	 * <p>
+	 * <c>Map</c> classes are assumed to be followed by zero or two meta objects indicating the key and value
+	 * types.
+	 *
+	 * <p>
+	 * The array can be arbitrarily long to indicate arbitrarily complex data structures.
+	 *
+	 * <ul class='notes'>
+	 * 	<li>
+	 * 		Use the {@link #to(Class)} method instead if you don't need a parameterized map/collection.
+	 * </ul>
+	 *
+	 * @param type
+	 * 	The object type to create.
+	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
+	 * @param args
+	 * 	The type arguments of the class if it's a collection or map.
+	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
+	 * 	<br>Ignored if the main type is not a map or collection.
+	 * @return The value, or {@link Optional#empty()} if the section or key does not exist.
+	 */
+	public <T> Optional<T> as(Type type, Type...args) {
+		return ofNullable(to(type, args));
+	}
+
+	/**
+	 * Same as {@link #to(Type, Type...)} but specifies the parser to use to parse the entry.
+	 *
+	 * @param parser
+	 * 	The parser to use to parse the entry.
+	 * @param type
+	 * 	The object type to create.
+	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
+	 * @param args
+	 * 	The type arguments of the class if it's a collection or map.
+	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
+	 * 	<br>Ignored if the main type is not a map or collection.
+	 * @return The value, or <jk>null</jk> if the section or key does not exist.
+	 */
+	@SuppressWarnings("unchecked")
+	public <T> T to(Parser parser, Type type, Type...args) {
+		if (isNull()) return null;
+
+		try {
+			String v = toString();
+			if (type == String.class) return (T)toString();
+			if (type == String[].class) return (T)toStringArray();
+			if (type == byte[].class) return (T)toBytes();
+			if (type == int.class) return (T)toInteger();
+			if (type == int.class || type == Integer.class) return (T)toInteger();
+			if (type == long.class || type == Long.class) return (T)toLong();
+			if (type == OMap.class) return (T)toMap();
+			if (type == OList.class) return (T)toList();
+			if (isEmpty()) return null;
+			if (isSimpleType(type)) return (T)config.beanSession.convertToType(v, (Class<?>)type);
+
+			if (parser instanceof JsonParser) {
+				char s1 = firstNonWhitespaceChar(v);
+				if (isArray(type) && s1 != '[')
+					v = '[' + v + ']';
+				else if (s1 != '[' && s1 != '{' && ! "null".equals(v))
+					v = '\'' + v + '\'';
+			}
+			return parser.parse(v, type, args);
+		} catch (ParseException e) {
+			throw new BeanRuntimeException(e, null, "Value could not be parsed.");
+		}
+	}
+
+	/**
+	 * Same as {@link #as(Type, Type...)} but specifies the parser to use to parse the entry.
+	 *
+	 * @param parser
+	 * 	The parser to use to parse the entry.
+	 * @param type
+	 * 	The object type to create.
+	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
+	 * @param args
+	 * 	The type arguments of the class if it's a collection or map.
+	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
+	 * 	<br>Ignored if the main type is not a map or collection.
+	 * @return The value, or {@link Optional#empty()} if the section or key does not exist.
+	 */
+	public <T> Optional<T> as(Parser parser, Type type, Type...args) {
+		return ofNullable(to(parser, type, args));
+	}
+
+	/**
+	 * Returns this entry as a string.
+	 *
+	 * @return This entry as a string, or <jk>null</jk> if the entry does not exist.
+	 */
+ 	@Override
+	public String toString() {
+ 		return isPresent() ? config.varSession.resolve(value) : null;
+	}
+
+	/**
+	 * Returns this entry as a string.
+	 *
+	 * @return This entry as a string, or {@link Optional#empty()} if the entry does not exist.
+	 */
+	public Optional<String> asString() {
+ 		return ofNullable(toString());
+	}
+
+ 	/**
+	 * Returns this entry as a string array.
+	 *
+	 * <p>
+	 * If the value exists, splits the value on commas and returns the values as trimmed strings.
+	 *
+	 * @return This entry as a string array, or <jk>null</jk> if the entry does not exist.
+	 */
+	public String[] toStringArray() {
+		if (! isPresent()) return null;
+		String v = toString();
+		char s1 = firstNonWhitespaceChar(v), s2 = lastNonWhitespaceChar(v);
+		if (s1 == '[' && s2 == ']' && config.parser instanceof JsonParser) {
+			try {
+				return config.parser.parse(v, String[].class);
+			} catch (ParseException e) {
+				throw new BeanRuntimeException(e);
+			}
+		}
+		return split(v);
+	}
+
+	/**
+	 * Returns this entry as a string array.
+	 *
+	 * <p>
+	 * If the value exists, splits the value on commas and returns the values as trimmed strings.
+	 *
+	 * @return This entry as a string array, or {@link Optional#empty()} if the entry does not exist.
+	 */
+	public Optional<String[]> asStringArray() {
+		return ofNullable(toStringArray());
+	}
+
+	/**
+	 * Returns this entry as an integer.
+	 *
+	 * <p>
+	 * <js>"K"</js>, <js>"M"</js>, and <js>"G"</js> can be used to identify kilo, mega, and giga in base 2.
+	 * <br><js>"k"</js>, <js>"m"</js>, and <js>"g"</js> can be used to identify kilo, mega, and giga in base 10.
+	 *
+	 * <h5 class='section'>Example:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		<code><js>"100K"</js> => 1024000</code>
+	 * 	<li>
+	 * 		<code><js>"100M"</js> => 104857600</code>
+	 * 	<li>
+	 * 		<code><js>"100k"</js> => 1000000</code>
+	 * 	<li>
+	 * 		<code><js>"100m"</js> => 100000000</code>
+	 * </ul>
+	 *
+	 * <p>
+	 * Uses {@link Integer#decode(String)} underneath, so any of the following integer formats are supported:
+	 * <ul>
+	 * 	<li><js>"0x..."</js>
+	 * 	<li><js>"0X..."</js>
+	 * 	<li><js>"#..."</js>
+	 * 	<li><js>"0..."</js>
+	 * </ul>
+	 *
+	 * @return The value, or <jk>null</jk> if the value does not exist or the value is empty.
+	 */
+	public Integer toInteger() {
+		return isNotEmpty() ? parseIntWithSuffix(toString()) : null;
+	}
+
+	/**
+	 * Returns this entry as an integer.
+	 *
+	 * <p>
+	 * <js>"K"</js>, <js>"M"</js>, and <js>"G"</js> can be used to identify kilo, mega, and giga in base 2.
+	 * <br><js>"k"</js>, <js>"m"</js>, and <js>"g"</js> can be used to identify kilo, mega, and giga in base 10.
+	 *
+	 * <h5 class='section'>Example:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		<code><js>"100K"</js> => 1024000</code>
+	 * 	<li>
+	 * 		<code><js>"100M"</js> => 104857600</code>
+	 * 	<li>
+	 * 		<code><js>"100k"</js> => 1000000</code>
+	 * 	<li>
+	 * 		<code><js>"100m"</js> => 100000000</code>
+	 * </ul>
+	 *
+	 * <p>
+	 * Uses {@link Integer#decode(String)} underneath, so any of the following integer formats are supported:
+	 * <ul>
+	 * 	<li><js>"0x..."</js>
+	 * 	<li><js>"0X..."</js>
+	 * 	<li><js>"#..."</js>
+	 * 	<li><js>"0..."</js>
+	 * </ul>
+	 *
+	 * @return The value, or {@link Optional#empty()} if the value does not exist or the value is empty.
+	 */
+	public Optional<Integer> asInteger() {
+		return ofNullable(toInteger());
+	}
+
+	/**
+	 * Returns this entry as a parsed boolean.
+	 *
+	 * <p>
+	 * Uses {@link Boolean#parseBoolean(String)} to parse value.
+	 *
+	 * @return The value, or <jk>null</jk> if the value does not exist or the value is empty.
+	 */
+	public Boolean toBoolean() {
+		return isNotEmpty() ? Boolean.parseBoolean(toString()) : null;
+	}
+
+	/**
+	 * Returns this entry as a parsed boolean.
+	 *
+	 * <p>
+	 * Uses {@link Boolean#parseBoolean(String)} to parse value.
+	 *
+	 * @return The value, or {@link Optional#empty()} if the value does not exist or the value is empty.
+	 */
+	public Optional<Boolean> asBoolean() {
+		return ofNullable(toBoolean());
+	}
+
+	/**
+	 * Returns this entry as a long.
+	 *
+	 * <p>
+	 * <js>"K"</js>, <js>"M"</js>, <js>"G"</js>, <js>"T"</js>, and <js>"P"</js> can be used to identify kilo, mega, giga, tera, and penta in base 2.
+	 * <br><js>"k"</js>, <js>"m"</js>, <js>"g"</js>, <js>"t"</js>, and <js>"p"</js> can be used to identify kilo, mega, giga, tera, and p in base 10.
+	 *
+	 * <h5 class='section'>Example:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		<code><js>"100K"</js> => 1024000</code>
+	 * 	<li>
+	 * 		<code><js>"100M"</js> => 104857600</code>
+	 * 	<li>
+	 * 		<code><js>"100k"</js> => 1000000</code>
+	 * 	<li>
+	 * 		<code><js>"100m"</js> => 100000000</code>
+	 * </ul>
+	 *
+	 * <p>
+	 * Uses {@link Long#decode(String)} underneath, so any of the following integer formats are supported:
+	 * <ul>
+	 * 	<li><js>"0x..."</js>
+	 * 	<li><js>"0X..."</js>
+	 * 	<li><js>"#..."</js>
+	 * 	<li><js>"0..."</js>
+	 * </ul>
+	 *
+	 * @return The value, or <jk>null</jk> if the value does not exist or the value is empty.
+	 */
+	public Long toLong() {
+		return isNotEmpty() ? parseLongWithSuffix(toString()) : null;
+	}
+
+	/**
+	 * Returns this entry as a long.
+	 *
+	 * <p>
+	 * <js>"K"</js>, <js>"M"</js>, <js>"G"</js>, <js>"T"</js>, and <js>"P"</js> can be used to identify kilo, mega, giga, tera, and penta in base 2.
+	 * <br><js>"k"</js>, <js>"m"</js>, <js>"g"</js>, <js>"t"</js>, and <js>"p"</js> can be used to identify kilo, mega, giga, tera, and p in base 10.
+	 *
+	 * <h5 class='section'>Example:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		<code><js>"100K"</js> => 1024000</code>
+	 * 	<li>
+	 * 		<code><js>"100M"</js> => 104857600</code>
+	 * 	<li>
+	 * 		<code><js>"100k"</js> => 1000000</code>
+	 * 	<li>
+	 * 		<code><js>"100m"</js> => 100000000</code>
+	 * </ul>
+	 *
+	 * <p>
+	 * Uses {@link Long#decode(String)} underneath, so any of the following integer formats are supported:
+	 * <ul>
+	 * 	<li><js>"0x..."</js>
+	 * 	<li><js>"0X..."</js>
+	 * 	<li><js>"#..."</js>
+	 * 	<li><js>"0..."</js>
+	 * </ul>
+	 *
+	 * @return The value, or {@link Optional#empty()} if the value does not exist or the value is empty.
+	 */
+	public Optional<Long> asLong() {
+		return ofNullable(toLong());
+	}
+
+	/**
+	 * Returns this entry as a double.
+	 *
+	 * <p>
+	 * Uses {@link Double#valueOf(String)} underneath, so any of the following number formats are supported:
+	 * <ul>
+	 * 	<li><js>"0x..."</js>
+	 * 	<li><js>"0X..."</js>
+	 * 	<li><js>"#..."</js>
+	 * 	<li><js>"0..."</js>
+	 * </ul>
+	 *
+	 * @return The value, or <jk>null</jk> if the value does not exist or the value is empty.
+	 */
+	public Double toDouble() {
+		return isNotEmpty() ? Double.valueOf(toString()) : null;
+	}
+
+	/**
+	 * Returns this entry as a double.
+	 *
+	 * <p>
+	 * Uses {@link Double#valueOf(String)} underneath, so any of the following number formats are supported:
+	 * <ul>
+	 * 	<li><js>"0x..."</js>
+	 * 	<li><js>"0X..."</js>
+	 * 	<li><js>"#..."</js>
+	 * 	<li><js>"0..."</js>
+	 * </ul>
+	 *
+	 * @return The value, or {@link Optional#empty()} if the value does not exist or the value is empty.
+	 */
+	public Optional<Double> asDouble() {
+		return ofNullable(toDouble());
+	}
+
+	/**
+	 * Returns this entry as a float.
+	 *
+	 * <p>
+	 * Uses {@link Float#valueOf(String)} underneath, so any of the following number formats are supported:
+	 * <ul>
+	 * 	<li><js>"0x..."</js>
+	 * 	<li><js>"0X..."</js>
+	 * 	<li><js>"#..."</js>
+	 * 	<li><js>"0..."</js>
+	 * </ul>
+	 *
+	 * @return The value, or <jk>null</jk> if the value does not exist or the value is empty.
+	 */
+	public Float toFloat() {
+		return isNotEmpty() ? Float.valueOf(toString()) : null;
+	}
+
+	/**
+	 * Returns this entry as a float.
+	 *
+	 * <p>
+	 * Uses {@link Float#valueOf(String)} underneath, so any of the following number formats are supported:
+	 * <ul>
+	 * 	<li><js>"0x..."</js>
+	 * 	<li><js>"0X..."</js>
+	 * 	<li><js>"#..."</js>
+	 * 	<li><js>"0..."</js>
+	 * </ul>
+	 *
+	 * @return The value, or {@link Optional#empty()} if the value does not exist or the value is empty.
+	 */
+	public Optional<Float> asFloat() {
+		return ofNullable(toFloat());
+	}
+
+	/**
+	 * Returns this entry as a byte array.
+	 *
+	 * <p>
+	 * Byte arrays are stored as encoded strings, typically BASE64, but dependent on the {@link Config.Builder#binaryFormat(BinaryFormat)} setting.
+	 *
+	 * @return The value, or <jk>null</jk> if the section or key does not exist.
+	 */
+	public byte[] toBytes() {
+		if (isNull()) return null;
+		String s = toString();
+		if (s.indexOf('\n') != -1) s = s.replaceAll("\n", "");
+		try {
+			if (config.binaryFormat == HEX)
+				return fromHex(s);
+			if (config.binaryFormat == SPACED_HEX)
+				return fromSpacedHex(s);
+			return base64Decode(s);
+		} catch (Exception e) {
+			throw new BeanRuntimeException(e, null, "Value could not be converted to a byte array.");
+		}
+	}
+
+	/**
+	 * Returns this entry as a byte array.
+	 *
+	 * <p>
+	 * Byte arrays are stored as encoded strings, typically BASE64, but dependent on the {@link Config.Builder#binaryFormat(BinaryFormat)} setting.
+	 *
+	 * @return The value, or {@link Optional#empty()} if the section or key does not exist.
+	 */
+	public Optional<byte[]> asBytes() {
+		return ofNullable(toBytes());
+	}
+
+	/**
+	 * Returns this entry as a parsed map.
+	 *
+	 * <p>
+	 * Uses the parser registered on the {@link Config} to parse the entry.
+	 *
+	 * <p>
+	 * If the parser is a JSON parser, the starting/trailing <js>"{"</js>/<js>"}"</js> in the value are optional.
+	 *
+	 * @return The value, or <jk>null</jk> if the section or key does not exist.
+	 * @throws ParseException If value could not be parsed.
+	 */
+	public OMap toMap() throws ParseException {
+		return toMap(null);
+	}
+
+	/**
+	 * Returns this entry as a parsed map.
+	 *
+	 * <p>
+	 * Uses the parser registered on the {@link Config} to parse the entry.
+	 *
+	 * <p>
+	 * If the parser is a JSON parser, the starting/trailing <js>"{"</js>/<js>"}"</js> in the value are optional.
+	 *
+	 * @return The value, or {@link Optional#empty()} if the section or key does not exist.
+	 * @throws ParseException If value could not be parsed.
+	 */
+	public Optional<OMap> asMap() throws ParseException {
+		return ofNullable(toMap());
+	}
+
+	/**
+	 * Returns this entry as a parsed map.
+	 *
+	 * <p>
+	 * If the parser is a JSON parser, the starting/trailing <js>"{"</js>/<js>"}"</js> in the value are optional.
+	 *
+	 * @param parser The parser to use to parse the value, or <jk>null</jk> to use the parser defined on the config.
+	 * @return The value, or <jk>null</jk> if the section or key does not exist.
+	 * @throws ParseException If value could not be parsed.
+	 */
+	public OMap toMap(Parser parser) throws ParseException {
+		if (isNull()) return null;
+		if (parser == null) parser = config.parser;
+		String s = toString();
+		if (parser instanceof JsonParser) {
+			char s1 = firstNonWhitespaceChar(s);
+			if (s1 != '{' && ! "null".equals(s))
+				s = '{' + s + '}';
+		}
+		return OMap.ofText(s, parser);
+	}
+
+	/**
+	 * Returns this entry as a parsed map.
+	 *
+	 * <p>
+	 * If the parser is a JSON parser, the starting/trailing <js>"{"</js>/<js>"}"</js> in the value are optional.
+	 *
+	 * @param parser The parser to use to parse the value, or {@link Optional#empty()} to use the parser defined on the config.
+	 * @return The value, or <jk>null</jk> if the section or key does not exist.
+	 * @throws ParseException If value could not be parsed.
+	 */
+	public Optional<OMap> asMap(Parser parser) throws ParseException {
+		return ofNullable(toMap(parser));
+	}
+
+	/**
+	 * Returns this entry as a parsed list.
+	 *
+	 * <p>
+	 * Uses the parser registered on the {@link Config} to parse the entry.
+	 *
+	 * <p>
+	 * If the parser is a JSON parser, the starting/trailing <js>"["</js>/<js>"]"</js> in the value are optional.
+	 *
+	 * @return The value, or <jk>null</jk> if the section or key does not exist.
+	 * @throws ParseException If value could not be parsed.
+	 */
+	public OList toList() throws ParseException {
+		return toList(config.parser);
+	}
+
+	/**
+	 * Returns this entry as a parsed list.
+	 *
+	 * <p>
+	 * Uses the parser registered on the {@link Config} to parse the entry.
+	 *
+	 * <p>
+	 * If the parser is a JSON parser, the starting/trailing <js>"["</js>/<js>"]"</js> in the value are optional.
+	 *
+	 * @return The value, or {@link Optional#empty()} if the section or key does not exist.
+	 * @throws ParseException If value could not be parsed.
+	 */
+	public Optional<OList> asList() throws ParseException {
+		return ofNullable(toList());
+	}
+
+	/**
+	 * Returns this entry as a parsed list.
+	 *
+	 * <p>
+	 * If the parser is a JSON parser, the starting/trailing <js>"["</js>/<js>"]"</js> in the value are optional.
+	 *
+	 * @param parser The parser to use to parse the value, or {@link Optional#empty()} to use the parser defined on the config.
+	 * @return The value, or <jk>null</jk> if the section or key does not exist.
+	 * @throws ParseException If value could not be parsed.
+	 */
+	public OList toList(Parser parser) throws ParseException {
+		if (isNull()) return null;
+		if (parser == null) parser = config.parser;
+		String s = toString();
+		if (parser instanceof JsonParser) {
+			char s1 = firstNonWhitespaceChar(s);
+			if (s1 != '[' && ! "null".equals(s))
+				s = '[' + s + ']';
+		}
+		return OList.ofText(s, parser);
+	}
+
+	/**
+	 * Returns this entry as a parsed list.
+	 *
+	 * <p>
+	 * If the parser is a JSON parser, the starting/trailing <js>"["</js>/<js>"]"</js> in the value are optional.
+	 *
+	 * @param parser The parser to use to parse the value, or {@link Optional#empty()} to use the parser defined on the config.
+	 * @return The value, or {@link Optional#empty()} if the section or key does not exist.
+	 * @throws ParseException If value could not be parsed.
+	 */
+	public Optional<OList> asList(Parser parser) throws ParseException {
+		return ofNullable(toList(parser));
+	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// Metadata retrievers
+	//-----------------------------------------------------------------------------------------------------------------
+
+	/**
+	 * Returns the name of this entry.
+	 *
+	 * @return The name of this entry.
+	 */
+	public String getKey() {
+		return configEntry.getKey();
+	}
+
+	/**
+	 * Returns the raw value of this entry.
+	 *
+	 * @return The raw value of this entry.
+	 */
+	public String getValue() {
+		return configEntry.getValue();
+	}
+
+	/**
+	 * Returns the same-line comment of this entry.
+	 *
+	 * @return The same-line comment of this entry.
+	 */
+	public String getComment() {
+		return configEntry.getComment();
+	}
+
+	/**
+	 * Returns the pre-lines of this entry.
+	 *
+	 * @return The pre-lines of this entry as an unmodifiable list.
+	 */
+	public List<String> getPreLines() {
+		return configEntry.getPreLines();
+	}
+
+	/**
+	 * Returns whether this entry has the specified modifier.
+	 *
+	 * @param m The modifier character.
+	 * @return <jk>true</jk> if this entry is encoded.
+	 */
+	public boolean hasModifier(char m) {
+		return configEntry.hasModifier(m);
+	}
+
+	/**
+	 * Returns the modifiers for this entry.
+	 *
+	 * @return The modifiers for this entry, or an empty string if it has no modifiers.
+	 */
+	public String getModifiers() {
+		return configEntry.getModifiers();
+	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// Helper methods
+	//-----------------------------------------------------------------------------------------------------------------
+
+	private boolean isEmpty() {
+		return StringUtils.isEmpty(value);
+	}
+
+	private boolean isNull() {
+		return value == null;
+	}
+
+	private boolean isArray(Type t) {
+		if (! (t instanceof Class))
+			return false;
+		Class<?> c = (Class<?>)t;
+		return (c.isArray());
+	}
+
+	private boolean isSimpleType(Type t) {
+		if (! (t instanceof Class))
+			return false;
+		Class<?> c = (Class<?>)t;
+		return (c == String.class || c.isPrimitive() || c.isAssignableFrom(Number.class) || c == Boolean.class || c.isEnum());
+	}
+}
diff --git a/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/internal/ConfigEntry.java b/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/internal/ConfigEntry.java
index 8b9faf3..89de958 100644
--- a/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/internal/ConfigEntry.java
+++ b/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/internal/ConfigEntry.java
@@ -81,6 +81,15 @@ public class ConfigEntry {
 	}
 
 	/**
+	 * Returns the name of this entry.
+	 *
+	 * @return The name of this entry.
+	 */
+	public String getKey() {
+		return key;
+	}
+
+	/**
 	 * Returns the raw value of this entry.
 	 *
 	 * @return The raw value of this entry.
diff --git a/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/internal/package-info.java b/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/internal/package-info.java
deleted file mode 100755
index e04991d..0000000
--- a/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/internal/package-info.java
+++ /dev/null
@@ -1,18 +0,0 @@
-// ***************************************************************************************************************************
-// * 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.                                              *
-// ***************************************************************************************************************************
-
-/**
- * Internal Utilities
- */
-package org.apache.juneau.config.internal;
-
diff --git a/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/vars/ConfigVar.java b/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/vars/ConfigVar.java
index 4bc6e4d..1595003 100644
--- a/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/vars/ConfigVar.java
+++ b/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/vars/ConfigVar.java
@@ -20,7 +20,7 @@ import org.apache.juneau.svl.*;
  *
  * <p>
  * The format for this var is <js>"$C{key[,defaultValue]}"</js>.
- * See {@link Config#getString(String)} for the format of the key.
+ * See {@link Config#get(String)} for the format of the key.
  *
  * <p>
  * This variable resolver requires that a {@link Config} bean be available in the resolver session bean factory.
@@ -65,7 +65,7 @@ public class ConfigVar extends DefaultingVar {
 
 	@Override /* Var */
 	public String resolve(VarResolverSession session, String key) {
-		return session.getBean(Config.class).get().getString(key);
+		return session.getBean(Config.class).get().get(key).orElse(null);
 	}
 
 	@Override /* Var */
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java
index 1e7831a..30183d9 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java
@@ -15,6 +15,7 @@ package org.apache.juneau.internal;
 import static org.apache.juneau.assertions.Assertions.*;
 import static org.apache.juneau.internal.ThrowableUtils.*;
 import static org.apache.juneau.internal.IOUtils.*;
+
 import java.io.*;
 import java.lang.reflect.*;
 import java.math.*;
@@ -2279,6 +2280,9 @@ public final class StringUtils {
 	 * 	<li><js>"K"</js> - x 1024
 	 * 	<li><js>"M"</js> - x 1024*1024
 	 * 	<li><js>"G"</js> - x 1024*1024*1024
+	 * 	<li><js>"k"</js> - x 1000
+	 * 	<li><js>"m"</js> - x 1000*1000
+	 * 	<li><js>"g"</js> - x 1000*1000*1000
 	 * </ul>
 	 *
 	 * @param s The string to parse.
@@ -2286,18 +2290,21 @@ public final class StringUtils {
 	 */
 	public static int parseIntWithSuffix(String s) {
 		assertArgNotNull("s", s);
-		int m = 1;
-		if (s.endsWith("G")) {
-			m = 1024*1024*1024;
-			s = s.substring(0, s.length()-1).trim();
-		} else if (s.endsWith("M")) {
-			m = 1024*1024;
-			s = s.substring(0, s.length()-1).trim();
-		} else if (s.endsWith("K")) {
-			m = 1024;
-			s = s.substring(0, s.length()-1).trim();
-		}
-		return Integer.decode(s) * m;
+		int m = multiplier(s);
+		if (m == 1)
+			return Integer.decode(s);
+		return Integer.decode(s.substring(0, s.length()-1).trim()) * m;
+	}
+
+	private static int multiplier(String s) {
+		char c = s.length() == 0 ? null : s.charAt(s.length()-1);
+		if (c == 'G') return 1024*1024*1024;
+		if (c == 'M') return 1024*1024;
+		if (c == 'K') return 1024;
+		if (c == 'g') return 1000*1000*1000;
+		if (c == 'm') return 1000*1000;
+		if (c == 'k') return 1000;
+		return 1;
 	}
 
 	/**
@@ -2309,6 +2316,13 @@ public final class StringUtils {
 	 * 	<li><js>"K"</js> - x 1024
 	 * 	<li><js>"M"</js> - x 1024*1024
 	 * 	<li><js>"G"</js> - x 1024*1024*1024
+	 * 	<li><js>"T"</js> - x 1024*1024*1024*1024
+	 * 	<li><js>"P"</js> - x 1024*1024*1024*1024*1024
+	 * 	<li><js>"k"</js> - x 1000
+	 * 	<li><js>"m"</js> - x 1000*1000
+	 * 	<li><js>"g"</js> - x 1000*1000*1000
+	 * 	<li><js>"t"</js> - x 1000*1000*1000*1000
+	 * 	<li><js>"p"</js> - x 1000*1000*1000*1000*1000
 	 * </ul>
 	 *
 	 * @param s The string to parse.
@@ -2316,18 +2330,25 @@ public final class StringUtils {
 	 */
 	public static long parseLongWithSuffix(String s) {
 		assertArgNotNull("s", s);
-		int m = 1;
-		if (s.endsWith("G")) {
-			m = 1024*1024*1024;
-			s = s.substring(0, s.length()-1).trim();
-		} else if (s.endsWith("M")) {
-			m = 1024*1024;
-			s = s.substring(0, s.length()-1).trim();
-		} else if (s.endsWith("K")) {
-			m = 1024;
-			s = s.substring(0, s.length()-1).trim();
-		}
-		return Long.decode(s) * m;
+		long m = multiplier2(s);
+		if (m == 1)
+			return Long.decode(s);
+		return Long.decode(s.substring(0, s.length()-1).trim()) * m;
+	}
+
+	private static long multiplier2(String s) {
+		char c = s.length() == 0 ? null : s.charAt(s.length()-1);
+		if (c == 'P') return 1024*1024*1024*1024*1024;
+		if (c == 'T') return 1024*1024*1024*1024;
+		if (c == 'G') return 1024*1024*1024;
+		if (c == 'M') return 1024*1024;
+		if (c == 'K') return 1024;
+		if (c == 'p') return 1000*1000*1000*1000*1000;
+		if (c == 't') return 1000*1000*1000*1000;
+		if (c == 'g') return 1000*1000*1000;
+		if (c == 'm') return 1000*1000;
+		if (c == 'k') return 1000;
+		return 1;
 	}
 
 	/**
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/05.jrs.Marshalling.html b/juneau-doc/docs/Topics/06.juneau-rest-server/05.jrs.Marshalling.html
index 4354651..ec056ef 100644
--- a/juneau-doc/docs/Topics/06.juneau-rest-server/05.jrs.Marshalling.html
+++ b/juneau-doc/docs/Topics/06.juneau-rest-server/05.jrs.Marshalling.html
@@ -106,6 +106,31 @@
 		|	}
 	</p>
 	<p>
+		Swaps are associated serializers and parsers registered on a REST resource via the {@link oaj.annotation.BeanConfig} annotation
+		on either the class or method level:
+	</p>
+	<p class='bcode w800'>
+		|	<jc>// Servlet with transforms applied</jc>
+		|	<ja>@Rest</ja>(
+		|		...
+		|	)
+		|	<ja>@BeanConfig</ja>(
+		|		swaps={
+		|			<jc>// Calendars should be serialized/parsed as ISO8601 date-time strings</jc>
+		|			TemporalCalendarSwap.IsoInstant.<jk>class</jk>,
+		|
+		|			<jc>// Byte arrays should be serialized/parsed as BASE64-encoded strings</jc>
+		|			ByteArraySwap.Base64.<jk>class</jk>
+		|		},
+		|		beanFilters={
+		|			<jc>// Subclasses of MyInterface will be treated as MyInterface objects.</jc>
+		|			<jc>// Bean properties not defined on that interface will be ignored.</jc>
+		|			MyInterface.<jk>class</jk>
+		|		}
+		|	)
+		|	<jk>public</jk> MyResource <jk>extends</jk> BasicRestServlet {...}
+	</p>
+	<p>
 		Config annotations are defined for all serializers and parsers:
 	</p>
 	<ul class='javatreec'>
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/09.jrs.Guards.html b/juneau-doc/docs/Topics/06.juneau-rest-server/07.jrs.Guards.html
similarity index 74%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/09.jrs.Guards.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/07.jrs.Guards.html
index 3aae066..c84865e 100644
--- a/juneau-doc/docs/Topics/06.juneau-rest-server/09.jrs.Guards.html
+++ b/juneau-doc/docs/Topics/06.juneau-rest-server/07.jrs.Guards.html
@@ -13,20 +13,24 @@
  ***************************************************************************************************************************/
  -->
 
-{title:'Guards', flags:'todo'}
+{title:'Guards', updated:'9.0.0'}
 
 <div class='topic'>
 	<p>
-		Guards are classes that control access to REST classes and methods.
+		Guards control access to REST classes and methods.
+		When guards are associated at the class-level, it's equivalent to associating guards on all Java methods on 
+		the servlet.
+		If multiple guards are present, ALL guards must pass.  (Note that this is different in behavior to {@doc jrs.Matchers Matchers}
+		which require only one matcher to pass.)
 	</p>
 	<p>
 		Guards are associated with resource classes and methods via the following:
 	</p>
-	<ul class='javatree'>
+	<ul class='javatreec'>
 		<li class='ja'>{@link oajr.annotation.Rest#guards() Rest(guards)} 
 		<li class='ja'>{@link oajr.annotation.RestOp#guards() RestOp(guards)} 
-		<li class='jm'>{@del oajr.RestContext.Builder#guards(Class...)} 
 	</ul>
+	<h5 class='figure'>Example:</h5>
 	<p class='bcode w800'>
 		|	<jc>// Define a guard that only lets Billy make a request</jc>
 		|	<jk>public</jk> BillyGuard <jk>extends</jk> RestGuard {
@@ -51,7 +55,7 @@
 	</p>
 	<p class='bcode w800'>
 		|	<jc>// DELETE method</jc>
-		|	<ja>@RestDDelete</ja>(guards={AdminGuard.<jk>class</jk>})
+		|	<ja>@RestDelete</ja>(guards={AdminGuard.<jk>class</jk>})
 		|	<jk>public void</jk> doDelete(RestRequest <jv>req</jv>, RestResponse <jv>res</jv>) <jk>throws</jk> Exception {...}
 	</p>
 	<p class='bcode w800'>
@@ -65,7 +69,7 @@
 	</p>
 	<p>
 		A guard failure results in an <l>HTTP 401 Unauthorized</l> response.
-		However, this can be configured by overriding the 
+		However, this can be configured by overriding 
 		{@link oajr.guard.RestGuard#guard(RestRequest,RestResponse)} and processing the response 
 		yourself.
 	</p>
@@ -73,19 +77,29 @@
 		|	<jk>public class</jk> AdminGuard <jk>extends</jk> RestGuard {
 		|
 		|		<ja>@Override</ja> <jc>/* RestGuard */</jc>
-		|		<jk>public boolean</jk> guard(RestRequest <jv>req</jv>, RestResponse <jv>res</jv>) <jk>throws</jk> RestException {
+		|		<jk>public boolean</jk> guard(RestRequest <jv>req</jv>, RestResponse <jv>res</jv>) <jk>throws</jk> BasicHttpException {
 		|			<jk>if</jk> (! isOkay(req))
-		|				<jk>throw new</jk> RestException(<jsf>SC_FORBIDDEN</jsf>, <js>"Access denied!!!"</js>);
+		|				<jk>throw new</jk> Forbidden(<js>"Access denied!!!"</js>);
 		|			<jk>return true</jk>;
 		|		}
 		|	}
 	</p>
 	<p>
-		When guards are associated at the class-level, it's equivalent to associating guards on all Java methods on 
-		the servlet.
-		If multiple guards are present, ALL guards must pass.
+		A simplified format is available for matching based on the user role on the request using the following:
 	</p>
-	<ul class='seealso'>
-		<li class='jf'>{@del oajr.RestContext#REST_guards}
+	
+	<ul class='javatreec'>
+		<li class='ja'>{@link oajr.annotation.Rest#roleGuard() Rest(roleGuard)} 
+		<li class='ja'>{@link oajr.annotation.RestOp#roleGuard() RestOp(roleGuard)} 
 	</ul>
+	<h5 class='figure'>Example:</h5>
+	<p class='bcode w800'>
+	|	<ja>@Rest</ja>(
+	|		path=<js>"/foo"</js>,
+	|		roleGuard=<js>"ROLE_ADMIN || (ROLE_READ_WRITE &amp;&amp; ROLE_SPECIAL)"</js>
+	|	)
+	|	<jk>public class</jk> MyResource <jk>extends</jk> RestServlet {
+	|		...
+	|	}
+	</p>
 </div>
\ No newline at end of file
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/07.jrs.Transforms.html b/juneau-doc/docs/Topics/06.juneau-rest-server/07.jrs.Transforms.html
deleted file mode 100644
index 56ce1f8..0000000
--- a/juneau-doc/docs/Topics/06.juneau-rest-server/07.jrs.Transforms.html
+++ /dev/null
@@ -1,72 +0,0 @@
-<!--
-/***************************************************************************************************************************
- * 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.
- ***************************************************************************************************************************/
- -->
-
-{title:'Transforms', updated:'8.1.0', flags:'todo'}
-
-<div class='topic'>
-	<p>
-		The Juneau serializers and parsers can be configured on how to handle POJOs through the use of Transforms.
-		(See {@doc jm.Swaps Swaps})
-	</p>
-	<p>
-		Transforms are associated serializers and parsers registered on a REST resource via the following:
-	</p>
-	<ul class='javatree'>
-		<li class='ja'>{@del BeanConfig#beanFilters() BeanConfig(beanFilters)} - On class or methods. 
-		<li class='ja'>{@link oaj.annotation.BeanConfig#swaps() BeanConfig(swaps)} - On class or methods. 
-		<li class='jm'>{@del RestContext.Builder#beanFilters(Object...)} 
-		<li class='jm'>{@del oajr.RestContext.Builder#swaps(Class...)} 
-	</ul>
-	<p class='bcode w800'>
-		|	<jc>// Servlet with transforms applied</jc>
-		|	<ja>@Rest</ja>(
-		|		...
-		|	)
-		|	<ja>@BeanConfig</ja>(
-		|		swaps={
-		|			<jc>// Calendars should be serialized/parsed as ISO8601 date-time strings</jc>
-		|			TemporalCalendarSwap.IsoInstant.<jk>class</jk>,
-		|
-		|			<jc>// Byte arrays should be serialized/parsed as BASE64-encoded strings</jc>
-		|			ByteArraySwap.Base64.<jk>class</jk>
-		|		},
-		|		beanFilters={
-		|			<jc>// Subclasses of MyInterface will be treated as MyInterface objects.</jc>
-		|			<jc>// Bean properties not defined on that interface will be ignored.</jc>
-		|			MyInterface.<jk>class</jk>
-		|		}
-		|	)
-		|	<jk>public</jk> MyRestServlet <jk>extends</jk> BasicRestServlet {...}
-	</p>
-	<p>
-		The programmatic equivalent to this is:
-	</p>
-	<p class='bcode w800'>
-		|	<jc>// Servlet with properties applied</jc>
-		|	<ja>@Rest</ja>(...)
-		|	<jk>public</jk> MyRestServlet <jk>extends</jk> BasicRestServlet {
-		|	
-		|		<jk>public</jk> MyRestServlet(RestContext.Builder builder) {
-		|			
-		|			builder
-		|				.swaps(
-		|					TemporalCalendarSwap.IsoInstant.<jk>class</jk>,
-		|					ByteArraySwap.Base64.<jk>class</jk>
-		|				) 
-		|				.beanFilters(MyInterface.<jk>class</jk>);
-		|		}
-		|	}
-	</p>
-</div>
\ No newline at end of file
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/11.jrs.Converters.html b/juneau-doc/docs/Topics/06.juneau-rest-server/08.jrs.Converters.html
similarity index 52%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/11.jrs.Converters.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/08.jrs.Converters.html
index 26d3f78..ef28972 100644
--- a/juneau-doc/docs/Topics/06.juneau-rest-server/11.jrs.Converters.html
+++ b/juneau-doc/docs/Topics/06.juneau-rest-server/08.jrs.Converters.html
@@ -13,32 +13,21 @@
  ***************************************************************************************************************************/
  -->
 
-{title:'Converters', flags:'todo'}
+{title:'Converters', updated:'9.0.0'}
 
 <div class='topic'>
 	<p>
-		Converters can be thought of as "post-processors" for POJOs before they get passed to the serializers.
+		Converters can be thought of as "post-processors" for response POJOs before they get passed to the serializer.
 	</p>
 	<p>
 		Converters are associated with resource classes and methods via the following:
 	</p>
-	<ul class='javatree'>
+	<ul class='javatreec'>
 		<li class='ja'>{@link oajr.annotation.Rest#converters() Rest(converters)} 
 		<li class='ja'>{@link oajr.annotation.RestOp#converters() RestOp(converters)} 
-		<li class='jm'>{@del oajr.RestContext.Builder#converters(Class...)} 
 	</ul>
 	<h5 class='figure'>Example:</h5>
 	<p class='bcode w800'>
-		|	<jc>// Associate the Traversable converter to all Java REST methods in this servlet</jc>
-		|	<ja>@Rest</ja>(converters=Traversable.<jk>class</jk>)
-		|	<jk>public</jk> MyRestServlet <jk>extends</jk> BasicRestServlet {
-		|		...
-		|	}
-	</p>
-	<p>
-		They can also be defined at the method level:
-	</p>
-	<p class='bcode w800'>
 		|	<jc>// GET person request handler.</jc>
 		|	<jc>// Traversable conversion enabled to allow nodes in returned POJO tree to be addressed.</jc>
 		|	<jc>// Queryable conversion enabled to allow returned POJO to be searched/viewed/sorted.</jc>
@@ -51,51 +40,12 @@
 		|	}
 	</p>	
 	<p>
-		The following converter is used to provide support for addressing child nodes in a POJO tree with URL path 
-		remainders.  
-		In this code, the 3rd parameter is the object that was returned by the Java method.
-		The converter uses the {@link oaj.utils.PojoRest} wrapper class to address nodes in the 
-		tree.
-	</p>
-	<p class='bcode w800'>
-		|	<jd>/**
-		|	 * Converter for enablement of PojoRest support on response objects returned by a @RestOp method.
-		|	 * When enabled, objects in a POJO tree returned by the REST method can be addressed through additional URL path information.
-		|	 */</jd>
-		|	<jk>public class</jk> Traversable <jk>implements</jk> RestConverter {
-		|	
-		|		<ja>@Override</ja> <jc>/* RestConverter */</jc>
-		|		<jk>public</jk> Object convert(RestRequest <jv>req</jv>, Object <jv>o</jv>) <jk>throws</jk> RestException {
-		|			<jk>if</jk> (<jv>o</jv> == <jk>null</jk>)
-		|				<jk>return null</jk>;
-		|	
-		|			String <jv>pathRemainder</jv> = <jv>req</jv>.getPathMatch().getRemainder();
-		|	
-		|			<jk>if</jk> (<jv>pathRemainder</jv> != <jk>null</jk>) {
-		|				<jk>try</jk> {
-		|				
-		|					<jc>// Use the PojoRest class to traverse our POJO model.</jc> 
-		|					PojoRest <jv>p</jv> = <jk>new</jk> PojoRest(<jv>o</jv>);
-		|					<jv>o</jv> = <jv>p</jv>.get(<jv>pathRemainder</jv>);
-		|				
-		|				} <jk>catch</jk> (PojoRestException <jv>e</jv>) {
-		|					<jk>throw new</jk> RestException(<jv>e</jv>.getStatus(), <jv>e</jv>);
-		|				} <jk>catch</jk> (Exception <jv>e</jv>) {
-		|					<jk>throw new</jk> RestException(HttpServletResponse.<jsf>SC_INTERNAL_SERVER_ERROR</jsf>, <jv>e</jv>);
-		|				}
-		|			}
-		|			
-		|			<jk>return</jk> <jv>o</jv>;
-		|		}
-		|	}
-	</p>	
-	<p>
 		Juneau defines the following converters out-of-the-box:
 	</p>
 	<ul class='javatree'>
 		<li class='jic'>
-		{@link oajr.RestConverter}
-		<ul>
+		{@link oajr.converter.RestConverter}
+		<ul class='spaced-list'>
 			<li class='jc'>
 				{@link oajr.converter.Queryable}
 				<br>Provides query parameters that can be used to transform the response (i.e. search/view/sort the 
@@ -110,8 +60,4 @@
 				serialized as the response.
 		</ul>
 	</ul>
-	
-	<ul class='seealso'>
-		<li class='jf'>{@del oajr.RestContext#REST_converters} 
-	</ul>
 </div>
\ No newline at end of file
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/12.jrs.Messages.html b/juneau-doc/docs/Topics/06.juneau-rest-server/09.jrs.LocalizedMessages.html
similarity index 92%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/12.jrs.Messages.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/09.jrs.LocalizedMessages.html
index 42c1aab..a14f08e 100644
--- a/juneau-doc/docs/Topics/06.juneau-rest-server/12.jrs.Messages.html
+++ b/juneau-doc/docs/Topics/06.juneau-rest-server/09.jrs.LocalizedMessages.html
@@ -13,7 +13,7 @@
  ***************************************************************************************************************************/
  -->
 
-{title:'Messages', updated:'8.2.0', flags:'todo'}
+{title:'Localized Messages', updated:'8.2.0,9.0.0'}
 
 <div class='topic'>
 	<p>
@@ -37,15 +37,14 @@
 	</ul>
 	
 	<p>
-		This annotation is used to provide request-localized (based on <c>Accept-Language</c>) messages for the following methods:
+		This annotation is used to provide request-localized (based on <c>Accept-Language</c>) messages for the following method:
 	</p>
 	<ul class='javatree'>
 		<li class='jm'>{@link oajr.RestRequest#getMessage(String, Object...)}
-		<li class='jm'>{@link oajr.RestContext#getMessages() RestContext.getMessages()}
 	</ul>
 	
 	<p>
-		Request-localized messages are also available by passing either of the following parameter types into your Java method:
+		Request-localized messages are also available by passing either of the following args into your Java method:
 	</p>
 	<ul class='javatree'>
 		<li class='jc'>{@link java.util.ResourceBundle} - Basic Java resource bundle.
@@ -102,9 +101,4 @@
 		Messages are automatically inherited from super classes.  If a string cannot be found in the bundle of the current
 		class, it will be searched for up the class hierarchy.
 	</p>
-	
-	<ul class='seealso'>
-		<li class='jc'>{@link oaj.cp.Messages}
-		<li class='jf'>{@del oajr.RestContext#REST_messages}
-	</ul>
 </div>
\ No newline at end of file
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/13.jrs.Encoders.html b/juneau-doc/docs/Topics/06.juneau-rest-server/10.jrs.Encoders.html
similarity index 94%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/13.jrs.Encoders.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/10.jrs.Encoders.html
index 4ec9a4f..9626ba1 100644
--- a/juneau-doc/docs/Topics/06.juneau-rest-server/13.jrs.Encoders.html
+++ b/juneau-doc/docs/Topics/06.juneau-rest-server/10.jrs.Encoders.html
@@ -13,7 +13,7 @@
  ***************************************************************************************************************************/
  -->
 
-{title:'Encoders', flags:'todo'}
+{title:'Encoders', updated:'9.0.0'}
 
 <div class='topic'>
 	<p>
@@ -44,8 +44,4 @@
 				{@link oaj.encoders.IdentityEncoder}
 		</ul>
 	</ul>
-	
-	<ul class='seealso'>
-		<li class='jf'>{@del oajr.RestContext#REST_encoders}
-	</ul>
 </div>
\ No newline at end of file
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/10.jrs.RoleGuards.html b/juneau-doc/docs/Topics/06.juneau-rest-server/10.jrs.RoleGuards.html
deleted file mode 100644
index 2cabe01..0000000
--- a/juneau-doc/docs/Topics/06.juneau-rest-server/10.jrs.RoleGuards.html
+++ /dev/null
@@ -1,81 +0,0 @@
-<!--
-/***************************************************************************************************************************
- * 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.
- ***************************************************************************************************************************/
- -->
-
-{title:'Role guards', created:'8.1.0', flags:'todo'}
- 
-<div class='topic'>
-	<p>
-		Specialized guards are provided for controlling access to servlet classes and methods based on user roles.
-		These are controlled via annotations on the REST class and methods:
-	</p>
-	<ul class='javatree'>
-		<li class='ja'>{@link oajr.annotation.Rest}
-		<ul>
-			<li class='jf'>{@link oajr.annotation.Rest#roleGuard() roleGuard()}
-			<li class='jf'>{@link oajr.annotation.Rest#rolesDeclared() rolesDeclared()}
-		</ul>
-		<li class='ja'>{@link oajr.annotation.RestOp}
-		<ul>
-			<li class='jf'>{@link oajr.annotation.RestOp#roleGuard() roleGuard()}
-			<li class='jf'>{@link oajr.annotation.RestOp#rolesDeclared() rolesDeclared()}
-		</ul>
-	</ul>
-	<p>
-		The <c>roleGuard()</c> annotation is an expression that defines whether a user with specified roles are allowed
-		to access methods.
-	</p>
-	<h5 class='figure'>Example:</h5>
-	<p class='bcode w800'>
-		|	<jc>// Only admin users or users with both read/write and special access 
-		|	// can run any methods on this class.</jc>
-		|	<ja>@Rest</ja>(
-		|		path=<js>"/foo"</js>,
-		|		roleGuard=<js>"ROLE_ADMIN || (ROLE_READ_WRITE &amp;&amp; ROLE_SPECIAL)"</js>
-		|	)
-		|	<jk>public class</jk> MyResource <jk>extends</jk> RestServlet {
-		|		...
-		|	}
-	</p>
-	<p>
-		The syntax allows for any of the following:
-	</p>
-	<ul>
-		<li><js>"foo"</js> - Single arguments.
-		<li><js>"foo,bar,baz"</js> - Multiple OR'ed arguments.
-		<li><js>"foo | bar | baz"</js> - Multiple OR'ed arguments, pipe syntax.
-		<li><js>"foo || bar || baz"</js> - Multiple OR'ed arguments, Java-OR syntax.
-		<li><js>"fo*"</js> - Patterns including <js>'*'</js> and <js>'?'</js>.
-		<li><js>"fo* &amp; *oo"</js> - Multiple AND'ed arguments, ampersand syntax.
-		<li><js>"fo* &amp;&amp; *oo"</js> - Multiple AND'ed arguments, Java-AND syntax.
-		<li><js>"fo* || (*oo || bar)"</js> - Parenthesis.
-	</ul>
-	
-	<p>
-	 	If patterns are used, you must specify the list of declared roles using the <c>rolesDeclared()</c> annotations.
-	 	This declares the list of all possible user roles and is needed because the servlet API does not provide this
-	 	capability.
-	</p>
-	
-	<h5 class='figure'>Example:</h5>
-	<p class='bcode w800'>
-		|	<ja>@Rest</ja>(
-		|		rolesDeclared=<js>"ROLE_ADMIN,ROLE_READ_WRITE,ROLE_READ_ONLY,ROLE_SPECIAL"</js>,
-		|		roleGuard=<js>"ROLE_ADMIN || (*WRITE* &amp;&amp; *SPECIAL*)"</js>
-		|	)
-		|	<jk>public class</jk> MyResource <jk>extends</jk> RestServlet {
-		|		...
-		|	}
-	</p>
-</div>
\ No newline at end of file
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/15.jrs.ConfigurationFiles.html b/juneau-doc/docs/Topics/06.juneau-rest-server/11.jrs.ConfigurationFiles.html
similarity index 77%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/15.jrs.ConfigurationFiles.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/11.jrs.ConfigurationFiles.html
index 1f7937d..f90e938 100644
--- a/juneau-doc/docs/Topics/06.juneau-rest-server/15.jrs.ConfigurationFiles.html
+++ b/juneau-doc/docs/Topics/06.juneau-rest-server/11.jrs.ConfigurationFiles.html
@@ -13,12 +13,25 @@
  ***************************************************************************************************************************/
  -->
 
-{title:'Configuration Files', flags:'todo'}
+{title:'Configuration Files', updated:'9.0.0'}
 
 <div class='topic'>
 	<p>
 		The Server API provides methods for associating configuration files with REST servlets so that 
-		configuration properties can be defined in external files.
+		configuration properties can be defined in external files.  It uses the following annotation:
+	</p>
+	<ul class='javatree'>
+		<li class='ja'>{@link oajr.annotation.Rest#config() Rest(config)}
+	</ul>
+	
+	<h5 class='figure'>Example:</h5>
+	<p class='bcode w800'>
+		|	<ja>@Rest</ja>(
+		|		<jc>// Config file is located at ./config_dir/myconfig.cfg</jc>
+		|		config=<js>"config_dir/myconfig.cfg"</js>,
+		|		...
+		|	)
+		|	<jk>public class</jk> MyResource {...}
 	</p>
 	<p>
 		In recap, the Configuration API provides support for INI-style configuration files with embedded string variables:
@@ -38,43 +51,46 @@
 		These properties are then accessible through the {@link oaj.config.Config} class.
 	</p>
 	<p class='bcode w800'>
-		|	Config c = Config.<jsm>create</jsm>(<js>"myconfig.cfg"</js>).build();
-		|	String path = c.getString(<js>"MyProperties/path"</js>);
-		|	File javaHome = c.getObject(<js>"MyProperties/javaHome"</js>, File.<jk>class</jk>);
-		|	String customMessage = c.getString(<js>"MyProperties/customMessage"</js>);
+		|	<ja>@RestGet</ja>(<js>"/"</js>)
+		|	<jk>public</jk> String sample(Config <jv>config</jv>) {
+		|		String <jv>path</jv> = <jv>config</jv>.getString(<js>"MyProperties/path"</js>);
+		|		File <jv>javaHome</jv> = <jv>config</jv>.getObject(<js>"MyProperties/javaHome"</js>, File.<jk>class</jk>);
+		|		String <jv>customMessage</jv> = <jv>config</jv>.getString(<js>"MyProperties/customMessage"</js>);
+		|		...
+		|	}
 	</p>
 	<p>
-		Configuration files are associated with REST resources through the following:
+		The annotation itself can contain string variables.  
+		For example, the Microservice API {@link oajr.BasicRestServlet} class defines the 
+		location of the config file as a system property <l>"juneau.configFile"</l>:
 	</p>
-	<ul class='javatree'>
-		<li class='ja'>{@link oajr.annotation.Rest#config() Rest(config)}
-	</ul>
-	
-	<h5 class='figure'>Example:</h5>
 	<p class='bcode w800'>
 		|	<ja>@Rest</ja>(
-		|		<jc>// Config file is located at ./config_dir/myconfig.cfg</jc>
-		|		config=<js>"config_dir/myconfig.cfg"</js>,
+		|		<jc>// Config file location is defined as a system property</jc>
+		|		config=<js>"$S{juneau.configFile}"</js>,
 		|		...
 		|	)
 		|	<jk>public class</jk> MyResource {...}
 	</p>
 	<p>
-		The annotation itself can contain string variables.  
-		For example, the Microservice API {@link oajr.BasicRestServlet} class defines the 
-		location of the config file as a system property <l>"juneau.configFile"</l>:
+		Spring Boot applications typically define an <c>application.properties</c> file.  You can reuse it
+		as a config file like so:
 	</p>
 	<p class='bcode w800'>
 		|	<ja>@Rest</ja>(
-		|		<jc>// Config file location is defined as a system property</jc>
-		|		config=<js>"$S{juneau.configFile}"</js>,
+		|		config=<js>"application.properties"</js>,
 		|		...
 		|	)
 		|	<jk>public class</jk> MyResource {...}
 	</p>
 	<p>
-		Once a config file has been associated with a REST resource, it can be accessed through the 
-		{@link oajr.RestContext.Builder#getConfig()} method.
+		Note that properties files are a subset of functionality of INI files (they're basically just INI files with a single default section).  
+		It's therefore possible to use INI-style syntax such as sections in your <c>application.properties</c> file.  
+	</p>
+	<p>
+		Once a config file has been associated with a REST resource, it can be accessed through one of the following:
+		{@link oajr.RestContext.Builder#getConfig()} method.  It can also be access by passing in a {@link oaj.config.Config} bean to any of your
+		REST OP methods.
 	</p>
 	<p>
 		A common usage is to use this method to initialize fields in your servlet.
@@ -85,7 +101,7 @@
 		|		config=<js>"config_dir/myconfig.cfg"</js>,
 		|		...
 		|	)
-		|	<jk>public class</jk> MyResource  {
+		|	<jk>public class</jk> MyResource {
 		|		<jk>private final</jk> String <jf>path</jf>;
 		|		<jk>private final</jk> File <jf>javaHome</jf>;
 		|	
@@ -99,12 +115,10 @@
 		Another common usage is to refer to config properties through <ck>$C</ck> variables in your annotations:
 	</p>
 	<p class='bcode w800'>
-		|	<ja>@Rest</ja>(
-		|		<jc>// Get stylesheet from myconfig.cfg, but default to devops.css if it's not specified</jc>
-		|		htmldoc=<ja>@HtmlDoc</ja>(
-		|			stylesheet=<js>"$C{MyServlet/stylesheet,servlet:/styles/devops.css}"</js>,
-		|		)
-		|		...
+		|	<ja>@Rest</ja>
+		|	<jc>// Get stylesheet from myconfig.cfg, but default to devops.css if it's not specified</jc>
+		|	<ja>@HtmlDoc</ja>(
+		|		stylesheet=<js>"$C{MyServlet/stylesheet,servlet:/styles/devops.css}"</js>,
 		|	)
 		|	<jk>public class</jk> MyResource {...}
 	</p>
@@ -134,8 +148,8 @@
 		|		 * Specify the GET parameter "?person=X" for a specialized message! 
 		|		 */</jd>
 		|		<ja>@RestGet</ja>(<js>"/"</js>)
-		|		<jk>public</jk> String sayHello(RestRequest <jv>req</jv>) {
-		|			<jk>return</jk> <jv>req</jv>.getConfig().getString(<js>"HelloWorldResource/message"</js>);
+		|		<jk>public</jk> String sayHello(Config <jv>config</jv>) {
+		|			<jk>return</jk> <jv>config</jv>.getString(<js>"HelloWorldResource/message"</js>);
 		|		}
 		|	}
 	</p>
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/14.jrs.SvlVariables.html b/juneau-doc/docs/Topics/06.juneau-rest-server/12.jrs.SvlVariables.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/14.jrs.SvlVariables.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/12.jrs.SvlVariables.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.StaticFiles.html b/juneau-doc/docs/Topics/06.juneau-rest-server/13.jrs.StaticFiles.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.StaticFiles.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/13.jrs.StaticFiles.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/17.jrs.ClientVersioning.html b/juneau-doc/docs/Topics/06.juneau-rest-server/14.jrs.ClientVersioning.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/17.jrs.ClientVersioning.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/14.jrs.ClientVersioning.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/18.jrs.InfoProvider.html b/juneau-doc/docs/Topics/06.juneau-rest-server/15.jrs.InfoProvider.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/18.jrs.InfoProvider.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/15.jrs.InfoProvider.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger.html b/juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/01.jrs.BasicRestServletSwagger.html b/juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/01.jrs.BasicRestServletSwagger.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/01.jrs.BasicRestServletSwagger.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/01.jrs.BasicRestServletSwagger.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/02.jrs.BasicSwaggerInfo.html b/juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/02.jrs.BasicSwaggerInfo.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/02.jrs.BasicSwaggerInfo.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/02.jrs.BasicSwaggerInfo.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/03.jrs.SwaggerTags.html b/juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/03.jrs.SwaggerTags.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/03.jrs.SwaggerTags.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/03.jrs.SwaggerTags.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/04.jrs.SwaggerOperations.html b/juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/04.jrs.SwaggerOperations.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/04.jrs.SwaggerOperations.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/04.jrs.SwaggerOperations.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/05.jrs.SwaggerParameters.html b/juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/05.jrs.SwaggerParameters.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/05.jrs.SwaggerParameters.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/05.jrs.SwaggerParameters.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/06.jrs.SwaggerParameterExamples.html b/juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/06.jrs.SwaggerParameterExamples.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/06.jrs.SwaggerParameterExamples.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/06.jrs.SwaggerParameterExamples.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/07.jrs.SwaggerResponses.html b/juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/07.jrs.SwaggerResponses.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/07.jrs.SwaggerResponses.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/07.jrs.SwaggerResponses.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/08.jrs.SwaggerResponseExamples.html b/juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/08.jrs.SwaggerResponseExamples.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/08.jrs.SwaggerResponseExamples.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/08.jrs.SwaggerResponseExamples.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/09.jrs.SwaggerModels.html b/juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/09.jrs.SwaggerModels.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/09.jrs.SwaggerModels.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/09.jrs.SwaggerModels.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/10.jrs.SwaggerStylesheet.html b/juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/10.jrs.SwaggerStylesheet.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/10.jrs.SwaggerStylesheet.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/10.jrs.SwaggerStylesheet.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/doc-files/jrs.Swagger.Models.1.png b/juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/doc-files/jrs.Swagger.Models.1.png
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/doc-files/jrs.Swagger.Models.1.png
rename to juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/doc-files/jrs.Swagger.Models.1.png
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/doc-files/jrs.Swagger.Models.2.png b/juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/doc-files/jrs.Swagger.Models.2.png
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/doc-files/jrs.Swagger.Models.2.png
rename to juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/doc-files/jrs.Swagger.Models.2.png
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/doc-files/jrs.Swagger.Models.3.png b/juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/doc-files/jrs.Swagger.Models.3.png
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/doc-files/jrs.Swagger.Models.3.png
rename to juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/doc-files/jrs.Swagger.Models.3.png
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/doc-files/jrs.Swagger.Operations.1.png b/juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/doc-files/jrs.Swagger.Operations.1.png
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/doc-files/jrs.Swagger.Operations.1.png
rename to juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/doc-files/jrs.Swagger.Operations.1.png
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/doc-files/jrs.Swagger.Operations.2.png b/juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/doc-files/jrs.Swagger.Operations.2.png
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/doc-files/jrs.Swagger.Operations.2.png
rename to juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/doc-files/jrs.Swagger.Operations.2.png
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/doc-files/jrs.Swagger.Operations.3.png b/juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/doc-files/jrs.Swagger.Operations.3.png
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/doc-files/jrs.Swagger.Operations.3.png
rename to juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/doc-files/jrs.Swagger.Operations.3.png
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/doc-files/jrs.Swagger.Parameters.1.png b/juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/doc-files/jrs.Swagger.Parameters.1.png
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/doc-files/jrs.Swagger.Parameters.1.png
rename to juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/doc-files/jrs.Swagger.Parameters.1.png
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/doc-files/jrs.Swagger.Parameters.2.png b/juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/doc-files/jrs.Swagger.Parameters.2.png
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/doc-files/jrs.Swagger.Parameters.2.png
rename to juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/doc-files/jrs.Swagger.Parameters.2.png
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/doc-files/jrs.Swagger.Parameters.3.png b/juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/doc-files/jrs.Swagger.Parameters.3.png
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/doc-files/jrs.Swagger.Parameters.3.png
rename to juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/doc-files/jrs.Swagger.Parameters.3.png
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/doc-files/jrs.Swagger.Parameters.4.png b/juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/doc-files/jrs.Swagger.Parameters.4.png
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/doc-files/jrs.Swagger.Parameters.4.png
rename to juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/doc-files/jrs.Swagger.Parameters.4.png
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/doc-files/jrs.Swagger.ResponseExamples.1.png b/juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/doc-files/jrs.Swagger.ResponseExamples.1.png
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/doc-files/jrs.Swagger.ResponseExamples.1.png
rename to juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/doc-files/jrs.Swagger.ResponseExamples.1.png
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/doc-files/jrs.Swagger.ResponseExamples.2.png b/juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/doc-files/jrs.Swagger.ResponseExamples.2.png
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/doc-files/jrs.Swagger.ResponseExamples.2.png
rename to juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/doc-files/jrs.Swagger.ResponseExamples.2.png
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/doc-files/jrs.Swagger.ResponseExamples.3.png b/juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/doc-files/jrs.Swagger.ResponseExamples.3.png
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/doc-files/jrs.Swagger.ResponseExamples.3.png
rename to juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/doc-files/jrs.Swagger.ResponseExamples.3.png
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/doc-files/jrs.Swagger.ResponseExamples.4.png b/juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/doc-files/jrs.Swagger.ResponseExamples.4.png
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.Swagger/doc-files/jrs.Swagger.ResponseExamples.4.png
rename to juneau-doc/docs/Topics/06.juneau-rest-server/16.jrs.Swagger/doc-files/jrs.Swagger.ResponseExamples.4.png
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/20.jrs.ExecutionStatistics.html b/juneau-doc/docs/Topics/06.juneau-rest-server/17.jrs.ExecutionStatistics.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/20.jrs.ExecutionStatistics.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/17.jrs.ExecutionStatistics.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/21.jrs.HtmlDocAnnotation.html b/juneau-doc/docs/Topics/06.juneau-rest-server/18.jrs.HtmlDocAnnotation.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/21.jrs.HtmlDocAnnotation.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/18.jrs.HtmlDocAnnotation.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/21.jrs.HtmlDocAnnotation/01.jrs.HtmlUIvsDI.html b/juneau-doc/docs/Topics/06.juneau-rest-server/18.jrs.HtmlDocAnnotation/01.jrs.HtmlUIvsDI.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/21.jrs.HtmlDocAnnotation/01.jrs.HtmlUIvsDI.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/18.jrs.HtmlDocAnnotation/01.jrs.HtmlUIvsDI.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/21.jrs.HtmlDocAnnotation/02.jrs.HtmlWidgets.html b/juneau-doc/docs/Topics/06.juneau-rest-server/18.jrs.HtmlDocAnnotation/02.jrs.HtmlWidgets.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/21.jrs.HtmlDocAnnotation/02.jrs.HtmlWidgets.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/18.jrs.HtmlDocAnnotation/02.jrs.HtmlWidgets.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/21.jrs.HtmlDocAnnotation/03.jrs.HtmlPredefinedWidgets.html b/juneau-doc/docs/Topics/06.juneau-rest-server/18.jrs.HtmlDocAnnotation/03.jrs.HtmlPredefinedWidgets.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/21.jrs.HtmlDocAnnotation/03.jrs.HtmlPredefinedWidgets.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/18.jrs.HtmlDocAnnotation/03.jrs.HtmlPredefinedWidgets.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/21.jrs.HtmlDocAnnotation/04.jrs.HtmlUiCustomization.html b/juneau-doc/docs/Topics/06.juneau-rest-server/18.jrs.HtmlDocAnnotation/04.jrs.HtmlUiCustomization.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/21.jrs.HtmlDocAnnotation/04.jrs.HtmlUiCustomization.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/18.jrs.HtmlDocAnnotation/04.jrs.HtmlUiCustomization.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/21.jrs.HtmlDocAnnotation/05.jrs.HtmlStylesheets.html b/juneau-doc/docs/Topics/06.juneau-rest-server/18.jrs.HtmlDocAnnotation/05.jrs.HtmlStylesheets.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/21.jrs.HtmlDocAnnotation/05.jrs.HtmlStylesheets.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/18.jrs.HtmlDocAnnotation/05.jrs.HtmlStylesheets.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/21.jrs.HtmlDocAnnotation/doc-files/jrs.HtmlDocAnnotation.PredefinedWidgets.1.png b/juneau-doc/docs/Topics/06.juneau-rest-server/18.jrs.HtmlDocAnnotation/doc-files/jrs.HtmlDocAnnotation.PredefinedWidgets.1.png
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/21.jrs.HtmlDocAnnotation/doc-files/jrs.HtmlDocAnnotation.PredefinedWidgets.1.png
rename to juneau-doc/docs/Topics/06.juneau-rest-server/18.jrs.HtmlDocAnnotation/doc-files/jrs.HtmlDocAnnotation.PredefinedWidgets.1.png
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/21.jrs.HtmlDocAnnotation/doc-files/jrs.HtmlDocAnnotation.PredefinedWidgets.2.png b/juneau-doc/docs/Topics/06.juneau-rest-server/18.jrs.HtmlDocAnnotation/doc-files/jrs.HtmlDocAnnotation.PredefinedWidgets.2.png
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/21.jrs.HtmlDocAnnotation/doc-files/jrs.HtmlDocAnnotation.PredefinedWidgets.2.png
rename to juneau-doc/docs/Topics/06.juneau-rest-server/18.jrs.HtmlDocAnnotation/doc-files/jrs.HtmlDocAnnotation.PredefinedWidgets.2.png
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/21.jrs.HtmlDocAnnotation/doc-files/jrs.HtmlDocAnnotation.PredefinedWidgets.3.png b/juneau-doc/docs/Topics/06.juneau-rest-server/18.jrs.HtmlDocAnnotation/doc-files/jrs.HtmlDocAnnotation.PredefinedWidgets.3.png
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/21.jrs.HtmlDocAnnotation/doc-files/jrs.HtmlDocAnnotation.PredefinedWidgets.3.png
rename to juneau-doc/docs/Topics/06.juneau-rest-server/18.jrs.HtmlDocAnnotation/doc-files/jrs.HtmlDocAnnotation.PredefinedWidgets.3.png
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/21.jrs.HtmlDocAnnotation/doc-files/jrs.HtmlDocAnnotation.PredefinedWidgets.4.png b/juneau-doc/docs/Topics/06.juneau-rest-server/18.jrs.HtmlDocAnnotation/doc-files/jrs.HtmlDocAnnotation.PredefinedWidgets.4.png
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/21.jrs.HtmlDocAnnotation/doc-files/jrs.HtmlDocAnnotation.PredefinedWidgets.4.png
rename to juneau-doc/docs/Topics/06.juneau-rest-server/18.jrs.HtmlDocAnnotation/doc-files/jrs.HtmlDocAnnotation.PredefinedWidgets.4.png
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/22.jrs.DefaultHeaders.html b/juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.DefaultHeaders.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/22.jrs.DefaultHeaders.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/19.jrs.DefaultHeaders.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/23.jrs.LoggingAndDebugging.html b/juneau-doc/docs/Topics/06.juneau-rest-server/20.jrs.LoggingAndDebugging.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/23.jrs.LoggingAndDebugging.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/20.jrs.LoggingAndDebugging.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/24.jrs.HttpStatusCodes.html b/juneau-doc/docs/Topics/06.juneau-rest-server/21.jrs.HttpStatusCodes.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/24.jrs.HttpStatusCodes.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/21.jrs.HttpStatusCodes.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/25.jrs.OverloadingHttpMethods.html b/juneau-doc/docs/Topics/06.juneau-rest-server/22.jrs.OverloadingHttpMethods.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/25.jrs.OverloadingHttpMethods.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/22.jrs.OverloadingHttpMethods.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/26.jrs.BuiltInParameters.html b/juneau-doc/docs/Topics/06.juneau-rest-server/23.jrs.BuiltInParameters.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/26.jrs.BuiltInParameters.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/23.jrs.BuiltInParameters.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/27.jrs.CustomSerializersAndParsers.html b/juneau-doc/docs/Topics/06.juneau-rest-server/24.jrs.CustomSerializersAndParsers.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/27.jrs.CustomSerializersAndParsers.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/24.jrs.CustomSerializersAndParsers.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/28.jrs.UsingWithOsgi.html b/juneau-doc/docs/Topics/06.juneau-rest-server/25.jrs.UsingWithOsgi.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/28.jrs.UsingWithOsgi.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/25.jrs.UsingWithOsgi.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/29.jrs.Injection.html b/juneau-doc/docs/Topics/06.juneau-rest-server/26.jrs.Injection.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/29.jrs.Injection.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/26.jrs.Injection.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/30.jrs.OtherNotes.html b/juneau-doc/docs/Topics/06.juneau-rest-server/27.jrs.OtherNotes.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/30.jrs.OtherNotes.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/27.jrs.OtherNotes.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/31.jrs.RestContext.html b/juneau-doc/docs/Topics/06.juneau-rest-server/28.jrs.RestContext.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/31.jrs.RestContext.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/28.jrs.RestContext.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/32.jrs.RestRpc.html b/juneau-doc/docs/Topics/06.juneau-rest-server/29.jrs.RestRpc.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/32.jrs.RestRpc.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/29.jrs.RestRpc.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/33.jrs.CustomRestContextsAndBuilders.html b/juneau-doc/docs/Topics/06.juneau-rest-server/30.jrs.CustomRestContextsAndBuilders.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/33.jrs.CustomRestContextsAndBuilders.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/30.jrs.CustomRestContextsAndBuilders.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/36.jrs.ResponseProcessors.html b/juneau-doc/docs/Topics/06.juneau-rest-server/31.jrs.FluentAssertions.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/36.jrs.ResponseProcessors.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/31.jrs.FluentAssertions.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/37.jrs.UtilityBeans.html b/juneau-doc/docs/Topics/06.juneau-rest-server/32.jrs.Overview.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/37.jrs.UtilityBeans.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/32.jrs.Overview.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/34.jrs.FluentAssertions.html b/juneau-doc/docs/Topics/06.juneau-rest-server/33.jrs.ResponseProcessors.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/34.jrs.FluentAssertions.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/33.jrs.ResponseProcessors.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/35.jrs.Overview.html b/juneau-doc/docs/Topics/06.juneau-rest-server/34.jrs.UtilityBeans.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/35.jrs.Overview.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/34.jrs.UtilityBeans.html
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/08.jrs.HandlingUris.html b/juneau-doc/docs/Topics/06.juneau-rest-server/35.jrs.SerializingUris.html
similarity index 100%
rename from juneau-doc/docs/Topics/06.juneau-rest-server/08.jrs.HandlingUris.html
rename to juneau-doc/docs/Topics/06.juneau-rest-server/35.jrs.SerializingUris.html
diff --git a/juneau-doc/src/main/javadoc/overview.html b/juneau-doc/src/main/javadoc/overview.html
index a9ec7e0..8a0b850 100644
--- a/juneau-doc/src/main/javadoc/overview.html
+++ b/juneau-doc/src/main/javadoc/overview.html
@@ -375,15 +375,12 @@
 		</ol>
 		<li><p><a class='doclink' href='#juneau-rest-server.jrs.Marshalling'>Marshalling</a><span class='update'>updated: <b>9.0.0</b></span></p>
 		<li><p><a class='doclink' href='#juneau-rest-server.jrs.HandlingFormPosts'>Form Posts</a><span class='update'>updated: <b>9.0.0</b></span></p>
-		<li><p><a class='doclink' href='#juneau-rest-server.jrs.Transforms'>Transforms</a><span class='update'>updated: 8.1.0, <b><red>todo</red></b></span></p>
-		<li><p><a class='doclink' href='#juneau-rest-server.jrs.HandlingUris'>URIs</a><span class='update'><b><red>todo</red></b></span></p>
-		<li><p><a class='doclink' href='#juneau-rest-server.jrs.Guards'>Guards</a><span class='update'><b><red>todo</red></b></span></p>
-		<li><p><a class='doclink' href='#juneau-rest-server.jrs.RoleGuards'>Role guards</a><span class='update'>created: 8.1.0, <b><red>todo</red></b></span></p>
-		<li><p><a class='doclink' href='#juneau-rest-server.jrs.Converters'>Converters</a><span class='update'><b><red>todo</red></b></span></p>
-		<li><p><a class='doclink' href='#juneau-rest-server.jrs.Messages'>Messages</a><span class='update'>updated: 8.2.0, <b><red>todo</red></b></span></p>
-		<li><p><a class='doclink' href='#juneau-rest-server.jrs.Encoders'>Encoders</a><span class='update'><b><red>todo</red></b></span></p>
+		<li><p><a class='doclink' href='#juneau-rest-server.jrs.Guards'>Guards</a><span class='update'>updated: <b>9.0.0</b></span></p>
+		<li><p><a class='doclink' href='#juneau-rest-server.jrs.Converters'>Converters</a><span class='update'>updated: <b>9.0.0</b></span></p>
+		<li><p><a class='doclink' href='#juneau-rest-server.jrs.LocalizedMessages'>Localized Messages</a><span class='update'>updated: 8.2.0,<b>9.0.0</b></span></p>
+		<li><p><a class='doclink' href='#juneau-rest-server.jrs.Encoders'>Encoders</a><span class='update'>updated: <b>9.0.0</b></span></p>
+		<li><p><a class='doclink' href='#juneau-rest-server.jrs.ConfigurationFiles'>Configuration Files</a><span class='update'>updated: <b>9.0.0</b></span></p>
 		<li><p><a class='doclink' href='#juneau-rest-server.jrs.SvlVariables'>SVL Variables</a><span class='update'><b><red>todo</red></b></span></p>
-		<li><p><a class='doclink' href='#juneau-rest-server.jrs.ConfigurationFiles'>Configuration Files</a><span class='update'><b><red>todo</red></b></span></p>
 		<li><p><a class='doclink' href='#juneau-rest-server.jrs.StaticFiles'>Static files</a><span class='update'><b><red>todo</red></b></span></p>
 		<li><p><a class='doclink' href='#juneau-rest-server.jrs.ClientVersioning'>Client Versioning</a><span class='update'><b><red>todo</red></b></span></p>
 		<li><p><a class='doclink' href='#juneau-rest-server.jrs.InfoProvider'>RestInfoProvider</a><span class='update'><b><red>todo</red></b></span></p>
@@ -425,6 +422,7 @@
 		<li><p><a class='doclink' href='#juneau-rest-server.jrs.Overview'>Utility Beans</a><span class='update'>created: <b>9.0.0</b>, <b><red>TODO</red></b></span></p>
 		<li><p><a class='doclink' href='#juneau-rest-server.jrs.ResponseProcessors'>Fluent Assertions</a><span class='update'>created: <b>9.0.0</b>, <b><red>TODO</red></b></span></p>
 		<li><p><a class='doclink' href='#juneau-rest-server.jrs.UtilityBeans'>Utility Beans</a><span class='update'>created: <b>9.0.0</b>, <b><red>TODO</red></b></span></p>
+		<li><p><a class='doclink' href='#juneau-rest-server.jrs.SerializingUris'>URIs</a><span class='update'><b><red>todo</red></b></span></p>
 	</ol>
 	<li><p class='toc2'><a class='doclink' href='#juneau-rest-server-rdf'>juneau-rest-server-jaxrs</a></p>
 	<li><p class='toc2'><a class='doclink' href='#juneau-rest-server-jaxrs'>juneau-rest-server-jaxrs</a></p>
@@ -16896,6 +16894,31 @@
 	}
 	</p>
 	<p>
+		Swaps are associated serializers and parsers registered on a REST resource via the {@link org.apache.juneau.annotation.BeanConfig} annotation
+		on either the class or method level:
+	</p>
+	<p class='bcode w800'>
+	<jc>// Servlet with transforms applied</jc>
+	<ja>@Rest</ja>(
+		...
+	)
+	<ja>@BeanConfig</ja>(
+		swaps={
+			<jc>// Calendars should be serialized/parsed as ISO8601 date-time strings</jc>
+			TemporalCalendarSwap.IsoInstant.<jk>class</jk>,
+
+			<jc>// Byte arrays should be serialized/parsed as BASE64-encoded strings</jc>
+			ByteArraySwap.Base64.<jk>class</jk>
+		},
+		beanFilters={
+			<jc>// Subclasses of MyInterface will be treated as MyInterface objects.</jc>
+			<jc>// Bean properties not defined on that interface will be ignored.</jc>
+			MyInterface.<jk>class</jk>
+		}
+	)
+	<jk>public</jk> MyResource <jk>extends</jk> BasicRestServlet {...}
+	</p>
+	<p>
 		Config annotations are defined for all serializers and parsers:
 	</p>
 	<ul class='javatreec'>
@@ -17054,168 +17077,24 @@
 
 <!-- ==================================================================================================== -->
 
-<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Transforms' id='juneau-rest-server.jrs.Transforms'>6.7 - Transforms</a><span class='update'>updated: 8.1.0, <b><red>todo</red></b></span></h3>
-<div class='topic'><!-- START: 6.7 - juneau-rest-server.jrs.Transforms -->
-<div class='topic'>
-	<p>
-		The Juneau serializers and parsers can be configured on how to handle POJOs through the use of Transforms.
-		(See {@doc jm.Swaps Swaps})
-	</p>
-	<p>
-		Transforms are associated serializers and parsers registered on a REST resource via the following:
-	</p>
-	<ul class='javatree'>
-		<li class='ja'>{@del BeanConfig#beanFilters() BeanConfig(beanFilters)} - On class or methods. 
-		<li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#swaps() BeanConfig(swaps)} - On class or methods. 
-		<li class='jm'>{@del RestContext.Builder#beanFilters(Object...)} 
-		<li class='jm'>{@del org.apache.juneau.rest.RestContext.Builder#swaps(Class...)} 
-	</ul>
-	<p class='bcode w800'>
-	<jc>// Servlet with transforms applied</jc>
-	<ja>@Rest</ja>(
-		...
-	)
-	<ja>@BeanConfig</ja>(
-		swaps={
-			<jc>// Calendars should be serialized/parsed as ISO8601 date-time strings</jc>
-			TemporalCalendarSwap.IsoInstant.<jk>class</jk>,
-
-			<jc>// Byte arrays should be serialized/parsed as BASE64-encoded strings</jc>
-			ByteArraySwap.Base64.<jk>class</jk>
-		},
-		beanFilters={
-			<jc>// Subclasses of MyInterface will be treated as MyInterface objects.</jc>
-			<jc>// Bean properties not defined on that interface will be ignored.</jc>
-			MyInterface.<jk>class</jk>
-		}
-	)
-	<jk>public</jk> MyRestServlet <jk>extends</jk> BasicRestServlet {...}
-	</p>
-	<p>
-		The programmatic equivalent to this is:
-	</p>
-	<p class='bcode w800'>
-	<jc>// Servlet with properties applied</jc>
-	<ja>@Rest</ja>(...)
-	<jk>public</jk> MyRestServlet <jk>extends</jk> BasicRestServlet {
-	
-		<jk>public</jk> MyRestServlet(RestContext.Builder builder) {
-			
-			builder
-				.swaps(
-					TemporalCalendarSwap.IsoInstant.<jk>class</jk>,
-					ByteArraySwap.Base64.<jk>class</jk>
-				) 
-				.beanFilters(MyInterface.<jk>class</jk>);
-		}
-	}
-	</p>
-</div>
-</div><!-- END: 6.7 - juneau-rest-server.jrs.Transforms -->
-
-<!-- ==================================================================================================== -->
-
-<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.HandlingUris' id='juneau-rest-server.jrs.HandlingUris'>6.8 - URIs</a><span class='update'><b><red>todo</red></b></span></h3>
-<div class='topic'><!-- START: 6.8 - juneau-rest-server.jrs.HandlingUris -->
+<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Guards' id='juneau-rest-server.jrs.Guards'>6.7 - Guards</a><span class='update'>updated: <b>9.0.0</b></span></h3>
+<div class='topic'><!-- START: 6.7 - juneau-rest-server.jrs.Guards -->
 <div class='topic'>
 	<p>
-		As mention earlier {@doc jm.MarshallingUris here}, Juneau serializers have sophisticated support for transforming relative URIs to absolute form.
-	</p>
-	<p>
-		The following example shows a REST method that returns a list of URIs of various forms: 
-	</p>
-	<p class='bcode w800'>
-	<ja>@Rest</ja>(
-		uriAuthority=<js>"http://foo.com:123"</js>,
-		uriContext=<js>"/myContext"</js>
-	)
-	<jk>public class</jk> MyResource {
-	
-		<ja>@RestGet</ja>
-		<jk>public</jk> URI[] getURIs() {
-			<jk>return new</jk> URI[] {
-				URI.<jsm>create</jsm>(<js>"http://www.apache.org/f1a"</js>),
-				URI.<jsm>create</jsm>(<js>"/f1b"</js>),
-				URI.<jsm>create</jsm>(<js>"/f1c/x/y"</js>),
-				URI.<jsm>create</jsm>(<js>"f1d"</js>),
-				URI.<jsm>create</jsm>(<js>"f1e/x/y"</js>),
-				URI.<jsm>create</jsm>(<js>""</js>),
-				URI.<jsm>create</jsm>(<js>"context:/f2a/x"</js>),
-				URI.<jsm>create</jsm>(<js>"context:/f2b"</js>),
-				URI.<jsm>create</jsm>(<js>"context:/"</js>),
-				URI.<jsm>create</jsm>(<js>"context:/.."</js>),
-				URI.<jsm>create</jsm>(<js>"servlet:/f3a/x"</js>),
-				URI.<jsm>create</jsm>(<js>"servlet:/f3b"</js>),
-				URI.<jsm>create</jsm>(<js>"servlet:/"</js>),
-				URI.<jsm>create</jsm>(<js>"servlet:/.."</js>),
-				URI.<jsm>create</jsm>(<js>"request:/f4a/x"</js>),
-				URI.<jsm>create</jsm>(<js>"request:/f4b"</js>),
-				URI.<jsm>create</jsm>(<js>"request:/"</js>),
-				URI.<jsm>create</jsm>(<js>"request:/.."</js>)
-			};
-		}
-	}	
-	</p>
-	<p>
-		When requested as JSON, it produces the following result:
-	</p>
-	<p class='bcode w800'>
-	{
-		<jok>f1a</jok>:<jov>'http://www.apache.org/f1a'</jov>,
-		<jok>f1b</jok>:<jov>'http://foo.com:123/f1b'</jov>,
-		<jok>f1c</jok>:<jov>'http://foo.com:123/f1c/x/y'</jov>,
-		<jok>f1d</jok>:<jov>'http://foo.com:123/myContext/myServlet/f1d'</jov>,
-		<jok>f1e</jok>:<jov>'http://foo.com:123/myContext/myServlet/f1e/x/y'</jov>,
-		<jok>f1f</jok>:<jov>'http://foo.com:123/myContext/myServlet'</jov>,
-		<jok>f2a</jok>:<jov>'http://foo.com:123/myContext/f2a/x'</jov>,
-		<jok>f2b</jok>:<jov>'http://foo.com:123/myContext/f2b'</jov>,
-		<jok>f2c</jok>:<jov>'http://foo.com:123/myContext'</jov>,
-		<jok>f2d</jok>:<jov>'http://foo.com:123'</jov>,
-		<jok>f3a</jok>:<jov>'http://foo.com:123/myContext/myServlet/f3a/x'</jov>,
-		<jok>f3b</jok>:<jov>'http://foo.com:123/myContext/myServlet/f3b'</jov>,
-		<jok>f3c</jok>:<jov>'http://foo.com:123/myContext/myServlet'</jov>,
-		<jok>f3d</jok>:<jov>'http://foo.com:123/myContext'</jov>,
-		<jok>f4a</jok>:<jov>'http://foo.com:123/myContext/myServlet/myPath/f4a/x'</jov>,
-		<jok>f4b</jok>:<jov>'http://foo.com:123/myContext/myServlet/myPath/f4b'</jov>,
-		<jok>f4c</jok>:<jov>'http://foo.com:123/myContext/myServlet/myPath'</jov>,
-		<jok>f4d</jok>:<jov>'http://foo.com:123/myContext/myServlet'</jov>
-	}
-	</p>
-	<p>
-		URI resolution is controlled by the following settings:
-	</p>
-	<ul class='javatree'>
-		<li class='jc'>{@link org.apache.juneau.rest.RestContext}
-		<ul>
-			<li class='jf'>{@del org.apache.juneau.rest.RestContext#REST_uriAuthority REST_uriAuthority}
-			<li class='jf'>{@del org.apache.juneau.rest.RestContext#REST_uriContext REST_uriContext}
-			<li class='jf'>{@del org.apache.juneau.rest.RestContext#REST_uriRelativity REST_uriRelativity}
-			<li class='jf'>{@del org.apache.juneau.rest.RestContext#REST_uriResolution REST_uriResolution}
-		</ul>	
-	</ul>
-	
-	<p>
-		URIs are resolved by both regular and part serializers.
-	</p>
-</div>
-</div><!-- END: 6.8 - juneau-rest-server.jrs.HandlingUris -->
-
-<!-- ==================================================================================================== -->
-
-<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Guards' id='juneau-rest-server.jrs.Guards'>6.9 - Guards</a><span class='update'><b><red>todo</red></b></span></h3>
-<div class='topic'><!-- START: 6.9 - juneau-rest-server.jrs.Guards -->
-<div class='topic'>
-	<p>
-		Guards are classes that control access to REST classes and methods.
+		Guards control access to REST classes and methods.
+		When guards are associated at the class-level, it's equivalent to associating guards on all Java methods on 
+		the servlet.
+		If multiple guards are present, ALL guards must pass.  (Note that this is different in behavior to {@doc jrs.Matchers Matchers}
+		which require only one matcher to pass.)
 	</p>
 	<p>
 		Guards are associated with resource classes and methods via the following:
 	</p>
-	<ul class='javatree'>
+	<ul class='javatreec'>
 		<li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#guards() Rest(guards)} 
 		<li class='ja'>{@link org.apache.juneau.rest.annotation.RestOp#guards() RestOp(guards)} 
-		<li class='jm'>{@del org.apache.juneau.rest.RestContext.Builder#guards(Class...)} 
 	</ul>
+	<h5 class='figure'>Example:</h5>
 	<p class='bcode w800'>
 	<jc>// Define a guard that only lets Billy make a request</jc>
 	<jk>public</jk> BillyGuard <jk>extends</jk> RestGuard {
@@ -17240,7 +17119,7 @@
 	</p>
 	<p class='bcode w800'>
 	<jc>// DELETE method</jc>
-	<ja>@RestDDelete</ja>(guards={AdminGuard.<jk>class</jk>})
+	<ja>@RestDelete</ja>(guards={AdminGuard.<jk>class</jk>})
 	<jk>public void</jk> doDelete(RestRequest <jv>req</jv>, RestResponse <jv>res</jv>) <jk>throws</jk> Exception {...}
 	</p>
 	<p class='bcode w800'>
@@ -17254,7 +17133,7 @@
 	</p>
 	<p>
 		A guard failure results in an <l>HTTP 401 Unauthorized</l> response.
-		However, this can be configured by overriding the 
+		However, this can be configured by overriding 
 		{@link org.apache.juneau.rest.guard.RestGuard#guard(RestRequest,RestResponse)} and processing the response 
 		yourself.
 	</p>
@@ -17262,53 +17141,23 @@
 	<jk>public class</jk> AdminGuard <jk>extends</jk> RestGuard {
 
 		<ja>@Override</ja> <jc>/* RestGuard */</jc>
-		<jk>public boolean</jk> guard(RestRequest <jv>req</jv>, RestResponse <jv>res</jv>) <jk>throws</jk> RestException {
+		<jk>public boolean</jk> guard(RestRequest <jv>req</jv>, RestResponse <jv>res</jv>) <jk>throws</jk> BasicHttpException {
 			<jk>if</jk> (! isOkay(req))
-				<jk>throw new</jk> RestException(<jsf>SC_FORBIDDEN</jsf>, <js>"Access denied!!!"</js>);
+				<jk>throw new</jk> Forbidden(<js>"Access denied!!!"</js>);
 			<jk>return true</jk>;
 		}
 	}
 	</p>
 	<p>
-		When guards are associated at the class-level, it's equivalent to associating guards on all Java methods on 
-		the servlet.
-		If multiple guards are present, ALL guards must pass.
+		A simplified format is available for matching based on the user role on the request using the following:
 	</p>
-	<ul class='seealso'>
-		<li class='jf'>{@del org.apache.juneau.rest.RestContext#REST_guards}
-	</ul>
-</div>
-</div><!-- END: 6.9 - juneau-rest-server.jrs.Guards -->
-
-<!-- ==================================================================================================== -->
-
-<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.RoleGuards' id='juneau-rest-server.jrs.RoleGuards'>6.10 - Role guards</a><span class='update'>created: 8.1.0, <b><red>todo</red></b></span></h3>
-<div class='topic'><!-- START: 6.10 - juneau-rest-server.jrs.RoleGuards -->
-<div class='topic'>
-	<p>
-		Specialized guards are provided for controlling access to servlet classes and methods based on user roles.
-		These are controlled via annotations on the REST class and methods:
-	</p>
-	<ul class='javatree'>
-		<li class='ja'>{@link org.apache.juneau.rest.annotation.Rest}
-		<ul>
-			<li class='jf'>{@link org.apache.juneau.rest.annotation.Rest#roleGuard() roleGuard()}
-			<li class='jf'>{@link org.apache.juneau.rest.annotation.Rest#rolesDeclared() rolesDeclared()}
-		</ul>
-		<li class='ja'>{@link org.apache.juneau.rest.annotation.RestOp}
-		<ul>
-			<li class='jf'>{@link org.apache.juneau.rest.annotation.RestOp#roleGuard() roleGuard()}
-			<li class='jf'>{@link org.apache.juneau.rest.annotation.RestOp#rolesDeclared() rolesDeclared()}
-		</ul>
+	
+	<ul class='javatreec'>
+		<li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#roleGuard() Rest(roleGuard)} 
+		<li class='ja'>{@link org.apache.juneau.rest.annotation.RestOp#roleGuard() RestOp(roleGuard)} 
 	</ul>
-	<p>
-		The <c>roleGuard()</c> annotation is an expression that defines whether a user with specified roles are allowed
-		to access methods.
-	</p>
 	<h5 class='figure'>Example:</h5>
 	<p class='bcode w800'>
-	<jc>// Only admin users or users with both read/write and special access 
-	// can run any methods on this class.</jc>
 	<ja>@Rest</ja>(
 		path=<js>"/foo"</js>,
 		roleGuard=<js>"ROLE_ADMIN || (ROLE_READ_WRITE &amp;&amp; ROLE_SPECIAL)"</js>
@@ -17317,67 +17166,26 @@
 		...
 	}
 	</p>
-	<p>
-		The syntax allows for any of the following:
-	</p>
-	<ul>
-		<li><js>"foo"</js> - Single arguments.
-		<li><js>"foo,bar,baz"</js> - Multiple OR'ed arguments.
-		<li><js>"foo | bar | baz"</js> - Multiple OR'ed arguments, pipe syntax.
-		<li><js>"foo || bar || baz"</js> - Multiple OR'ed arguments, Java-OR syntax.
-		<li><js>"fo*"</js> - Patterns including <js>'*'</js> and <js>'?'</js>.
-		<li><js>"fo* &amp; *oo"</js> - Multiple AND'ed arguments, ampersand syntax.
-		<li><js>"fo* &amp;&amp; *oo"</js> - Multiple AND'ed arguments, Java-AND syntax.
-		<li><js>"fo* || (*oo || bar)"</js> - Parenthesis.
-	</ul>
-	
-	<p>
-	 	If patterns are used, you must specify the list of declared roles using the <c>rolesDeclared()</c> annotations.
-	 	This declares the list of all possible user roles and is needed because the servlet API does not provide this
-	 	capability.
-	</p>
-	
-	<h5 class='figure'>Example:</h5>
-	<p class='bcode w800'>
-	<ja>@Rest</ja>(
-		rolesDeclared=<js>"ROLE_ADMIN,ROLE_READ_WRITE,ROLE_READ_ONLY,ROLE_SPECIAL"</js>,
-		roleGuard=<js>"ROLE_ADMIN || (*WRITE* &amp;&amp; *SPECIAL*)"</js>
-	)
-	<jk>public class</jk> MyResource <jk>extends</jk> RestServlet {
-		...
-	}
-	</p>
 </div>
-</div><!-- END: 6.10 - juneau-rest-server.jrs.RoleGuards -->
+</div><!-- END: 6.7 - juneau-rest-server.jrs.Guards -->
 
 <!-- ==================================================================================================== -->
 
-<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Converters' id='juneau-rest-server.jrs.Converters'>6.11 - Converters</a><span class='update'><b><red>todo</red></b></span></h3>
-<div class='topic'><!-- START: 6.11 - juneau-rest-server.jrs.Converters -->
+<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Converters' id='juneau-rest-server.jrs.Converters'>6.8 - Converters</a><span class='update'>updated: <b>9.0.0</b></span></h3>
+<div class='topic'><!-- START: 6.8 - juneau-rest-server.jrs.Converters -->
 <div class='topic'>
 	<p>
-		Converters can be thought of as "post-processors" for POJOs before they get passed to the serializers.
+		Converters can be thought of as "post-processors" for response POJOs before they get passed to the serializer.
 	</p>
 	<p>
 		Converters are associated with resource classes and methods via the following:
 	</p>
-	<ul class='javatree'>
+	<ul class='javatreec'>
 		<li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#converters() Rest(converters)} 
 		<li class='ja'>{@link org.apache.juneau.rest.annotation.RestOp#converters() RestOp(converters)} 
-		<li class='jm'>{@del org.apache.juneau.rest.RestContext.Builder#converters(Class...)} 
 	</ul>
 	<h5 class='figure'>Example:</h5>
 	<p class='bcode w800'>
-	<jc>// Associate the Traversable converter to all Java REST methods in this servlet</jc>
-	<ja>@Rest</ja>(converters=Traversable.<jk>class</jk>)
-	<jk>public</jk> MyRestServlet <jk>extends</jk> BasicRestServlet {
-		...
-	}
-	</p>
-	<p>
-		They can also be defined at the method level:
-	</p>
-	<p class='bcode w800'>
 	<jc>// GET person request handler.</jc>
 	<jc>// Traversable conversion enabled to allow nodes in returned POJO tree to be addressed.</jc>
 	<jc>// Queryable conversion enabled to allow returned POJO to be searched/viewed/sorted.</jc>
@@ -17390,51 +17198,12 @@
 	}
 	</p>	
 	<p>
-		The following converter is used to provide support for addressing child nodes in a POJO tree with URL path 
-		remainders.  
-		In this code, the 3rd parameter is the object that was returned by the Java method.
-		The converter uses the {@link org.apache.juneau.utils.PojoRest} wrapper class to address nodes in the 
-		tree.
-	</p>
-	<p class='bcode w800'>
-	<jd>/**
-	 * Converter for enablement of PojoRest support on response objects returned by a @RestOp method.
-	 * When enabled, objects in a POJO tree returned by the REST method can be addressed through additional URL path information.
-	 */</jd>
-	<jk>public class</jk> Traversable <jk>implements</jk> RestConverter {
-	
-		<ja>@Override</ja> <jc>/* RestConverter */</jc>
-		<jk>public</jk> Object convert(RestRequest <jv>req</jv>, Object <jv>o</jv>) <jk>throws</jk> RestException {
-			<jk>if</jk> (<jv>o</jv> == <jk>null</jk>)
-				<jk>return null</jk>;
-	
-			String <jv>pathRemainder</jv> = <jv>req</jv>.getPathMatch().getRemainder();
-	
-			<jk>if</jk> (<jv>pathRemainder</jv> != <jk>null</jk>) {
-				<jk>try</jk> {
-				
-					<jc>// Use the PojoRest class to traverse our POJO model.</jc> 
-					PojoRest <jv>p</jv> = <jk>new</jk> PojoRest(<jv>o</jv>);
-					<jv>o</jv> = <jv>p</jv>.get(<jv>pathRemainder</jv>);
-				
-				} <jk>catch</jk> (PojoRestException <jv>e</jv>) {
-					<jk>throw new</jk> RestException(<jv>e</jv>.getStatus(), <jv>e</jv>);
-				} <jk>catch</jk> (Exception <jv>e</jv>) {
-					<jk>throw new</jk> RestException(HttpServletResponse.<jsf>SC_INTERNAL_SERVER_ERROR</jsf>, <jv>e</jv>);
-				}
-			}
-			
-			<jk>return</jk> <jv>o</jv>;
-		}
-	}
-	</p>	
-	<p>
 		Juneau defines the following converters out-of-the-box:
 	</p>
 	<ul class='javatree'>
 		<li class='jic'>
-		{@link org.apache.juneau.rest.RestConverter}
-		<ul>
+		{@link org.apache.juneau.rest.converter.RestConverter}
+		<ul class='spaced-list'>
 			<li class='jc'>
 				{@link org.apache.juneau.rest.converter.Queryable}
 				<br>Provides query parameters that can be used to transform the response (i.e. search/view/sort the 
@@ -17449,17 +17218,13 @@
 				serialized as the response.
 		</ul>
 	</ul>
-	
-	<ul class='seealso'>
-		<li class='jf'>{@del org.apache.juneau.rest.RestContext#REST_converters} 
-	</ul>
 </div>
-</div><!-- END: 6.11 - juneau-rest-server.jrs.Converters -->
+</div><!-- END: 6.8 - juneau-rest-server.jrs.Converters -->
 
 <!-- ==================================================================================================== -->
 
-<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Messages' id='juneau-rest-server.jrs.Messages'>6.12 - Messages</a><span class='update'>updated: 8.2.0, <b><red>todo</red></b></span></h3>
-<div class='topic'><!-- START: 6.12 - juneau-rest-server.jrs.Messages -->
+<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.LocalizedMessages' id='juneau-rest-server.jrs.LocalizedMessages'>6.9 - Localized Messages</a><span class='update'>updated: 8.2.0,<b>9.0.0</b></span></h3>
+<div class='topic'><!-- START: 6.9 - juneau-rest-server.jrs.LocalizedMessages -->
 <div class='topic'>
 	<p>
 		The {@link org.apache.juneau.rest.annotation.Rest#messages @Rest(messages)} annotation identifies the location of the resource bundle 
@@ -17482,15 +17247,14 @@
 	</ul>
 	
 	<p>
-		This annotation is used to provide request-localized (based on <c>Accept-Language</c>) messages for the following methods:
+		This annotation is used to provide request-localized (based on <c>Accept-Language</c>) messages for the following method:
 	</p>
 	<ul class='javatree'>
 		<li class='jm'>{@link org.apache.juneau.rest.RestRequest#getMessage(String, Object...)}
-		<li class='jm'>{@link org.apache.juneau.rest.RestContext#getMessages() RestContext.getMessages()}
 	</ul>
 	
 	<p>
-		Request-localized messages are also available by passing either of the following parameter types into your Java method:
+		Request-localized messages are also available by passing either of the following args into your Java method:
 	</p>
 	<ul class='javatree'>
 		<li class='jc'>{@link java.util.ResourceBundle} - Basic Java resource bundle.
@@ -17547,18 +17311,13 @@
 		Messages are automatically inherited from super classes.  If a string cannot be found in the bundle of the current
 		class, it will be searched for up the class hierarchy.
 	</p>
-	
-	<ul class='seealso'>
-		<li class='jc'>{@link org.apache.juneau.cp.Messages}
-		<li class='jf'>{@del org.apache.juneau.rest.RestContext#REST_messages}
-	</ul>
 </div>
-</div><!-- END: 6.12 - juneau-rest-server.jrs.Messages -->
+</div><!-- END: 6.9 - juneau-rest-server.jrs.LocalizedMessages -->
 
 <!-- ==================================================================================================== -->
 
-<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Encoders' id='juneau-rest-server.jrs.Encoders'>6.13 - Encoders</a><span class='update'><b><red>todo</red></b></span></h3>
-<div class='topic'><!-- START: 6.13 - juneau-rest-server.jrs.Encoders -->
+<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Encoders' id='juneau-rest-server.jrs.Encoders'>6.10 - Encoders</a><span class='update'>updated: <b>9.0.0</b></span></h3>
+<div class='topic'><!-- START: 6.10 - juneau-rest-server.jrs.Encoders -->
 <div class='topic'>
 	<p>
 		The {@link org.apache.juneau.rest.annotation.Rest#encoders @Rest(encoders)} annotation can 
@@ -17578,27 +17337,209 @@
 	<p>
 		Juneau defines the following encoders out-of-the-box:
 	</p>
-	<ul class='javatree'>
-		<li class='jac'>
-		{@link org.apache.juneau.encoders.Encoder}
-		<ul>
-			<li class='jc'>
-				{@link org.apache.juneau.encoders.GzipEncoder}
-			<li class='jc'>
-				{@link org.apache.juneau.encoders.IdentityEncoder}
-		</ul>
-	</ul>
+	<ul class='javatree'>
+		<li class='jac'>
+		{@link org.apache.juneau.encoders.Encoder}
+		<ul>
+			<li class='jc'>
+				{@link org.apache.juneau.encoders.GzipEncoder}
+			<li class='jc'>
+				{@link org.apache.juneau.encoders.IdentityEncoder}
+		</ul>
+	</ul>
+</div>
+</div><!-- END: 6.10 - juneau-rest-server.jrs.Encoders -->
+
+<!-- ==================================================================================================== -->
+
+<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.ConfigurationFiles' id='juneau-rest-server.jrs.ConfigurationFiles'>6.11 - Configuration Files</a><span class='update'>updated: <b>9.0.0</b></span></h3>
+<div class='topic'><!-- START: 6.11 - juneau-rest-server.jrs.ConfigurationFiles -->
+<div class='topic'>
+	<p>
+		The Server API provides methods for associating configuration files with REST servlets so that 
+		configuration properties can be defined in external files.  It uses the following annotation:
+	</p>
+	<ul class='javatree'>
+		<li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#config() Rest(config)}
+	</ul>
+	
+	<h5 class='figure'>Example:</h5>
+	<p class='bcode w800'>
+	<ja>@Rest</ja>(
+		<jc>// Config file is located at ./config_dir/myconfig.cfg</jc>
+		config=<js>"config_dir/myconfig.cfg"</js>,
+		...
+	)
+	<jk>public class</jk> MyResource {...}
+	</p>
+	<p>
+		In recap, the Configuration API provides support for INI-style configuration files with embedded string variables:
+	</p>
+	
+	<h5 class='figure'>Example:</h5>
+	<p class='bcode w800'>
+	<cc>#--------------------------</cc>
+	<cc># Examples </cc>
+	<cc>#--------------------------</cc>
+	<cs>[MyProperties]</cs>
+	<ck>path</ck> = <cv>$E{PATH}</cv>
+	<ck>javaHome</ck> = <cv>$S{java.home}</cv>
+	<ck>customMessage</ck> = <cv>Java home is $C{MyProperties/javaHome} and the environment path is $C{MyProperties/path}.</cv>
+	</p>
+	<p>
+		These properties are then accessible through the {@link org.apache.juneau.config.Config} class.
+	</p>
+	<p class='bcode w800'>
+		<ja>@RestGet</ja>(<js>"/"</js>)
+		<jk>public</jk> String sample(Config <jv>config</jv>) {
+			String <jv>path</jv> = <jv>config</jv>.getString(<js>"MyProperties/path"</js>);
+			File <jv>javaHome</jv> = <jv>config</jv>.getObject(<js>"MyProperties/javaHome"</js>, File.<jk>class</jk>);
+			String <jv>customMessage</jv> = <jv>config</jv>.getString(<js>"MyProperties/customMessage"</js>);
+			...
+		}
+	</p>
+	<p>
+		The annotation itself can contain string variables.  
+		For example, the Microservice API {@link org.apache.juneau.rest.BasicRestServlet} class defines the 
+		location of the config file as a system property <l>"juneau.configFile"</l>:
+	</p>
+	<p class='bcode w800'>
+	<ja>@Rest</ja>(
+		<jc>// Config file location is defined as a system property</jc>
+		config=<js>"$S{juneau.configFile}"</js>,
+		...
+	)
+	<jk>public class</jk> MyResource {...}
+	</p>
+	<p>
+		Spring Boot applications typically define an <c>application.properties</c> file.  You can reuse it
+		as a config file like so:
+	</p>
+	<p class='bcode w800'>
+	<ja>@Rest</ja>(
+		config=<js>"application.properties"</js>,
+		...
+	)
+	<jk>public class</jk> MyResource {...}
+	</p>
+	<p>
+		Note that properties files are a subset of functionality of INI files (they're basically just INI files with a single default section).  
+		It's therefore possible to use INI-style syntax such as sections in your <c>application.properties</c> file.  
+	</p>
+	<p>
+		Once a config file has been associated with a REST resource, it can be accessed through one of the following:
+		{@link org.apache.juneau.rest.RestContext.Builder#getConfig()} method.  It can also be access by passing in a {@link org.apache.juneau.config.Config} bean to any of your
+		REST OP methods.
+	</p>
+	<p>
+		A common usage is to use this method to initialize fields in your servlet.
+	</p>
+	<p class='bcode w800'>
+	<ja>@Rest</ja>(
+		<jc>// Config file is located at ./config_dir/myconfig.cfg</jc>
+		config=<js>"config_dir/myconfig.cfg"</js>,
+		...
+	)
+	<jk>public class</jk> MyResource {
+		<jk>private final</jk> String <jf>path</jf>;
+		<jk>private final</jk> File <jf>javaHome</jf>;
+	
+		<jk>public</jk> MyResource(RestContext.Builder builder) {
+			Config c = builder.getConfig();
+			<jf>path</jf> = c.getString(<js>"MyProperties/path"</js>);
+			<jf>javaHome</jf> = c.getObject(File.<jk>class</jk>, <js>"MyProperties/javaHome"</js>);
+		}
+	</p>
+	<p>
+		Another common usage is to refer to config properties through <ck>$C</ck> variables in your annotations:
+	</p>
+	<p class='bcode w800'>
+	<ja>@Rest</ja>
+	<jc>// Get stylesheet from myconfig.cfg, but default to devops.css if it's not specified</jc>
+	<ja>@HtmlDoc</ja>(
+		stylesheet=<js>"$C{MyServlet/stylesheet,servlet:/styles/devops.css}"</js>,
+	)
+	<jk>public class</jk> MyResource {...}
+	</p>
+	<p>
+		It's even possible to reference request-level variables in your config file if you use 
+		{@link org.apache.juneau.rest.RestRequest#getConfig()} to access the config file:
+	</p>
+	<p class='bcode w800'>
+	<cc>#-------------------------------------</cc>
+	<cc># Contents of config_dir/myconfig.cfg </cc>
+	<cc>#-------------------------------------</cc>
+	<cs>[HelloWorldResource]</cs>
+	<ck>message</ck> = <cv>Hello $RQ{person}!</cv>
+	</p>
+	<p class='bcode w800'>
+	<jd>/** 
+	 * Sample REST resource that prints out a simple "Hello world!" message.
+	 */</jd>
+	 <ja>@Rest</ja>(
+		config=<js>"config_dir/myconfig.cfg"</js>,
+		...
+	)
+	<jk>public class</jk> HelloWorldResource <jk>extends</jk> BasicRestServlet {
+		
+		<jd>/** 
+		 * GET request handler.
+		 * Specify the GET parameter "?person=X" for a specialized message! 
+		 */</jd>
+		<ja>@RestGet</ja>(<js>"/"</js>)
+		<jk>public</jk> String sayHello(Config <jv>config</jv>) {
+			<jk>return</jk> <jv>config</jv>.getString(<js>"HelloWorldResource/message"</js>);
+		}
+	}
+	</p>
+	<p>
+		You can even add resource bundles into the mix:
+	</p>
+	<p class='bcode w800'>
+	<cc>#-------------------------------------</cc>
+	<cc># Contents of config_dir/myconfig.cfg </cc>
+	<cc>#-------------------------------------</cc>
+	<cs>[HelloWorldResource]</cs>
+	<ck>message</ck> = <cv>$L{localizedMessage,$RQ{person}}</cv>
+	</p>
+	<p class='bcode w800'>
+	<cc>#-------------------------------------------</cc>
+	<cc># Contents of HelloWorldResource.properties </cc>
+	<cc>#-------------------------------------------</cc>
+	<ck>localizedMessage</ck> = <cv>Hello {0}!</cv>
+	</p>
+	<p class='bcode w800'>
+	<jd>/** 
+	 * Sample REST resource that prints out a simple "Hello world!" message.
+	 */</jd>
+	<ja>@Rest</ja>(
+		messages=<js>"HelloWorldResources"</js>,
+		config=<js>"config_dir/myconfig.cfg"</js>,
+		...
+	)
+	<jk>public class</jk> HelloWorldResource <jk>extends</jk> BasicRestServlet {
+		
+		<jd>/** 
+		 * GET request handler.
+		 * Specify the GET parameter "?person=X" for a specialized message! 
+		 */</jd>
+		<ja>@RestGet</ja>(<js>"/"</js>)
+		<jk>public</jk> String sayHello(RestRequest <jv>req</jv>) {
+			<jk>return</jk> <jv>req</jv>.getConfig().getString(<js>"HelloWorldResource/message"</js>);
+		}
+	}
+	</p>
 	
 	<ul class='seealso'>
-		<li class='jf'>{@del org.apache.juneau.rest.RestContext#REST_encoders}
+		<li>{@doc juneau-config}
 	</ul>
 </div>
-</div><!-- END: 6.13 - juneau-rest-server.jrs.Encoders -->
+</div><!-- END: 6.11 - juneau-rest-server.jrs.ConfigurationFiles -->
 
 <!-- ==================================================================================================== -->
 
-<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.SvlVariables' id='juneau-rest-server.jrs.SvlVariables'>6.14 - SVL Variables</a><span class='update'><b><red>todo</red></b></span></h3>
-<div class='topic'><!-- START: 6.14 - juneau-rest-server.jrs.SvlVariables -->
+<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.SvlVariables' id='juneau-rest-server.jrs.SvlVariables'>6.12 - SVL Variables</a><span class='update'><b><red>todo</red></b></span></h3>
+<div class='topic'><!-- START: 6.12 - juneau-rest-server.jrs.SvlVariables -->
 <div class='topic'>
 	<p>	
 		In the previous examples, there were several cases where embedded variables were contained within
@@ -17869,184 +17810,12 @@
 		</tr>
 	</table>
 </div>
-</div><!-- END: 6.14 - juneau-rest-server.jrs.SvlVariables -->
-
-<!-- ==================================================================================================== -->
-
-<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.ConfigurationFiles' id='juneau-rest-server.jrs.ConfigurationFiles'>6.15 - Configuration Files</a><span class='update'><b><red>todo</red></b></span></h3>
-<div class='topic'><!-- START: 6.15 - juneau-rest-server.jrs.ConfigurationFiles -->
-<div class='topic'>
-	<p>
-		The Server API provides methods for associating configuration files with REST servlets so that 
-		configuration properties can be defined in external files.
-	</p>
-	<p>
-		In recap, the Configuration API provides support for INI-style configuration files with embedded string variables:
-	</p>
-	
-	<h5 class='figure'>Example:</h5>
-	<p class='bcode w800'>
-	<cc>#--------------------------</cc>
-	<cc># Examples </cc>
-	<cc>#--------------------------</cc>
-	<cs>[MyProperties]</cs>
-	<ck>path</ck> = <cv>$E{PATH}</cv>
-	<ck>javaHome</ck> = <cv>$S{java.home}</cv>
-	<ck>customMessage</ck> = <cv>Java home is $C{MyProperties/javaHome} and the environment path is $C{MyProperties/path}.</cv>
-	</p>
-	<p>
-		These properties are then accessible through the {@link org.apache.juneau.config.Config} class.
-	</p>
-	<p class='bcode w800'>
-	Config c = Config.<jsm>create</jsm>(<js>"myconfig.cfg"</js>).build();
-	String path = c.getString(<js>"MyProperties/path"</js>);
-	File javaHome = c.getObject(<js>"MyProperties/javaHome"</js>, File.<jk>class</jk>);
-	String customMessage = c.getString(<js>"MyProperties/customMessage"</js>);
-	</p>
-	<p>
-		Configuration files are associated with REST resources through the following:
-	</p>
-	<ul class='javatree'>
-		<li class='ja'>{@link org.apache.juneau.rest.annotation.Rest#config() Rest(config)}
-	</ul>
-	
-	<h5 class='figure'>Example:</h5>
-	<p class='bcode w800'>
-	<ja>@Rest</ja>(
-		<jc>// Config file is located at ./config_dir/myconfig.cfg</jc>
-		config=<js>"config_dir/myconfig.cfg"</js>,
-		...
-	)
-	<jk>public class</jk> MyResource {...}
-	</p>
-	<p>
-		The annotation itself can contain string variables.  
-		For example, the Microservice API {@link org.apache.juneau.rest.BasicRestServlet} class defines the 
-		location of the config file as a system property <l>"juneau.configFile"</l>:
-	</p>
-	<p class='bcode w800'>
-	<ja>@Rest</ja>(
-		<jc>// Config file location is defined as a system property</jc>
-		config=<js>"$S{juneau.configFile}"</js>,
-		...
-	)
-	<jk>public class</jk> MyResource {...}
-	</p>
-	<p>
-		Once a config file has been associated with a REST resource, it can be accessed through the 
-		{@link org.apache.juneau.rest.RestContext.Builder#getConfig()} method.
-	</p>
-	<p>
-		A common usage is to use this method to initialize fields in your servlet.
-	</p>
-	<p class='bcode w800'>
-	<ja>@Rest</ja>(
-		<jc>// Config file is located at ./config_dir/myconfig.cfg</jc>
-		config=<js>"config_dir/myconfig.cfg"</js>,
-		...
-	)
-	<jk>public class</jk> MyResource  {
-		<jk>private final</jk> String <jf>path</jf>;
-		<jk>private final</jk> File <jf>javaHome</jf>;
-	
-		<jk>public</jk> MyResource(RestContext.Builder builder) {
-			Config c = builder.getConfig();
-			<jf>path</jf> = c.getString(<js>"MyProperties/path"</js>);
-			<jf>javaHome</jf> = c.getObject(File.<jk>class</jk>, <js>"MyProperties/javaHome"</js>);
-		}
-	</p>
-	<p>
-		Another common usage is to refer to config properties through <ck>$C</ck> variables in your annotations:
-	</p>
-	<p class='bcode w800'>
-	<ja>@Rest</ja>(
-		<jc>// Get stylesheet from myconfig.cfg, but default to devops.css if it's not specified</jc>
-		htmldoc=<ja>@HtmlDoc</ja>(
-			stylesheet=<js>"$C{MyServlet/stylesheet,servlet:/styles/devops.css}"</js>,
-		)
-		...
-	)
-	<jk>public class</jk> MyResource {...}
-	</p>
-	<p>
-		It's even possible to reference request-level variables in your config file if you use 
-		{@link org.apache.juneau.rest.RestRequest#getConfig()} to access the config file:
-	</p>
-	<p class='bcode w800'>
-	<cc>#-------------------------------------</cc>
-	<cc># Contents of config_dir/myconfig.cfg </cc>
-	<cc>#-------------------------------------</cc>
-	<cs>[HelloWorldResource]</cs>
-	<ck>message</ck> = <cv>Hello $RQ{person}!</cv>
-	</p>
-	<p class='bcode w800'>
-	<jd>/** 
-	 * Sample REST resource that prints out a simple "Hello world!" message.
-	 */</jd>
-	 <ja>@Rest</ja>(
-		config=<js>"config_dir/myconfig.cfg"</js>,
-		...
-	)
-	<jk>public class</jk> HelloWorldResource <jk>extends</jk> BasicRestServlet {
-		
-		<jd>/** 
-		 * GET request handler.
-		 * Specify the GET parameter "?person=X" for a specialized message! 
-		 */</jd>
-		<ja>@RestGet</ja>(<js>"/"</js>)
-		<jk>public</jk> String sayHello(RestRequest <jv>req</jv>) {
-			<jk>return</jk> <jv>req</jv>.getConfig().getString(<js>"HelloWorldResource/message"</js>);
-		}
-	}
-	</p>
-	<p>
-		You can even add resource bundles into the mix:
-	</p>
-	<p class='bcode w800'>
-	<cc>#-------------------------------------</cc>
-	<cc># Contents of config_dir/myconfig.cfg </cc>
-	<cc>#-------------------------------------</cc>
-	<cs>[HelloWorldResource]</cs>
-	<ck>message</ck> = <cv>$L{localizedMessage,$RQ{person}}</cv>
-	</p>
-	<p class='bcode w800'>
-	<cc>#-------------------------------------------</cc>
-	<cc># Contents of HelloWorldResource.properties </cc>
-	<cc>#-------------------------------------------</cc>
-	<ck>localizedMessage</ck> = <cv>Hello {0}!</cv>
-	</p>
-	<p class='bcode w800'>
-	<jd>/** 
-	 * Sample REST resource that prints out a simple "Hello world!" message.
-	 */</jd>
-	<ja>@Rest</ja>(
-		messages=<js>"HelloWorldResources"</js>,
-		config=<js>"config_dir/myconfig.cfg"</js>,
-		...
-	)
-	<jk>public class</jk> HelloWorldResource <jk>extends</jk> BasicRestServlet {
-		
-		<jd>/** 
-		 * GET request handler.
-		 * Specify the GET parameter "?person=X" for a specialized message! 
-		 */</jd>
-		<ja>@RestGet</ja>(<js>"/"</js>)
-		<jk>public</jk> String sayHello(RestRequest <jv>req</jv>) {
-			<jk>return</jk> <jv>req</jv>.getConfig().getString(<js>"HelloWorldResource/message"</js>);
-		}
-	}
-	</p>
-	
-	<ul class='seealso'>
-		<li>{@doc juneau-config}
-	</ul>
-</div>
-</div><!-- END: 6.15 - juneau-rest-server.jrs.ConfigurationFiles -->
+</div><!-- END: 6.12 - juneau-rest-server.jrs.SvlVariables -->
 
 <!-- ==================================================================================================== -->
 
-<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.StaticFiles' id='juneau-rest-server.jrs.StaticFiles'>6.16 - Static files</a><span class='update'><b><red>todo</red></b></span></h3>
-<div class='topic'><!-- START: 6.16 - juneau-rest-server.jrs.StaticFiles -->
+<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.StaticFiles' id='juneau-rest-server.jrs.StaticFiles'>6.13 - Static files</a><span class='update'><b><red>todo</red></b></span></h3>
+<div class='topic'><!-- START: 6.13 - juneau-rest-server.jrs.StaticFiles -->
 <div class='topic'>
 	<p>
 		The {@link org.apache.juneau.rest.annotation.Rest#staticFiles @Rest(staticFiles)} 
@@ -18094,12 +17863,12 @@
 		<li class='jf'>{@del org.apache.juneau.rest.RestContext#REST_staticFiles}
 	</ul>
 </div>
-</div><!-- END: 6.16 - juneau-rest-server.jrs.StaticFiles -->
+</div><!-- END: 6.13 - juneau-rest-server.jrs.StaticFiles -->
 
 <!-- ==================================================================================================== -->
 
-<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.ClientVersioning' id='juneau-rest-server.jrs.ClientVersioning'>6.17 - Client Versioning</a><span class='update'><b><red>todo</red></b></span></h3>
-<div class='topic'><!-- START: 6.17 - juneau-rest-server.jrs.ClientVersioning -->
+<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.ClientVersioning' id='juneau-rest-server.jrs.ClientVersioning'>6.14 - Client Versioning</a><span class='update'><b><red>todo</red></b></span></h3>
+<div class='topic'><!-- START: 6.14 - juneau-rest-server.jrs.ClientVersioning -->
 <div class='topic'>
 	<p>
 		Client version headers are used to support backwards compatibility for breaking REST interface changes.
@@ -18143,12 +17912,12 @@
 		<li class='jf'>{@del org.apache.juneau.rest.RestContext#REST_clientVersionHeader}
 	</ul>
 </div>
-</div><!-- END: 6.17 - juneau-rest-server.jrs.ClientVersioning -->
+</div><!-- END: 6.14 - juneau-rest-server.jrs.ClientVersioning -->
 
 <!-- ==================================================================================================== -->
 
-<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.InfoProvider' id='juneau-rest-server.jrs.InfoProvider'>6.18 - RestInfoProvider</a><span class='update'><b><red>todo</red></b></span></h3>
-<div class='topic'><!-- START: 6.18 - juneau-rest-server.jrs.InfoProvider -->
+<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.InfoProvider' id='juneau-rest-server.jrs.InfoProvider'>6.15 - RestInfoProvider</a><span class='update'><b><red>todo</red></b></span></h3>
+<div class='topic'><!-- START: 6.15 - juneau-rest-server.jrs.InfoProvider -->
 <div class='topic'>
 	<p>
 		The {@del org.apache.juneau.rest.RestInfoProvider} class is used to find the title
@@ -18194,12 +17963,12 @@
 		from the <l>BasicRestInfoProvider</l> class described next.
 	</p>
 </div>
-</div><!-- END: 6.18 - juneau-rest-server.jrs.InfoProvider -->
+</div><!-- END: 6.15 - juneau-rest-server.jrs.InfoProvider -->
 
 <!-- ==================================================================================================== -->
 
-<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Swagger' id='juneau-rest-server.jrs.Swagger'>6.19 - Swagger</a><span class='update'><b><red>todo</red></b></span></h3>
-<div class='topic'><!-- START: 6.19 - juneau-rest-server.jrs.Swagger -->
+<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Swagger' id='juneau-rest-server.jrs.Swagger'>6.16 - Swagger</a><span class='update'><b><red>todo</red></b></span></h3>
+<div class='topic'><!-- START: 6.16 - juneau-rest-server.jrs.Swagger -->
 <div class='topic'>
 	<p>
 		One of the most useful features of Juneau is the ability to generate Swagger-based OPTIONS pages for self-documenting designs 
@@ -18217,8 +17986,8 @@
 
 <!-- ==================================================================================================== -->
 
-<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Swagger.jrs.BasicRestServletSwagger' id='juneau-rest-server.jrs.Swagger.jrs.BasicRestServletSwagger'>6.19.1 - BasicRestServlet</a><span class='update'>updated: 8.1.0, <b><red>todo</red></b></span></h4>
-<div class='topic'><!-- START: 6.19.1 - juneau-rest-server.jrs.Swagger.jrs.BasicRestServletSwagger -->
+<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Swagger.jrs.BasicRestServletSwagger' id='juneau-rest-server.jrs.Swagger.jrs.BasicRestServletSwagger'>6.16.1 - BasicRestServlet</a><span class='update'>updated: 8.1.0, <b><red>todo</red></b></span></h4>
+<div class='topic'><!-- START: 6.16.1 - juneau-rest-server.jrs.Swagger.jrs.BasicRestServletSwagger -->
 <div class='topic'>
 	<p>
 		Any subclass of {@link org.apache.juneau.rest.BasicRestServlet} gets an auto-generated Swagger UI when performing an <c>OPTIONS</c>
@@ -18295,12 +18064,12 @@
 		your own <ja>@RestOp</ja>-annotated method that returns a {@link org.apache.juneau.dto.swagger.Swagger} object and a {@link org.apache.juneau.dto.swagger.ui.SwaggerUI} swap.
 	</p>
 </div>
-</div><!-- END: 6.19.1 - juneau-rest-server.jrs.Swagger.jrs.BasicRestServletSwagger -->
+</div><!-- END: 6.16.1 - juneau-rest-server.jrs.Swagger.jrs.BasicRestServletSwagger -->
 
 <!-- ==================================================================================================== -->
 
-<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Swagger.jrs.BasicSwaggerInfo' id='juneau-rest-server.jrs.Swagger.jrs.BasicSwaggerInfo'>6.19.2 - Basic Swagger Info</a><span class='update'><b><red>todo</red></b></span></h4>
-<div class='topic'><!-- START: 6.19.2 - juneau-rest-server.jrs.Swagger.jrs.BasicSwaggerInfo -->
+<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Swagger.jrs.BasicSwaggerInfo' id='juneau-rest-server.jrs.Swagger.jrs.BasicSwaggerInfo'>6.16.2 - Basic Swagger Info</a><span class='update'><b><red>todo</red></b></span></h4>
+<div class='topic'><!-- START: 6.16.2 - juneau-rest-server.jrs.Swagger.jrs.BasicSwaggerInfo -->
 <div class='topic'>
 	<p>
 		Let's look at the various parts of the <c>Petstore</c> application Swagger UI to see how they are defined.
@@ -18463,12 +18232,12 @@
 		<li>Swagger JSON file
 	</ol>
 </div>
-</div><!-- END: 6.19.2 - juneau-rest-server.jrs.Swagger.jrs.BasicSwaggerInfo -->
+</div><!-- END: 6.16.2 - juneau-rest-server.jrs.Swagger.jrs.BasicSwaggerInfo -->
 
 <!-- ==================================================================================================== -->
 
-<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Swagger.jrs.SwaggerTags' id='juneau-rest-server.jrs.Swagger.jrs.SwaggerTags'>6.19.3 - Tags</a><span class='update'><b><red>todo</red></b></span></h4>
-<div class='topic'><!-- START: 6.19.3 - juneau-rest-server.jrs.Swagger.jrs.SwaggerTags -->
+<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Swagger.jrs.SwaggerTags' id='juneau-rest-server.jrs.Swagger.jrs.SwaggerTags'>6.16.3 - Tags</a><span class='update'><b><red>todo</red></b></span></h4>
+<div class='topic'><!-- START: 6.16.3 - juneau-rest-server.jrs.Swagger.jrs.SwaggerTags -->
 <div class='topic'>
 	<p>
 		Tags allow you to group operations into general categories.
@@ -18565,12 +18334,12 @@
 	</p>
 	<img class='bordered w900' src='doc-files/jrs.Swagger.5.png'>
 </div>
-</div><!-- END: 6.19.3 - juneau-rest-server.jrs.Swagger.jrs.SwaggerTags -->
+</div><!-- END: 6.16.3 - juneau-rest-server.jrs.Swagger.jrs.SwaggerTags -->
 
 <!-- ==================================================================================================== -->
 
-<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Swagger.jrs.SwaggerOperations' id='juneau-rest-server.jrs.Swagger.jrs.SwaggerOperations'>6.19.4 - Operations</a><span class='update'><b><red>todo</red></b></span></h4>
-<div class='topic'><!-- START: 6.19.4 - juneau-rest-server.jrs.Swagger.jrs.SwaggerOperations -->
+<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Swagger.jrs.SwaggerOperations' id='juneau-rest-server.jrs.Swagger.jrs.SwaggerOperations'>6.16.4 - Operations</a><span class='update'><b><red>todo</red></b></span></h4>
+<div class='topic'><!-- START: 6.16.4 - juneau-rest-server.jrs.Swagger.jrs.SwaggerOperations -->
 <div class='topic'>
 	<p>
 		<ja>@RestOp</ja>-annotated methods automatically get rendered as Swagger operations:
@@ -18610,12 +18379,12 @@
 	}
 	</p>
 </div>
-</div><!-- END: 6.19.4 - juneau-rest-server.jrs.Swagger.jrs.SwaggerOperations -->
+</div><!-- END: 6.16.4 - juneau-rest-server.jrs.Swagger.jrs.SwaggerOperations -->
 
 <!-- ==================================================================================================== -->
 
-<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Swagger.jrs.SwaggerParameters' id='juneau-rest-server.jrs.Swagger.jrs.SwaggerParameters'>6.19.5 - Parameters</a><span class='update'><b><red>todo</red></b></span></h4>
-<div class='topic'><!-- START: 6.19.5 - juneau-rest-server.jrs.Swagger.jrs.SwaggerParameters -->
+<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Swagger.jrs.SwaggerParameters' id='juneau-rest-server.jrs.Swagger.jrs.SwaggerParameters'>6.16.5 - Parameters</a><span class='update'><b><red>todo</red></b></span></h4>
+<div class='topic'><!-- START: 6.16.5 - juneau-rest-server.jrs.Swagger.jrs.SwaggerParameters -->
 <div class='topic'>
 	<p>
 		Expanding operations shows you a list of parameters:
@@ -18749,12 +18518,12 @@
 		Note that the schema information on the body parameter is automatically detected if not provided.
 	</p>
 </div>
-</div><!-- END: 6.19.5 - juneau-rest-server.jrs.Swagger.jrs.SwaggerParameters -->
+</div><!-- END: 6.16.5 - juneau-rest-server.jrs.Swagger.jrs.SwaggerParameters -->
 
 <!-- ==================================================================================================== -->
 
-<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Swagger.jrs.SwaggerParameterExamples' id='juneau-rest-server.jrs.Swagger.jrs.SwaggerParameterExamples'>6.19.6 - Parameter Examples</a><span class='update'>updated: 8.1.0, <b><red>todo</red></b></span></h4>
-<div class='topic'><!-- START: 6.19.6 - juneau-rest-server.jrs.Swagger.jrs.SwaggerParameterExamples -->
+<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Swagger.jrs.SwaggerParameterExamples' id='juneau-rest-server.jrs.Swagger.jrs.SwaggerParameterExamples'>6.16.6 - Parameter Examples</a><span class='update'>updated: 8.1.0, <b><red>todo</red></b></span></h4>
+<div class='topic'><!-- START: 6.16.6 - juneau-rest-server.jrs.Swagger.jrs.SwaggerParameterExamples -->
 <div class='topic'>
 	<p>
 		The <c>model</c> select box in the parameters can be expanded to show examples:
@@ -18976,12 +18745,12 @@
 		</ul>
 	</ul>
 </div>
-</div><!-- END: 6.19.6 - juneau-rest-server.jrs.Swagger.jrs.SwaggerParameterExamples -->
+</div><!-- END: 6.16.6 - juneau-rest-server.jrs.Swagger.jrs.SwaggerParameterExamples -->
 
 <!-- ==================================================================================================== -->
 
-<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Swagger.jrs.SwaggerResponses' id='juneau-rest-server.jrs.Swagger.jrs.SwaggerResponses'>6.19.7 - Responses</a><span class='update'><b><red>todo</red></b></span></h4>
-<div class='topic'><!-- START: 6.19.7 - juneau-rest-server.jrs.Swagger.jrs.SwaggerResponses -->
+<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Swagger.jrs.SwaggerResponses' id='juneau-rest-server.jrs.Swagger.jrs.SwaggerResponses'>6.16.7 - Responses</a><span class='update'><b><red>todo</red></b></span></h4>
+<div class='topic'><!-- START: 6.16.7 - juneau-rest-server.jrs.Swagger.jrs.SwaggerResponses -->
 <div class='topic'>
 	<p>
 		Under the input parameters are listed the possible responses for the resource:
@@ -19020,12 +18789,12 @@
 		<li class='link'>{@doc jrs.ResponseBeans}
 	</ul>
 </div>
-</div><!-- END: 6.19.7 - juneau-rest-server.jrs.Swagger.jrs.SwaggerResponses -->
+</div><!-- END: 6.16.7 - juneau-rest-server.jrs.Swagger.jrs.SwaggerResponses -->
 
 <!-- ==================================================================================================== -->
 
-<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Swagger.jrs.SwaggerResponseExamples' id='juneau-rest-server.jrs.Swagger.jrs.SwaggerResponseExamples'>6.19.8 - Response Examples</a><span class='update'><b><red>todo</red></b></span></h4>
-<div class='topic'><!-- START: 6.19.8 - juneau-rest-server.jrs.Swagger.jrs.SwaggerResponseExamples -->
+<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Swagger.jrs.SwaggerResponseExamples' id='juneau-rest-server.jrs.Swagger.jrs.SwaggerResponseExamples'>6.16.8 - Response Examples</a><span class='update'><b><red>todo</red></b></span></h4>
+<div class='topic'><!-- START: 6.16.8 - juneau-rest-server.jrs.Swagger.jrs.SwaggerResponseExamples -->
 <div class='topic'>
 	<p>
 		The <c>model</c> select box in the responses can be expanded to show examples:
@@ -19245,12 +19014,12 @@
 	}
 	</p>	
 </div>
-</div><!-- END: 6.19.8 - juneau-rest-server.jrs.Swagger.jrs.SwaggerResponseExamples -->
+</div><!-- END: 6.16.8 - juneau-rest-server.jrs.Swagger.jrs.SwaggerResponseExamples -->
 
 <!-- ==================================================================================================== -->
 
-<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Swagger.jrs.SwaggerModels' id='juneau-rest-server.jrs.Swagger.jrs.SwaggerModels'>6.19.9 - Models</a><span class='update'><b><red>todo</red></b></span></h4>
-<div class='topic'><!-- START: 6.19.9 - juneau-rest-server.jrs.Swagger.jrs.SwaggerModels -->
+<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Swagger.jrs.SwaggerModels' id='juneau-rest-server.jrs.Swagger.jrs.SwaggerModels'>6.16.9 - Models</a><span class='update'><b><red>todo</red></b></span></h4>
+<div class='topic'><!-- START: 6.16.9 - juneau-rest-server.jrs.Swagger.jrs.SwaggerModels -->
 <div class='topic'>
 	<p>
 		The {@del org.apache.juneau.jsonschema.JsonSchemaGenerator#JSONSCHEMA_useBeanDefs} setting can be used to reduce the size of your
@@ -19345,12 +19114,12 @@
 	</p>
 	<img class='bordered w900' src='doc-files/jrs.Swagger.Models.3.png'> 
 </div>
-</div><!-- END: 6.19.9 - juneau-rest-server.jrs.Swagger.jrs.SwaggerModels -->
+</div><!-- END: 6.16.9 - juneau-rest-server.jrs.Swagger.jrs.SwaggerModels -->
 
 <!-- ==================================================================================================== -->
 
-<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Swagger.jrs.SwaggerStylesheet' id='juneau-rest-server.jrs.Swagger.jrs.SwaggerStylesheet'>6.19.10 - SwaggerUI.css</a><span class='update'><b><red>todo</red></b></span></h4>
-<div class='topic'><!-- START: 6.19.10 - juneau-rest-server.jrs.Swagger.jrs.SwaggerStylesheet -->
+<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Swagger.jrs.SwaggerStylesheet' id='juneau-rest-server.jrs.Swagger.jrs.SwaggerStylesheet'>6.16.10 - SwaggerUI.css</a><span class='update'><b><red>todo</red></b></span></h4>
+<div class='topic'><!-- START: 6.16.10 - juneau-rest-server.jrs.Swagger.jrs.SwaggerStylesheet -->
 <div class='topic'>
 	<p>
 		The look-and-feel of the Swagger UI is controlled via a single CSS file:  <c>SwaggerUI.css</c>.
@@ -19361,13 +19130,13 @@
 		This file can be modified to change the look-and-feel of your Swagger UI.
 	</p>
 </div>
-</div><!-- END: 6.19.10 - juneau-rest-server.jrs.Swagger.jrs.SwaggerStylesheet -->
-</div><!-- END: 6.19 - juneau-rest-server.jrs.Swagger -->
+</div><!-- END: 6.16.10 - juneau-rest-server.jrs.Swagger.jrs.SwaggerStylesheet -->
+</div><!-- END: 6.16 - juneau-rest-server.jrs.Swagger -->
 
 <!-- ==================================================================================================== -->
 
-<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.ExecutionStatistics' id='juneau-rest-server.jrs.ExecutionStatistics'>6.20 - REST method execution statistics</a><span class='update'>created: 8.1.3, <b><red>todo</red></b></span></h3>
-<div class='topic'><!-- START: 6.20 - juneau-rest-server.jrs.ExecutionStatistics -->
+<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.ExecutionStatistics' id='juneau-rest-server.jrs.ExecutionStatistics'>6.17 - REST method execution statistics</a><span class='update'>created: 8.1.3, <b><red>todo</red></b></span></h3>
+<div class='topic'><!-- START: 6.17 - juneau-rest-server.jrs.ExecutionStatistics -->
 <div class='topic'>
 	<p>
 		<ja>@RestResource</ja> annotated classes get automated timing and error statistic information for all <ja>@RestOp</ja>
@@ -19395,12 +19164,12 @@
 		</ul>
 	</ul>
 </div>
-</div><!-- END: 6.20 - juneau-rest-server.jrs.ExecutionStatistics -->
+</div><!-- END: 6.17 - juneau-rest-server.jrs.ExecutionStatistics -->
 
 <!-- ==================================================================================================== -->
 
-<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.HtmlDocAnnotation' id='juneau-rest-server.jrs.HtmlDocAnnotation'>6.21 - @HtmlDocConfig</a><span class='update'>updated: 8.1.0, <b><red>todo</red></b></span></h3>
-<div class='topic'><!-- START: 6.21 - juneau-rest-server.jrs.HtmlDocAnnotation -->
+<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.HtmlDocAnnotation' id='juneau-rest-server.jrs.HtmlDocAnnotation'>6.18 - @HtmlDocConfig</a><span class='update'>updated: 8.1.0, <b><red>todo</red></b></span></h3>
+<div class='topic'><!-- START: 6.18 - juneau-rest-server.jrs.HtmlDocAnnotation -->
 <div class='topic'>
 	<p>
 		The {@link org.apache.juneau.html.annotation.HtmlDocConfig @HtmlDocConfig} annotation is used to customize the HTML 
@@ -19518,8 +19287,8 @@
 
 <!-- ==================================================================================================== -->
 
-<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlUIvsDI' id='juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlUIvsDI'>6.21.1 - User Interfaces (UI) vs. Developer Interfaces (DI)</a><span class='update'><b><red>todo</red></b></span></h4>
-<div class='topic'><!-- START: 6.21.1 - juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlUIvsDI -->
+<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlUIvsDI' id='juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlUIvsDI'>6.18.1 - User Interfaces (UI) vs. Developer Interfaces (DI)</a><span class='update'><b><red>todo</red></b></span></h4>
+<div class='topic'><!-- START: 6.18.1 - juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlUIvsDI -->
 <div class='topic'>
 	<p>
 		An important distinction needs to be made about the HTML representations produced by the REST
@@ -19562,12 +19331,12 @@
 			Angular, or any number of sophisticated Javascript UI frameworks.  Resist the urge to do so.
 	</ul>		
 </div>
-</div><!-- END: 6.21.1 - juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlUIvsDI -->
+</div><!-- END: 6.18.1 - juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlUIvsDI -->
 
 <!-- ==================================================================================================== -->
 
-<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlWidgets' id='juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlWidgets'>6.21.2 - Widgets</a><span class='update'><b><red>todo</red></b></span></h4>
-<div class='topic'><!-- START: 6.21.2 - juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlWidgets -->
+<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlWidgets' id='juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlWidgets'>6.18.2 - Widgets</a><span class='update'><b><red>todo</red></b></span></h4>
+<div class='topic'><!-- START: 6.18.2 - juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlWidgets -->
 <div class='topic'>
 	<p>
 		The {@link org.apache.juneau.rest.widget.Widget} class allows you to add arbitrary HTML, CSS, and Javascript
@@ -19682,12 +19451,12 @@
 		<li class='jf'>{@del org.apache.juneau.rest.RestContext#REST_widgets}
 	</ul>
 </div>
-</div><!-- END: 6.21.2 - juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlWidgets -->
+</div><!-- END: 6.18.2 - juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlWidgets -->
 
 <!-- ==================================================================================================== -->
 
-<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlPredefinedWidgets' id='juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlPredefinedWidgets'>6.21.3 - Predefined Widgets</a><span class='update'><b><red>todo</red></b></span></h4>
-<div class='topic'><!-- START: 6.21.3 - juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlPredefinedWidgets -->
+<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlPredefinedWidgets' id='juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlPredefinedWidgets'>6.18.3 - Predefined Widgets</a><span class='update'><b><red>todo</red></b></span></h4>
+<div class='topic'><!-- START: 6.18.3 - juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlPredefinedWidgets -->
 <div class='topic'>
 	<p>
 		The {@link org.apache.juneau.rest.widget} package contains predefined reusable widgets.
@@ -19924,12 +19693,12 @@
 	}
 	</p>
 </div>
-</div><!-- END: 6.21.3 - juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlPredefinedWidgets -->
+</div><!-- END: 6.18.3 - juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlPredefinedWidgets -->
 
 <!-- ==================================================================================================== -->
 
-<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlUiCustomization' id='juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlUiCustomization'>6.21.4 - UI Customization</a><span class='update'><b><red>todo</red></b></span></h4>
-<div class='topic'><!-- START: 6.21.4 - juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlUiCustomization -->
+<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlUiCustomization' id='juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlUiCustomization'>6.18.4 - UI Customization</a><span class='update'><b><red>todo</red></b></span></h4>
+<div class='topic'><!-- START: 6.18.4 - juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlUiCustomization -->
 <div class='topic'>
 	<p>
 		The HTML views of POJOs can somewhat be considered a rudimentary User Interface.
@@ -20075,12 +19844,12 @@
 		<li class='link'>{@doc jmj.UiCustomization}
 	</ul>
 </div>
-</div><!-- END: 6.21.4 - juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlUiCustomization -->
+</div><!-- END: 6.18.4 - juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlUiCustomization -->
 
 <!-- ==================================================================================================== -->
 
-<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlStylesheets' id='juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlStylesheets'>6.21.5 - Stylesheets</a><span class='update'>updated: 8.1.0, <b><red>todo</red></b></span></h4>
-<div class='topic'><!-- START: 6.21.5 - juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlStylesheets -->
+<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlStylesheets' id='juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlStylesheets'>6.18.5 - Stylesheets</a><span class='update'>updated: 8.1.0, <b><red>todo</red></b></span></h4>
+<div class='topic'><!-- START: 6.18.5 - juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlStylesheets -->
 <div class='topic'>
 	<p>
 		The sample root page renders in the default "devops" look-and-feel:
@@ -20192,13 +19961,13 @@
 	}
 	</p>
 </div>
-</div><!-- END: 6.21.5 - juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlStylesheets -->
-</div><!-- END: 6.21 - juneau-rest-server.jrs.HtmlDocAnnotation -->
+</div><!-- END: 6.18.5 - juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlStylesheets -->
+</div><!-- END: 6.18 - juneau-rest-server.jrs.HtmlDocAnnotation -->
 
 <!-- ==================================================================================================== -->
 
-<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.DefaultHeaders' id='juneau-rest-server.jrs.DefaultHeaders'>6.22 - Default Headers</a><span class='update'><b><red>todo</red></b></span></h3>
-<div class='topic'><!-- START: 6.22 - juneau-rest-server.jrs.DefaultHeaders -->
+<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.DefaultHeaders' id='juneau-rest-server.jrs.DefaultHeaders'>6.19 - Default Headers</a><span class='update'><b><red>todo</red></b></span></h3>
+<div class='topic'><!-- START: 6.19 - juneau-rest-server.jrs.DefaultHeaders -->
 <div class='topic'>
 	<p>
 		The following annotations are provided for specifying default header values for requests and responses:
@@ -20242,12 +20011,12 @@
 		</li>
 	</ul>
 </div>
-</div><!-- END: 6.22 - juneau-rest-server.jrs.DefaultHeaders -->
+</div><!-- END: 6.19 - juneau-rest-server.jrs.DefaultHeaders -->
 
 <!-- ==================================================================================================== -->
 
-<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.LoggingAndDebugging' id='juneau-rest-server.jrs.LoggingAndDebugging'>6.23 - Logging / Debugging</a><span class='update'>created: 8.1.0, updated: 8.2.0, <b><red>todo</red></b></span></h3>
-<div class='topic'><!-- START: 6.23 - juneau-rest-server.jrs.LoggingAndDebugging -->
+<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.LoggingAndDebugging' id='juneau-rest-server.jrs.LoggingAndDebugging'>6.20 - Logging / Debugging</a><span class='update'>created: 8.1.0, updated: 8.2.0, <b><red>todo</red></b></span></h3>
+<div class='topic'><!-- START: 6.20 - juneau-rest-server.jrs.LoggingAndDebugging -->
 <div class='topic'>
 	<p>
 		The REST APIs provides support for fine-tuned control of logging for HTTP requests and responses.
@@ -20580,12 +20349,12 @@
 		to the log file again.
 	</p>
 </div>
-</div><!-- END: 6.23 - juneau-rest-server.jrs.LoggingAndDebugging -->
+</div><!-- END: 6.20 - juneau-rest-server.jrs.LoggingAndDebugging -->
 
 <!-- ==================================================================================================== -->
 
-<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.HttpStatusCodes' id='juneau-rest-server.jrs.HttpStatusCodes'>6.24 - HTTP Status Codes</a><span class='update'><b><red>todo</red></b></span></h3>
-<div class='topic'><!-- START: 6.24 - juneau-rest-server.jrs.HttpStatusCodes -->
+<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.HttpStatusCodes' id='juneau-rest-server.jrs.HttpStatusCodes'>6.21 - HTTP Status Codes</a><span class='update'><b><red>todo</red></b></span></h3>
+<div class='topic'><!-- START: 6.21 - juneau-rest-server.jrs.HttpStatusCodes -->
 <div class='topic'>
 	<p>
 		By default, a 200 (OK) status is automatically set as the HTTP status when a Java method executes 
@@ -20650,12 +20419,12 @@
 		</tr>
 	</table>
 </div>
-</div><!-- END: 6.24 - juneau-rest-server.jrs.HttpStatusCodes -->
+</div><!-- END: 6.21 - juneau-rest-server.jrs.HttpStatusCodes -->
 
 <!-- ==================================================================================================== -->
 
-<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.OverloadingHttpMethods' id='juneau-rest-server.jrs.OverloadingHttpMethods'>6.25 - Overloading HTTP Methods</a><span class='update'><b><red>todo</red></b></span></h3>
-<div class='topic'><!-- START: 6.25 - juneau-rest-server.jrs.OverloadingHttpMethods -->
+<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.OverloadingHttpMethods' id='juneau-rest-server.jrs.OverloadingHttpMethods'>6.22 - Overloading HTTP Methods</a><span class='update'><b><red>todo</red></b></span></h3>
+<div class='topic'><!-- START: 6.22 - juneau-rest-server.jrs.OverloadingHttpMethods -->
 <div class='topic'>
 	<p>
 		Through the use of the built-in <l>"method"</l> GET parameter, you can implement requests beyond the basic 
@@ -20681,12 +20450,12 @@
 	)
 	</p>
 </div>
-</div><!-- END: 6.25 - juneau-rest-server.jrs.OverloadingHttpMethods -->
+</div><!-- END: 6.22 - juneau-rest-server.jrs.OverloadingHttpMethods -->
 
 <!-- ==================================================================================================== -->
 
-<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.BuiltInParameters' id='juneau-rest-server.jrs.BuiltInParameters'>6.26 - Built-in Parameters</a><span class='update'><b><red>todo</red></b></span></h3>
-<div class='topic'><!-- START: 6.26 - juneau-rest-server.jrs.BuiltInParameters -->
+<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.BuiltInParameters' id='juneau-rest-server.jrs.BuiltInParameters'>6.23 - Built-in Parameters</a><span class='update'><b><red>todo</red></b></span></h3>
+<div class='topic'><!-- START: 6.23 - juneau-rest-server.jrs.BuiltInParameters -->
 <div class='topic'>
 	<p>
 		The following URL parameters have special meaning and can be passed in through the URL of the request:
@@ -20748,12 +20517,12 @@
 		</tr>
 	</table>
 </div>
-</div><!-- END: 6.26 - juneau-rest-server.jrs.BuiltInParameters -->
+</div><!-- END: 6.23 - juneau-rest-server.jrs.BuiltInParameters -->
 
 <!-- ==================================================================================================== -->
 
-<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.CustomSerializersAndParsers' id='juneau-rest-server.jrs.CustomSerializersAndParsers'>6.27 - Custom Serializers and Parsers</a><span class='update'><b><red>todo</red></b></span></h3>
-<div class='topic'><!-- START: 6.27 - juneau-rest-server.jrs.CustomSerializersAndParsers -->
+<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.CustomSerializersAndParsers' id='juneau-rest-server.jrs.CustomSerializersAndParsers'>6.24 - Custom Serializers and Parsers</a><span class='update'><b><red>todo</red></b></span></h3>
+<div class='topic'><!-- START: 6.24 - juneau-rest-server.jrs.CustomSerializersAndParsers -->
 <div class='topic'>
 	<p>
 		A very easy-to-use API is provided for defining your own serializers and parsers at both the servlet and 
@@ -20870,12 +20639,12 @@
 	}
 	</p>
 </div>
-</div><!-- END: 6.27 - juneau-rest-server.jrs.CustomSerializersAndParsers -->
+</div><!-- END: 6.24 - juneau-rest-server.jrs.CustomSerializersAndParsers -->
 
 <!-- ==================================================================================================== -->
 
-<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.UsingWithOsgi' id='juneau-rest-server.jrs.UsingWithOsgi'>6.28 - Using with OSGi</a><span class='update'><b><red>todo</red></b></span></h3>
-<div class='topic'><!-- START: 6.28 - juneau-rest-server.jrs.UsingWithOsgi -->
+<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.UsingWithOsgi' id='juneau-rest-server.jrs.UsingWithOsgi'>6.25 - Using with OSGi</a><span class='update'><b><red>todo</red></b></span></h3>
+<div class='topic'><!-- START: 6.25 - juneau-rest-server.jrs.UsingWithOsgi -->
 <div class='topic'>
 	<p>
 		Since REST servlets are basically just <l>HttpServlets</l>, incorporating them into an OSGi environment
@@ -20939,12 +20708,12 @@
 	}
 	</p>
 </div>
-</div><!-- END: 6.28 - juneau-rest-server.jrs.UsingWithOsgi -->
+</div><!-- END: 6.25 - juneau-rest-server.jrs.UsingWithOsgi -->
 
 <!-- ==================================================================================================== -->
 
-<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Injection' id='juneau-rest-server.jrs.Injection'>6.29 - Using with Spring and Injection frameworks</a><span class='update'><b><red>todo</red></b></span></h3>
-<div class='topic'><!-- START: 6.29 - juneau-rest-server.jrs.Injection -->
+<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Injection' id='juneau-rest-server.jrs.Injection'>6.26 - Using with Spring and Injection frameworks</a><span class='update'><b><red>todo</red></b></span></h3>
+<div class='topic'><!-- START: 6.26 - juneau-rest-server.jrs.Injection -->
 <div class='topic'>
 	<p>
 		The Juneau REST server API is compatible with dependency injection frameworks such as Spring.
@@ -21048,12 +20817,12 @@
 		}
 	</p>
 </div>
-</div><!-- END: 6.29 - juneau-rest-server.jrs.Injection -->
+</div><!-- END: 6.26 - juneau-rest-server.jrs.Injection -->
 
 <!-- ==================================================================================================== -->
 
-<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.OtherNotes' id='juneau-rest-server.jrs.OtherNotes'>6.30 - Other Notes</a><span class='update'><b><red>todo</red></b></span></h3>
-<div class='topic'><!-- START: 6.30 - juneau-rest-server.jrs.OtherNotes -->
+<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.OtherNotes' id='juneau-rest-server.jrs.OtherNotes'>6.27 - Other Notes</a><span class='update'><b><red>todo</red></b></span></h3>
+<div class='topic'><!-- START: 6.27 - juneau-rest-server.jrs.OtherNotes -->
 <div class='topic'>
 	<ul class='spaced-list'>
 		<li>
@@ -21066,12 +20835,12 @@
 			parameter can be specified:  <l>"/sample?X-Response-Headers={Refresh=1}"</l>
 	</ul>
 </div>
-</div><!-- END: 6.30 - juneau-rest-server.jrs.OtherNotes -->
+</div><!-- END: 6.27 - juneau-rest-server.jrs.OtherNotes -->
 
 <!-- ==================================================================================================== -->
 
-<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.RestContext' id='juneau-rest-server.jrs.RestContext'>6.31 - RestContext</a><span class='update'><b><red>todo</red></b></span></h3>
-<div class='topic'><!-- START: 6.31 - juneau-rest-server.jrs.RestContext -->
+<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.RestContext' id='juneau-rest-server.jrs.RestContext'>6.28 - RestContext</a><span class='update'><b><red>todo</red></b></span></h3>
+<div class='topic'><!-- START: 6.28 - juneau-rest-server.jrs.RestContext -->
 <div class='topic'>
 	<p>
 		The {@link org.apache.juneau.rest.RestContext} object is the workhorse class for all of the configuration
@@ -21121,12 +20890,12 @@
 			resource finders, info providers, etc...
 	</p>
 </div>
-</div><!-- END: 6.31 - juneau-rest-server.jrs.RestContext -->
+</div><!-- END: 6.28 - juneau-rest-server.jrs.RestContext -->
 
 <!-- ==================================================================================================== -->
 
-<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.RestRpc' id='juneau-rest-server.jrs.RestRpc'>6.32 - REST/RPC</a><span class='update'>updated: 8.0.0, <b><red>todo</red></b></span></h3>
-<div class='topic'><!-- START: 6.32 - juneau-rest-server.jrs.RestRpc -->
+<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.RestRpc' id='juneau-rest-server.jrs.RestRpc'>6.29 - REST/RPC</a><span class='update'>updated: 8.0.0, <b><red>todo</red></b></span></h3>
+<div class='topic'><!-- START: 6.29 - juneau-rest-server.jrs.RestRpc -->
 <div class='topic'>
 	<p>
 		The REST/RPC (RPC over REST) API allows the creation of client-side remote proxy interfaces for calling methods on server-side POJOs using entirely REST.
@@ -21447,12 +21216,12 @@
 	<h5 class='figure'>Sample form entry page results</h5>
 	<img class='bordered w800' src='doc-files/jrs.restRPC.9.png'>
 </div>
-</div><!-- END: 6.32 - juneau-rest-server.jrs.RestRpc -->
+</div><!-- END: 6.29 - juneau-rest-server.jrs.RestRpc -->
 
 <!-- ==================================================================================================== -->
 
-<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.CustomRestContextsAndBuilders' id='juneau-rest-server.jrs.CustomRestContextsAndBuilders'>6.33 - Custom REST Context and Builders</a><span class='update'>created: <b>9.0.0</b>, <b><red>todo</red></b></span></h3>
-<div class='topic'><!-- START: 6.33 - juneau-rest-server.jrs.CustomRestContextsAndBuilders -->
+<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.CustomRestContextsAndBuilders' id='juneau-rest-server.jrs.CustomRestContextsAndBuilders'>6.30 - Custom REST Context and Builders</a><span class='update'>created: <b>9.0.0</b>, <b><red>todo</red></b></span></h3>
+<div class='topic'><!-- START: 6.30 - juneau-rest-server.jrs.CustomRestContextsAndBuilders -->
 <div class='topic'>
 	<p>
 		They can also be defined programmatically:
@@ -21486,51 +21255,138 @@
 	}
 	</p>
 </div>
-</div><!-- END: 6.33 - juneau-rest-server.jrs.CustomRestContextsAndBuilders -->
+</div><!-- END: 6.30 - juneau-rest-server.jrs.CustomRestContextsAndBuilders -->
 
 <!-- ==================================================================================================== -->
 
-<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.FluentAssertions' id='juneau-rest-server.jrs.FluentAssertions'>6.34 - Fluent Assertions</a><span class='update'>created: <b>9.0.0</b>, <b><red>TODO</red></b></span></h3>
-<div class='topic'><!-- START: 6.34 - juneau-rest-server.jrs.FluentAssertions -->
+<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.FluentAssertions' id='juneau-rest-server.jrs.FluentAssertions'>6.31 - Fluent Assertions</a><span class='update'>created: <b>9.0.0</b>, <b><red>TODO</red></b></span></h3>
+<div class='topic'><!-- START: 6.31 - juneau-rest-server.jrs.FluentAssertions -->
 <div class='topic'>
 	<p>
 		TODO
 	</p>
 </div>
-</div><!-- END: 6.34 - juneau-rest-server.jrs.FluentAssertions -->
+</div><!-- END: 6.31 - juneau-rest-server.jrs.FluentAssertions -->
 
 <!-- ==================================================================================================== -->
 
-<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Overview' id='juneau-rest-server.jrs.Overview'>6.35 - Utility Beans</a><span class='update'>created: <b>9.0.0</b>, <b><red>TODO</red></b></span></h3>
-<div class='topic'><!-- START: 6.35 - juneau-rest-server.jrs.Overview -->
+<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Overview' id='juneau-rest-server.jrs.Overview'>6.32 - Utility Beans</a><span class='update'>created: <b>9.0.0</b>, <b><red>TODO</red></b></span></h3>
+<div class='topic'><!-- START: 6.32 - juneau-rest-server.jrs.Overview -->
 <div class='topic'>
 	<p>
 		TODO
 	</p>
 </div>
-</div><!-- END: 6.35 - juneau-rest-server.jrs.Overview -->
+</div><!-- END: 6.32 - juneau-rest-server.jrs.Overview -->
 
 <!-- ==================================================================================================== -->
 
-<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.ResponseProcessors' id='juneau-rest-server.jrs.ResponseProcessors'>6.36 - Fluent Assertions</a><span class='update'>created: <b>9.0.0</b>, <b><red>TODO</red></b></span></h3>
-<div class='topic'><!-- START: 6.36 - juneau-rest-server.jrs.ResponseProcessors -->
+<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.ResponseProcessors' id='juneau-rest-server.jrs.ResponseProcessors'>6.33 - Fluent Assertions</a><span class='update'>created: <b>9.0.0</b>, <b><red>TODO</red></b></span></h3>
+<div class='topic'><!-- START: 6.33 - juneau-rest-server.jrs.ResponseProcessors -->
 <div class='topic'>
 	<p>
 		TODO
 	</p>
 </div>
-</div><!-- END: 6.36 - juneau-rest-server.jrs.ResponseProcessors -->
+</div><!-- END: 6.33 - juneau-rest-server.jrs.ResponseProcessors -->
 
 <!-- ==================================================================================================== -->
 
-<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.UtilityBeans' id='juneau-rest-server.jrs.UtilityBeans'>6.37 - Utility Beans</a><span class='update'>created: <b>9.0.0</b>, <b><red>TODO</red></b></span></h3>
-<div class='topic'><!-- START: 6.37 - juneau-rest-server.jrs.UtilityBeans -->
+<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.UtilityBeans' id='juneau-rest-server.jrs.UtilityBeans'>6.34 - Utility Beans</a><span class='update'>created: <b>9.0.0</b>, <b><red>TODO</red></b></span></h3>
+<div class='topic'><!-- START: 6.34 - juneau-rest-server.jrs.UtilityBeans -->
 <div class='topic'>
 	<p>
 		TODO
 	</p>
 </div>
-</div><!-- END: 6.37 - juneau-rest-server.jrs.UtilityBeans -->
+</div><!-- END: 6.34 - juneau-rest-server.jrs.UtilityBeans -->
+
+<!-- ==================================================================================================== -->
+
+<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.SerializingUris' id='juneau-rest-server.jrs.SerializingUris'>6.35 - URIs</a><span class='update'><b><red>todo</red></b></span></h3>
+<div class='topic'><!-- START: 6.35 - juneau-rest-server.jrs.SerializingUris -->
+<div class='topic'>
+	<p>
+		As mention earlier {@doc jm.MarshallingUris here}, Juneau serializers have sophisticated support for transforming relative URIs to absolute form.
+	</p>
+	<p>
+		The following example shows a REST method that returns a list of URIs of various forms: 
+	</p>
+	<p class='bcode w800'>
+	<ja>@Rest</ja>(
+		uriAuthority=<js>"http://foo.com:123"</js>,
+		uriContext=<js>"/myContext"</js>
+	)
+	<jk>public class</jk> MyResource {
+	
+		<ja>@RestGet</ja>
+		<jk>public</jk> URI[] getURIs() {
+			<jk>return new</jk> URI[] {
+				URI.<jsm>create</jsm>(<js>"http://www.apache.org/f1a"</js>),
+				URI.<jsm>create</jsm>(<js>"/f1b"</js>),
+				URI.<jsm>create</jsm>(<js>"/f1c/x/y"</js>),
+				URI.<jsm>create</jsm>(<js>"f1d"</js>),
+				URI.<jsm>create</jsm>(<js>"f1e/x/y"</js>),
+				URI.<jsm>create</jsm>(<js>""</js>),
+				URI.<jsm>create</jsm>(<js>"context:/f2a/x"</js>),
+				URI.<jsm>create</jsm>(<js>"context:/f2b"</js>),
+				URI.<jsm>create</jsm>(<js>"context:/"</js>),
+				URI.<jsm>create</jsm>(<js>"context:/.."</js>),
+				URI.<jsm>create</jsm>(<js>"servlet:/f3a/x"</js>),
+				URI.<jsm>create</jsm>(<js>"servlet:/f3b"</js>),
+				URI.<jsm>create</jsm>(<js>"servlet:/"</js>),
+				URI.<jsm>create</jsm>(<js>"servlet:/.."</js>),
+				URI.<jsm>create</jsm>(<js>"request:/f4a/x"</js>),
+				URI.<jsm>create</jsm>(<js>"request:/f4b"</js>),
+				URI.<jsm>create</jsm>(<js>"request:/"</js>),
+				URI.<jsm>create</jsm>(<js>"request:/.."</js>)
+			};
+		}
+	}	
+	</p>
+	<p>
+		When requested as JSON, it produces the following result:
+	</p>
+	<p class='bcode w800'>
+	{
+		<jok>f1a</jok>:<jov>'http://www.apache.org/f1a'</jov>,
+		<jok>f1b</jok>:<jov>'http://foo.com:123/f1b'</jov>,
+		<jok>f1c</jok>:<jov>'http://foo.com:123/f1c/x/y'</jov>,
+		<jok>f1d</jok>:<jov>'http://foo.com:123/myContext/myServlet/f1d'</jov>,
+		<jok>f1e</jok>:<jov>'http://foo.com:123/myContext/myServlet/f1e/x/y'</jov>,
+		<jok>f1f</jok>:<jov>'http://foo.com:123/myContext/myServlet'</jov>,
+		<jok>f2a</jok>:<jov>'http://foo.com:123/myContext/f2a/x'</jov>,
+		<jok>f2b</jok>:<jov>'http://foo.com:123/myContext/f2b'</jov>,
+		<jok>f2c</jok>:<jov>'http://foo.com:123/myContext'</jov>,
+		<jok>f2d</jok>:<jov>'http://foo.com:123'</jov>,
+		<jok>f3a</jok>:<jov>'http://foo.com:123/myContext/myServlet/f3a/x'</jov>,
+		<jok>f3b</jok>:<jov>'http://foo.com:123/myContext/myServlet/f3b'</jov>,
+		<jok>f3c</jok>:<jov>'http://foo.com:123/myContext/myServlet'</jov>,
+		<jok>f3d</jok>:<jov>'http://foo.com:123/myContext'</jov>,
+		<jok>f4a</jok>:<jov>'http://foo.com:123/myContext/myServlet/myPath/f4a/x'</jov>,
+		<jok>f4b</jok>:<jov>'http://foo.com:123/myContext/myServlet/myPath/f4b'</jov>,
+		<jok>f4c</jok>:<jov>'http://foo.com:123/myContext/myServlet/myPath'</jov>,
+		<jok>f4d</jok>:<jov>'http://foo.com:123/myContext/myServlet'</jov>
+	}
+	</p>
+	<p>
+		URI resolution is controlled by the following settings:
+	</p>
+	<ul class='javatree'>
+		<li class='jc'>{@link org.apache.juneau.rest.RestContext}
+		<ul>
+			<li class='jf'>{@del org.apache.juneau.rest.RestContext#REST_uriAuthority REST_uriAuthority}
+			<li class='jf'>{@del org.apache.juneau.rest.RestContext#REST_uriContext REST_uriContext}
+			<li class='jf'>{@del org.apache.juneau.rest.RestContext#REST_uriRelativity REST_uriRelativity}
+			<li class='jf'>{@del org.apache.juneau.rest.RestContext#REST_uriResolution REST_uriResolution}
+		</ul>	
+	</ul>
+	
+	<p>
+		URIs are resolved by both regular and part serializers.
+	</p>
+</div>
+</div><!-- END: 6.35 - juneau-rest-server.jrs.SerializingUris -->
 </div><!-- END: 6 - juneau-rest-server -->
 
 <!-- ==================================================================================================== -->
diff --git a/juneau-doc/src/main/javadoc/resources/docs.txt b/juneau-doc/src/main/javadoc/resources/docs.txt
index edbf8da..b446473 100644
--- a/juneau-doc/src/main/javadoc/resources/docs.txt
+++ b/juneau-doc/src/main/javadoc/resources/docs.txt
@@ -268,7 +268,6 @@ jrs.ExecutionStatistics = #juneau-rest-server.jrs.ExecutionStatistics, Overview
 jrs.FluentAssertions = #juneau-rest-server.jrs.FluentAssertions, Overview > juneau-rest-server > Fluent Assertions
 jrs.Guards = #juneau-rest-server.jrs.Guards, Overview > juneau-rest-server > Guards
 jrs.HandlingFormPosts = #juneau-rest-server.jrs.HandlingFormPosts, Overview > juneau-rest-server > Form Posts
-jrs.HandlingUris = #juneau-rest-server.jrs.HandlingUris, Overview > juneau-rest-server > URIs
 jrs.HelloWorldExample = #juneau-rest-server.jrs.HelloWorldExample, Overview > juneau-rest-server > Hello World Example
 jrs.HtmlDocAnnotation = #juneau-rest-server.jrs.HtmlDocAnnotation, Overview > juneau-rest-server > @HtmlDocConfig
 jrs.HtmlPredefinedWidgets = #juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlPredefinedWidgets, Overview > juneau-rest-server > @HtmlDocConfig > Predefined Widgets
@@ -287,10 +286,10 @@ jrs.JavaMethodParameters = #juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.Ja
 jrs.JavaMethodReturnTypes = #juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.JavaMethodReturnTypes, Overview > juneau-rest-server > @RestOp-Annotated Methods > Java Method Return Types
 jrs.JavaMethodThrowableTypes = #juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.JavaMethodThrowableTypes, Overview > juneau-rest-server > @RestOp-Annotated Methods > Java Method Throwable Types
 jrs.LifecycleHooks = #juneau-rest-server.jrs.AnnotatedClasses.jrs.LifecycleHooks, Overview > juneau-rest-server > @Rest-Annotated Classes > Lifecycle Hooks
+jrs.LocalizedMessages = #juneau-rest-server.jrs.LocalizedMessages, Overview > juneau-rest-server > Localized Messages
 jrs.LoggingAndDebugging = #juneau-rest-server.jrs.LoggingAndDebugging, Overview > juneau-rest-server > Logging / Debugging
 jrs.Marshalling = #juneau-rest-server.jrs.Marshalling, Overview > juneau-rest-server > Marshalling
 jrs.Matchers = #juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.Matchers, Overview > juneau-rest-server > @RestOp-Annotated Methods > Matchers
-jrs.Messages = #juneau-rest-server.jrs.Messages, Overview > juneau-rest-server > Messages
 jrs.OtherNotes = #juneau-rest-server.jrs.OtherNotes, Overview > juneau-rest-server > Other Notes
 jrs.OverloadingHttpMethods = #juneau-rest-server.jrs.OverloadingHttpMethods, Overview > juneau-rest-server > Overloading HTTP Methods
 jrs.Overview = #juneau-rest-server.jrs.Overview, Overview > juneau-rest-server > Utility Beans
@@ -302,7 +301,7 @@ jrs.ResponseProcessors = #juneau-rest-server.jrs.ResponseProcessors, Overview >
 jrs.RestContext = #juneau-rest-server.jrs.RestContext, Overview > juneau-rest-server > RestContext
 jrs.RestOpAnnotatedMethods = #juneau-rest-server.jrs.RestOpAnnotatedMethods, Overview > juneau-rest-server > @RestOp-Annotated Methods
 jrs.RestRpc = #juneau-rest-server.jrs.RestRpc, Overview > juneau-rest-server > REST/RPC
-jrs.RoleGuards = #juneau-rest-server.jrs.RoleGuards, Overview > juneau-rest-server > Role guards
+jrs.SerializingUris = #juneau-rest-server.jrs.SerializingUris, Overview > juneau-rest-server > URIs
 jrs.StaticFiles = #juneau-rest-server.jrs.StaticFiles, Overview > juneau-rest-server > Static files
 jrs.SvlVariables = #juneau-rest-server.jrs.SvlVariables, Overview > juneau-rest-server > SVL Variables
 jrs.Swagger = #juneau-rest-server.jrs.Swagger, Overview > juneau-rest-server > Swagger
@@ -314,7 +313,6 @@ jrs.SwaggerResponseExamples = #juneau-rest-server.jrs.Swagger.jrs.SwaggerRespons
 jrs.SwaggerResponses = #juneau-rest-server.jrs.Swagger.jrs.SwaggerResponses, Overview > juneau-rest-server > Swagger > Responses
 jrs.SwaggerStylesheet = #juneau-rest-server.jrs.Swagger.jrs.SwaggerStylesheet, Overview > juneau-rest-server > Swagger > SwaggerUI.css
 jrs.SwaggerTags = #juneau-rest-server.jrs.Swagger.jrs.SwaggerTags, Overview > juneau-rest-server > Swagger > Tags
-jrs.Transforms = #juneau-rest-server.jrs.Transforms, Overview > juneau-rest-server > Transforms
 jrs.UsingWithOsgi = #juneau-rest-server.jrs.UsingWithOsgi, Overview > juneau-rest-server > Using with OSGi
 jrs.UtilityBeans = #juneau-rest-server.jrs.UtilityBeans, Overview > juneau-rest-server > Utility Beans
 jrsj.BaseProvider = #juneau-rest-server-jaxrs.jrsj.BaseProvider, Overview > juneau-rest-server-jaxrs > Juneau JAX-RS Provider
diff --git a/juneau-doc/src/main/javadoc/resources/fragments/toc.html b/juneau-doc/src/main/javadoc/resources/fragments/toc.html
index 4766e60..0cd408b 100644
--- a/juneau-doc/src/main/javadoc/resources/fragments/toc.html
+++ b/juneau-doc/src/main/javadoc/resources/fragments/toc.html
@@ -229,15 +229,12 @@
 		</ol>
 		<li><p><a class='doclink' href='{OVERVIEW_URL}#juneau-rest-server.jrs.Marshalling'>Marshalling</a><span class='update'>updated: <b>9.0.0</b></span></p>
 		<li><p><a class='doclink' href='{OVERVIEW_URL}#juneau-rest-server.jrs.HandlingFormPosts'>Form Posts</a><span class='update'>updated: <b>9.0.0</b></span></p>
-		<li><p><a class='doclink' href='{OVERVIEW_URL}#juneau-rest-server.jrs.Transforms'>Transforms</a><span class='update'>updated: 8.1.0, <b><red>todo</red></b></span></p>
-		<li><p><a class='doclink' href='{OVERVIEW_URL}#juneau-rest-server.jrs.HandlingUris'>URIs</a><span class='update'><b><red>todo</red></b></span></p>
-		<li><p><a class='doclink' href='{OVERVIEW_URL}#juneau-rest-server.jrs.Guards'>Guards</a><span class='update'><b><red>todo</red></b></span></p>
-		<li><p><a class='doclink' href='{OVERVIEW_URL}#juneau-rest-server.jrs.RoleGuards'>Role guards</a><span class='update'>created: 8.1.0, <b><red>todo</red></b></span></p>
-		<li><p><a class='doclink' href='{OVERVIEW_URL}#juneau-rest-server.jrs.Converters'>Converters</a><span class='update'><b><red>todo</red></b></span></p>
-		<li><p><a class='doclink' href='{OVERVIEW_URL}#juneau-rest-server.jrs.Messages'>Messages</a><span class='update'>updated: 8.2.0, <b><red>todo</red></b></span></p>
-		<li><p><a class='doclink' href='{OVERVIEW_URL}#juneau-rest-server.jrs.Encoders'>Encoders</a><span class='update'><b><red>todo</red></b></span></p>
+		<li><p><a class='doclink' href='{OVERVIEW_URL}#juneau-rest-server.jrs.Guards'>Guards</a><span class='update'>updated: <b>9.0.0</b></span></p>
+		<li><p><a class='doclink' href='{OVERVIEW_URL}#juneau-rest-server.jrs.Converters'>Converters</a><span class='update'>updated: <b>9.0.0</b></span></p>
+		<li><p><a class='doclink' href='{OVERVIEW_URL}#juneau-rest-server.jrs.LocalizedMessages'>Localized Messages</a><span class='update'>updated: 8.2.0,<b>9.0.0</b></span></p>
+		<li><p><a class='doclink' href='{OVERVIEW_URL}#juneau-rest-server.jrs.Encoders'>Encoders</a><span class='update'>updated: <b>9.0.0</b></span></p>
+		<li><p><a class='doclink' href='{OVERVIEW_URL}#juneau-rest-server.jrs.ConfigurationFiles'>Configuration Files</a><span class='update'>updated: <b>9.0.0</b></span></p>
 		<li><p><a class='doclink' href='{OVERVIEW_URL}#juneau-rest-server.jrs.SvlVariables'>SVL Variables</a><span class='update'><b><red>todo</red></b></span></p>
-		<li><p><a class='doclink' href='{OVERVIEW_URL}#juneau-rest-server.jrs.ConfigurationFiles'>Configuration Files</a><span class='update'><b><red>todo</red></b></span></p>
 		<li><p><a class='doclink' href='{OVERVIEW_URL}#juneau-rest-server.jrs.StaticFiles'>Static files</a><span class='update'><b><red>todo</red></b></span></p>
 		<li><p><a class='doclink' href='{OVERVIEW_URL}#juneau-rest-server.jrs.ClientVersioning'>Client Versioning</a><span class='update'><b><red>todo</red></b></span></p>
 		<li><p><a class='doclink' href='{OVERVIEW_URL}#juneau-rest-server.jrs.InfoProvider'>RestInfoProvider</a><span class='update'><b><red>todo</red></b></span></p>
@@ -279,6 +276,7 @@
 		<li><p><a class='doclink' href='{OVERVIEW_URL}#juneau-rest-server.jrs.Overview'>Utility Beans</a><span class='update'>created: <b>9.0.0</b>, <b><red>TODO</red></b></span></p>
 		<li><p><a class='doclink' href='{OVERVIEW_URL}#juneau-rest-server.jrs.ResponseProcessors'>Fluent Assertions</a><span class='update'>created: <b>9.0.0</b>, <b><red>TODO</red></b></span></p>
 		<li><p><a class='doclink' href='{OVERVIEW_URL}#juneau-rest-server.jrs.UtilityBeans'>Utility Beans</a><span class='update'>created: <b>9.0.0</b>, <b><red>TODO</red></b></span></p>
+		<li><p><a class='doclink' href='{OVERVIEW_URL}#juneau-rest-server.jrs.SerializingUris'>URIs</a><span class='update'><b><red>todo</red></b></span></p>
 	</ol>
 	<li><p class='toc2'><a class='doclink' href='{OVERVIEW_URL}#juneau-rest-server-rdf'>juneau-rest-server-jaxrs</a></p>
 	<li><p class='toc2'><a class='doclink' href='{OVERVIEW_URL}#juneau-rest-server-jaxrs'>juneau-rest-server-jaxrs</a></p>
diff --git a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/Microservice.java b/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/Microservice.java
index 43085b4..eeab7c6 100755
--- a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/Microservice.java
+++ b/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/Microservice.java
@@ -649,7 +649,7 @@ public class Microservice implements ConfigEventListener {
 		// --------------------------------------------------------------------------------
 		// Initialize console commands.
 		// --------------------------------------------------------------------------------
-		this.consoleEnabled = ObjectUtils.firstNonNull(builder.consoleEnabled, config.getBoolean("Console/enabled", false));
+		this.consoleEnabled = ObjectUtils.firstNonNull(builder.consoleEnabled, config.get("Console/enabled").asBoolean().orElse(false));
 		if (consoleEnabled) {
 			Console c = System.console();
 			this.consoleReader = ObjectUtils.firstNonNull(builder.consoleReader, new Scanner(c == null ? new InputStreamReader(System.in) : c.reader()));
@@ -658,7 +658,7 @@ public class Microservice implements ConfigEventListener {
 			for (ConsoleCommand cc : builder.consoleCommands) {
 				consoleCommandMap.put(cc.getName(), cc);
 			}
-			for (String s : config.getStringArray("Console/commands")) {
+			for (String s : config.get("Console/commands").asStringArray().orElse(new String[0])) {
 				ConsoleCommand cc;
 				try {
 					cc = (ConsoleCommand)Class.forName(s).newInstance();
@@ -760,7 +760,7 @@ public class Microservice implements ConfigEventListener {
 		Set<String> spKeys = config.getKeys("SystemProperties");
 		if (spKeys != null)
 			for (String key : spKeys)
-				System.setProperty(key, config.getString("SystemProperties/"+key));
+				System.setProperty(key, config.get("SystemProperties/"+key).orElse(null));
 
 		// --------------------------------------------------------------------------------
 		// Initialize logging.
@@ -770,43 +770,42 @@ public class Microservice implements ConfigEventListener {
 		if (this.logger == null) {
 			LogManager.getLogManager().reset();
 			this.logger = Logger.getLogger("");
-			String logFile = firstNonNull(logConfig.logFile, config.getString("Logging/logFile"));
+			String logFile = firstNonNull(logConfig.logFile, config.get("Logging/logFile").orElse(null));
 
 			if (isNotEmpty(logFile)) {
-				String logDir = firstNonNull(logConfig.logDir, config.getString("Logging/logDir", "."));
+				String logDir = firstNonNull(logConfig.logDir, config.get("Logging/logDir").orElse("."));
 				File logDirFile = resolveFile(logDir);
 				mkdirs(logDirFile, false);
 				logDir = logDirFile.getAbsolutePath();
 				System.setProperty("juneau.logDir", logDir);
 
-				boolean append = firstNonNull(logConfig.append, config.getBoolean("Logging/append"));
-				int limit = firstNonNull(logConfig.limit, config.getInt("Logging/limit", 1024*1024));
-				int count = firstNonNull(logConfig.count, config.getInt("Logging/count", 1));
+				boolean append = firstNonNull(logConfig.append, config.get("Logging/append").asBoolean().orElse(false));
+				int limit = firstNonNull(logConfig.limit, config.get("Logging/limit").asInteger().orElse(1024*1024));
+				int count = firstNonNull(logConfig.count, config.get("Logging/count").asInteger().orElse(1));
 
 				FileHandler fh = new FileHandler(logDir + '/' + logFile, limit, count, append);
 
 				Formatter f = logConfig.formatter;
 				if (f == null) {
-					String format = config.getString("Logging/format", "[{date} {level}] {msg}%n");
-					String dateFormat = config.getString("Logging/dateFormat", "yyyy.MM.dd hh:mm:ss");
-					boolean useStackTraceHashes = config.getBoolean("Logging/useStackTraceHashes");
+					String format = config.get("Logging/format").orElse("[{date} {level}] {msg}%n");
+					String dateFormat = config.get("Logging/dateFormat").orElse("yyyy.MM.dd hh:mm:ss");
+					boolean useStackTraceHashes = config.get("Logging/useStackTraceHashes").asBoolean().orElse(false);
 					f = new LogEntryFormatter(format, dateFormat, useStackTraceHashes);
 				}
 				fh.setFormatter(f);
-				fh.setLevel(firstNonNull(logConfig.fileLevel, config.getObjectWithDefault("Logging/fileLevel", Level.INFO, Level.class)));
+				fh.setLevel(firstNonNull(logConfig.fileLevel, config.get("Logging/fileLevel").as(Level.class).orElse(Level.INFO)));
 				logger.addHandler(fh);
 
 				ConsoleHandler ch = new ConsoleHandler();
-				ch.setLevel(firstNonNull(logConfig.consoleLevel, config.getObjectWithDefault("Logging/consoleLevel", Level.WARNING, Level.class)));
+				ch.setLevel(firstNonNull(logConfig.consoleLevel, config.get("Logging/consoleLevel").as(Level.class).orElse(Level.WARNING)));
 				ch.setFormatter(f);
 				logger.addHandler(ch);
 			}
 		}
 
-		OMap loggerLevels = config.getObject("Logging/levels", OMap.class);
-		if (loggerLevels != null)
-			for (String l : loggerLevels.keySet())
-				Logger.getLogger(l).setLevel(loggerLevels.get(l, Level.class));
+		OMap loggerLevels = config.get("Logging/levels").as(OMap.class).orElseGet(OMap::new);
+		for (String l : loggerLevels.keySet())
+			Logger.getLogger(l).setLevel(loggerLevels.get(l, Level.class));
 		for (String l : logConfig.levels.keySet())
 			Logger.getLogger(l).setLevel(logConfig.levels.get(l));
 
diff --git a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/console/ConfigCommand.java b/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/console/ConfigCommand.java
index 1952085..6e70e85 100644
--- a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/console/ConfigCommand.java
+++ b/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/console/ConfigCommand.java
@@ -61,7 +61,7 @@ public class ConfigCommand extends ConsoleCommand {
 			if (option.equals("get")) {
 				// config get <key>
 				if (args.size() == 3) {
-					String val = conf.getString(key);
+					String val = conf.get(key).orElse(null);
 					if (val != null)
 						out.println(val);
 					else
@@ -82,7 +82,7 @@ public class ConfigCommand extends ConsoleCommand {
 			} else if (option.equals("remove")) {
 				// config remove <key>
 				if (args.size() == 3) {
-					if (conf.getString(key) != null) {
+					if (conf.get(key).isPresent()) {
 						conf.remove(key);
 						out.println(mb.getString("ConfigRemove", key));
 					} else {
diff --git a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/DirectoryResource.java b/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/DirectoryResource.java
index d52c020..acac476 100755
--- a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/DirectoryResource.java
+++ b/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/DirectoryResource.java
@@ -114,10 +114,10 @@ public class DirectoryResource extends BasicRestServlet {
 	final boolean allowDeletes, allowUploads, allowViews;
 
 	public DirectoryResource(Config c) throws Exception {
-		rootDir = new File(c.getString(DIRECTORY_RESOURCE_rootDir, "."));
-		allowViews = c.getBoolean(DIRECTORY_RESOURCE_allowViews, false);
-		allowDeletes = c.getBoolean(DIRECTORY_RESOURCE_allowDeletes, false);
-		allowUploads = c.getBoolean(DIRECTORY_RESOURCE_allowUploads, false);
+		rootDir = new File(c.get(DIRECTORY_RESOURCE_rootDir).orElse("."));
+		allowViews = c.get(DIRECTORY_RESOURCE_allowViews).asBoolean().orElse(false);
+		allowDeletes = c.get(DIRECTORY_RESOURCE_allowDeletes).asBoolean().orElse(false);
+		allowUploads = c.get(DIRECTORY_RESOURCE_allowUploads).asBoolean().orElse(false);
 	}
 
 	@RestGet(
diff --git a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/LogsResource.java b/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/LogsResource.java
index fabca60..c518503 100755
--- a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/LogsResource.java
+++ b/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/LogsResource.java
@@ -93,12 +93,12 @@ public class LogsResource extends BasicRestServlet {
 	final boolean allowDeletes;
 
 	public LogsResource(Config c) {
-		logDir = new File(c.getString(LOGS_RESOURCE_logDir, "logDir"));
-		allowDeletes = c.getBoolean(LOGS_RESOURCE_allowDeletes, true);
+		logDir = new File(c.get(LOGS_RESOURCE_logDir).orElse("logDir"));
+		allowDeletes = c.get(LOGS_RESOURCE_allowDeletes).asBoolean().orElse(true);
 		leFormatter = new LogEntryFormatter(
-			c.getString(LOGS_RESOURCE_logFormat, "[{date} {level}] {msg}%n"),
-			c.getString(LOGS_RESOURCE_dateFormat, "yyyy.MM.dd hh:mm:ss"),
-			c.getBoolean(LOGS_RESOURCE_useStackTraceHashes, true)
+			c.get(LOGS_RESOURCE_logFormat).orElse("[{date} {level}] {msg}%n"),
+			c.get(LOGS_RESOURCE_dateFormat).orElse("yyyy.MM.dd hh:mm:ss"),
+			c.get(LOGS_RESOURCE_useStackTraceHashes).asBoolean().orElse(true)
 		);
 	}
 
diff --git a/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/ConfigResource.java b/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/ConfigResource.java
index a51c22e..717e81c 100644
--- a/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/ConfigResource.java
+++ b/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/ConfigResource.java
@@ -34,6 +34,6 @@ public class ConfigResource extends BasicRestServlet {
 
 	@RestOp(method=GET, path="/{key}/{class}")
 	public Object test2(RestRequest req, @Path("key") String key, @Path("class") Class<?> c) throws Exception {
-		return req.getConfig().getObject(key, c);
+		return req.getConfig().get(key).as(c).orElse(null);
 	}
 }
diff --git a/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/TestMicroservice.java b/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/TestMicroservice.java
index 146a6f1..c506af1 100644
--- a/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/TestMicroservice.java
+++ b/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/TestMicroservice.java
@@ -159,7 +159,7 @@ public class TestMicroservice {
 	private static int dumpCount = 0;
 
 	public static void jettyDump(RequestLine rl, StatusLine sl) {
-		try (FileWriter fw = new FileWriter(microservice.getConfig().getString("Logging/logDir") + "/jetty-thread-dump-"+(dumpCount++)+".log")) {
+		try (FileWriter fw = new FileWriter(microservice.getConfig().get("Logging/logDir").orElse("") + "/jetty-thread-dump-"+(dumpCount++)+".log")) {
 			String dump = microservice.getServer().dump();
 			fw.append("RequestLine = [" + rl + "]\n");
 			fw.append("StatusLine = [" + sl + "]\n");
diff --git a/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettyMicroservice.java b/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettyMicroservice.java
index 3fc71e9..70f1350 100644
--- a/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettyMicroservice.java
+++ b/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettyMicroservice.java
@@ -670,15 +670,15 @@ public class JettyMicroservice extends Microservice {
 		OMap mf = getManifest();
 		VarResolver vr = getVarResolver();
 
-		int[] ports = ObjectUtils.firstNonNull(builder.ports, cf.getObjectWithDefault("Jetty/port", mf.getWithDefault("Jetty-Port", new int[]{8000}, int[].class), int[].class));
+		int[] ports = ObjectUtils.firstNonNull(builder.ports, cf.get("Jetty/port").as(int[].class).orElseGet(()->mf.getWithDefault("Jetty-Port", new int[]{8000}, int[].class)));
 		int availablePort = findOpenPort(ports);
 
 		if (System.getProperty("availablePort") == null)
 			System.setProperty("availablePort", String.valueOf(availablePort));
 
 		String jettyXml = builder.jettyXml;
-		String jettyConfig = cf.getString("Jetty/config", mf.getString("Jetty-Config", "jetty.xml"));
-		boolean resolveVars = ObjectUtils.firstNonNull(builder.jettyXmlResolveVars, cf.getBoolean("Jetty/resolveVars"));
+		String jettyConfig = cf.get("Jetty/config").orElse(mf.getString("Jetty-Config", "jetty.xml"));
+		boolean resolveVars = ObjectUtils.firstNonNull(builder.jettyXmlResolveVars, cf.get("Jetty/resolveVars").asBoolean().orElse(false));
 
 		if (jettyXml == null)
 			jettyXml = IOUtils.loadSystemResourceAsString("jetty.xml", ".", "files");
@@ -696,7 +696,7 @@ public class JettyMicroservice extends Microservice {
 			throw new ExecutableException(e2);
 		}
 
-		for (String s : cf.getStringArray("Jetty/servlets", new String[0])) {
+		for (String s : cf.get("Jetty/servlets").asStringArray().orElse(new String[0])) {
 			try {
 				ClassInfo c = ClassInfo.of(Class.forName(s));
 				if (c.isChildOf(RestServlet.class)) {
@@ -710,7 +710,7 @@ public class JettyMicroservice extends Microservice {
 			}
 		}
 
-		for (Map.Entry<String,Object> e : cf.getMap("Jetty/servletMap", OMap.EMPTY_MAP).entrySet()) {
+		for (Map.Entry<String,Object> e : cf.get("Jetty/servletMap").asMap().orElse(OMap.EMPTY_MAP).entrySet()) {
 			try {
 				ClassInfo c = ClassInfo.of(Class.forName(e.getValue().toString()));
 				if (c.isChildOf(Servlet.class)) {
@@ -724,7 +724,7 @@ public class JettyMicroservice extends Microservice {
 			}
 		}
 
-		for (Map.Entry<String,Object> e : cf.getMap("Jetty/servletAttributes", OMap.EMPTY_MAP).entrySet())
+		for (Map.Entry<String,Object> e : cf.get("Jetty/servletAttributes").asMap().orElse(OMap.EMPTY_MAP).entrySet())
 			addServletAttribute(e.getKey(), e.getValue());
 
 		for (Map.Entry<String,Servlet> e : builder.servlets.entrySet())
diff --git a/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/resources/DebugResource.java b/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/resources/DebugResource.java
index 728ed53..ff97b3d 100644
--- a/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/resources/DebugResource.java
+++ b/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/resources/DebugResource.java
@@ -76,7 +76,7 @@ public class DebugResource extends BasicRestServlet {
 	@RestPost(path="/jetty/dump", description="Generates and saves the jetty thread dump file to jetty-thread-dump.log.")
 	public String createJettyDump(RestRequest req, RestResponse res) throws Exception {
 		String dump = JettyMicroservice.getInstance().getServer().dump();
-		try (FileWriter fw = new FileWriter(req.getConfig().getString("Logging/logDir") + "/jetty-thread-dump.log")) {
+		try (FileWriter fw = new FileWriter(req.getConfig().get("Logging/logDir").orElse("") + "/jetty-thread-dump.log")) {
 			fw.write(dump);
 		}
 		return "OK";
diff --git a/juneau-rest/juneau-rest-server-springboot/src/main/java/org/apache/juneau/rest/springboot/BasicSpringRestServlet.java b/juneau-rest/juneau-rest-server-springboot/src/main/java/org/apache/juneau/rest/springboot/BasicSpringRestServlet.java
index c9f4534..511a650 100644
--- a/juneau-rest/juneau-rest-server-springboot/src/main/java/org/apache/juneau/rest/springboot/BasicSpringRestServlet.java
+++ b/juneau-rest/juneau-rest-server-springboot/src/main/java/org/apache/juneau/rest/springboot/BasicSpringRestServlet.java
@@ -172,7 +172,7 @@ public abstract class BasicSpringRestServlet extends SpringRestServlet implement
 
 	@Override /* BasicRestConfig */
 	public HttpResource getFavIcon() {
-		String favIcon = getContext().getConfig().getString("REST/favicon", "images/juneau.png");
+		String favIcon = getContext().getConfig().get("REST/favicon").orElse("images/juneau.png");
 		return getHtdoc(favIcon, null);
 	}
 
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestObject.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestObject.java
index 950e6df..5c82718 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestObject.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestObject.java
@@ -59,7 +59,7 @@ public abstract class BasicRestObject extends RestObject implements BasicUnivers
 
 	@Override /* BasicRestOperations */
 	public HttpResource getFavIcon() {
-		String favIcon = getContext().getConfig().getString("REST/favicon", "images/juneau.png");
+		String favIcon = getContext().getConfig().get("REST/favicon").orElse("images/juneau.png");
 		return getHtdoc(favIcon, null);
 	}
 
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestServlet.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestServlet.java
index ec2e95b..016505b 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestServlet.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestServlet.java
@@ -156,7 +156,7 @@ public abstract class BasicRestServlet extends RestServlet implements BasicUnive
 
 	@Override /* BasicRestOperations */
 	public HttpResource getFavIcon() {
-		String favIcon = getContext().getConfig().getString("REST/favicon", "images/juneau.png");
+		String favIcon = getContext().getConfig().get("REST/favicon").orElse("images/juneau.png");
 		return getHtdoc(favIcon, null);
 	}
 
diff --git a/juneau-sc/juneau-sc-server/src/main/java/org/apache/juneau/server/config/repository/GetConfiguration.java b/juneau-sc/juneau-sc-server/src/main/java/org/apache/juneau/server/config/repository/GetConfiguration.java
index e01be54..0993724 100644
--- a/juneau-sc/juneau-sc-server/src/main/java/org/apache/juneau/server/config/repository/GetConfiguration.java
+++ b/juneau-sc/juneau-sc-server/src/main/java/org/apache/juneau/server/config/repository/GetConfiguration.java
@@ -42,9 +42,9 @@ public class GetConfiguration implements Command, GetValue<Map<String, ConfigIte
 
 		Config config = Config.create().name("juneau-server-config.cfg").build();
 
-		String pathStr = config.getString("GitServer/pathLocal");
+		String pathStr = config.get("GitServer/pathLocal").orElse(null);
 
-		String git = config.get("GitServer/gitRemote");
+		String git = config.get("GitServer/gitRemote").orElse(null);
 
 		GitControl gitControl = new GitControl(pathStr, git);
 
diff --git a/juneau-utest/src/test/java/org/apache/juneau/config/ConfigImportsTest.java b/juneau-utest/src/test/java/org/apache/juneau/config/ConfigImportsTest.java
index 5f13c20..2a1fea4 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/config/ConfigImportsTest.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/config/ConfigImportsTest.java
@@ -40,7 +40,7 @@ public class ConfigImportsTest {
 			.create("B")
 			.store(ms)
 			.build();
-		assertEquals("1", c.getString("x"));
+		assertEquals("1", c.get("x").get());
 
 		c.set("x", "2");
 		c.commit();
@@ -55,8 +55,8 @@ public class ConfigImportsTest {
 		ms.write("A2", "", "y=2");
 		ms.write("B", "", "<A1>\n<A2>");
 		Config c = Config.create("B").store(ms).build();
-		assertEquals("1", c.getString("x"));
-		assertEquals("2", c.getString("y"));
+		assertEquals("1", c.get("x").get());
+		assertEquals("2", c.get("y").get());
 
 		c.set("x", "3");
 		c.set("y", "4");
@@ -73,8 +73,8 @@ public class ConfigImportsTest {
 		ms.write("A2", "", "<A1>\ny=2");
 		ms.write("B", "", "<A2>");
 		Config c = Config.create("B").store(ms).build();
-		assertEquals("1", c.getString("x"));
-		assertEquals("2", c.getString("y"));
+		assertEquals("1", c.get("x").get());
+		assertEquals("2", c.get("y").get());
 
 		c.set("x", "3");
 		c.set("y", "4");
@@ -99,7 +99,7 @@ public class ConfigImportsTest {
 		ConfigMemoryStore ms = ConfigMemoryStore.create().build();
 		ms.write("B", "", "<A>\nx=1");
 		Config c = Config.create("B").store(ms).build();
-		assertEquals("1", c.getString("x"));
+		assertEquals("1", c.get("x").get());
 	}
 
 	@Test
@@ -108,10 +108,10 @@ public class ConfigImportsTest {
 		ms.write("A", "", "x=1");
 		ms.write("B", "", "<A>");
 		Config c = Config.create("B").store(ms).build();
-		assertEquals("1", c.getString("x"));
+		assertEquals("1", c.get("x").get());
 		c.set("x", "2");
-		assertEquals("2", c.getString("x"));
-		assertEquals("1", Config.create("A").store(ms).build().getString("x"));
+		assertEquals("2", c.get("x").get());
+		assertEquals("1", Config.create("A").store(ms).build().get("x").get());
 	}
 
 	@Test
@@ -120,8 +120,8 @@ public class ConfigImportsTest {
 		ms.write("A", "", "x=1\n[A]\na1=1");
 		ms.write("B", "", "<A>\n[A]\na2=2");
 		Config c = Config.create("B").store(ms).build();
-		assertEquals("1", c.getString("A/a1"));
-		assertEquals("2", c.getString("A/a2"));
+		assertEquals("1", c.get("A/a1").get());
+		assertEquals("2", c.get("A/a2").get());
 	}
 
 	@Test
@@ -130,8 +130,8 @@ public class ConfigImportsTest {
 		ms.write("A", "", "x=1\n[A]\na1=1");
 		ms.write("B", "", "[A]\na2=2\n<A>");
 		Config c = Config.create("B").store(ms).build();
-		assertEquals("1", c.getString("A/a1"));
-		assertEquals("2", c.getString("A/a2"));
+		assertEquals("1", c.get("A/a1").get());
+		assertEquals("2", c.get("A/a2").get());
 	}
 
 	@Test
@@ -140,7 +140,7 @@ public class ConfigImportsTest {
 		ms.write("A", "", "x=1\n[A]\na1=1");
 		ms.write("B", "", "<A>\n[A]\na1=2");
 		Config c = Config.create("B").store(ms).build();
-		assertEquals("2", c.getString("A/a1"));
+		assertEquals("2", c.get("A/a1").get());
 	}
 
 	//-----------------------------------------------------------------------------------------------------------------
@@ -207,8 +207,8 @@ public class ConfigImportsTest {
 		assertEquals(1, l.getEvents().size());
 		assertEquals("2", l.getNewValue("A", "a1"));
 
-		assertEquals("2", cb.get("A/a1"));
-		assertEquals("2", cb.get("B/b1"));
+		assertEquals("2", cb.get("A/a1").get());
+		assertEquals("2", cb.get("B/b1").get());
 
 		l.reset();
 		cb.removeListener(l);
@@ -219,8 +219,8 @@ public class ConfigImportsTest {
 
 		assertFalse(l.isTriggered());
 
-		assertEquals("3", cb.get("A/a1"));
-		assertEquals("2", cb.get("B/b1"));
+		assertEquals("3", cb.get("A/a1").get());
+		assertEquals("2", cb.get("B/b1").get());
 	}
 
 	@Test
@@ -252,9 +252,9 @@ public class ConfigImportsTest {
 		assertEquals(1, l.getEvents().size());
 		assertEquals("2", l.getNewValue("A", "a1"));
 
-		assertEquals("2", cc.get("A/a1"));
-		assertEquals("2", cc.get("B/b1"));
-		assertEquals("3", cc.get("C/c1"));
+		assertEquals("2", cc.get("A/a1").get());
+		assertEquals("2", cc.get("B/b1").get());
+		assertEquals("3", cc.get("C/c1").get());
 
 		l.reset();
 		cc.removeListener(l);
@@ -266,9 +266,9 @@ public class ConfigImportsTest {
 
 		assertFalse(l.isTriggered());
 
-		assertEquals("3", cc.get("A/a1"));
-		assertEquals("2", cc.get("B/b1"));
-		assertEquals("3", cc.get("C/c1"));
+		assertEquals("3", cc.get("A/a1").get());
+		assertEquals("2", cc.get("B/b1").get());
+		assertEquals("3", cc.get("C/c1").get());
 	}
 
 	@Test
@@ -293,8 +293,8 @@ public class ConfigImportsTest {
 		assertEquals(1, l.getEvents().size());
 		assertEquals("2", l.getNewValue("A", "a1"));
 
-		assertEquals("2", cb.get("A/a1"));
-		assertEquals("2", cb.get("A/b1"));
+		assertEquals("2", cb.get("A/a1").get());
+		assertEquals("2", cb.get("A/b1").get());
 
 		l.reset();
 		cb.removeListener(l);
@@ -305,8 +305,8 @@ public class ConfigImportsTest {
 
 		assertFalse(l.isTriggered());
 
-		assertEquals("3", cb.get("A/a1"));
-		assertEquals("2", cb.get("A/b1"));
+		assertEquals("3", cb.get("A/a1").get());
+		assertEquals("2", cb.get("A/b1").get());
 	}
 
 	@Test
@@ -328,7 +328,7 @@ public class ConfigImportsTest {
 		ms.write("A", "x=1\n[A]\na1=1", "x=1\n[A]\na1=3");
 
 		assertFalse(l.isTriggered());
-		assertEquals("2", cb.get("A/a1"));
+		assertEquals("2", cb.get("A/a1").get());
 	}
 
 	@Test
@@ -353,7 +353,7 @@ public class ConfigImportsTest {
 		ms.write("A", "x=1\n[A]\na1=1", "x=1\n[A]\na1=4");
 
 		assertFalse(l.isTriggered());
-		assertEquals("3", cc.get("A/a1"));
+		assertEquals("3", cc.get("A/a1").get());
 	}
 
 	//-----------------------------------------------------------------------------------------------------------------
@@ -385,8 +385,8 @@ public class ConfigImportsTest {
 		assertEquals(2, l.getEvents().size());  // Should contain [SET(y = 1), SET(A/a1 = 1)]
 		assertEquals("1", l.getNewValue("A", "a1"));
 
-		assertEquals("1", cb.get("A/a1"));
-		assertEquals("2", cb.get("B/b1"));
+		assertEquals("1", cb.get("A/a1").get());
+		assertEquals("2", cb.get("B/b1").get());
 
 		assertEquals(2, ca.getConfigMap().getListeners().size());
 		assertEquals(1, cb.getConfigMap().getListeners().size());
@@ -399,8 +399,8 @@ public class ConfigImportsTest {
 		assertEquals(2, l.getEvents().size());  // Should contain [REMOVE_ENTRY(y), REMOVE_ENTRY(A/a1)]
  		assertEquals(null, l.getNewValue("A", "a1"));
 
-		assertNull(cb.get("A/a1"));
-		assertEquals("2", cb.get("B/b1"));
+		assertNull(cb.get("A/a1").orElse(null));
+		assertEquals("2", cb.get("B/b1").get());
 
 		l.reset();
 		cb.removeListener(l);
@@ -411,7 +411,7 @@ public class ConfigImportsTest {
 
 		assertFalse(l.isTriggered());
 
-		assertEquals("1", cb.get("A/a1"));
-		assertEquals("2", cb.get("B/b1"));
+		assertEquals("1", cb.get("A/a1").get());
+		assertEquals("2", cb.get("B/b1").get());
 	}
 }
diff --git a/juneau-utest/src/test/java/org/apache/juneau/config/ConfigInterfaceTest.java b/juneau-utest/src/test/java/org/apache/juneau/config/ConfigInterfaceTest.java
index 6fb6e5f..f7ad992 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/config/ConfigInterfaceTest.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/config/ConfigInterfaceTest.java
@@ -43,21 +43,21 @@ public class ConfigInterfaceTest {
 	public void testString() throws Exception {
 		proxy.setString("foo");
 		assertEquals("foo", proxy.getString());
-		assertEquals("foo", cf.get("A/string"));
+		assertEquals("foo", cf.get("A/string").get());
 	}
 
 	@Test
 	public void testInt() throws Exception {
 		proxy.setInt(1);
 		assertEquals(1, proxy.getInt());
-		assertEquals("1", cf.get("A/int"));
+		assertEquals("1", cf.get("A/int").get());
 	}
 
 	@Test
 	public void testInteger() throws Exception {
 		proxy.setInteger(2);
 		assertEquals(2, proxy.getInteger().intValue());
-		assertEquals("2", cf.get("A/integer"));
+		assertEquals("2", cf.get("A/integer").get());
 		assertObject(proxy.getInteger()).isType(Integer.class);
 	}
 
@@ -65,14 +65,14 @@ public class ConfigInterfaceTest {
 	public void testBoolean() throws Exception {
 		proxy.setBoolean(true);
 		assertEquals(true, proxy.isBoolean());
-		assertEquals("true", cf.get("A/boolean"));
+		assertEquals("true", cf.get("A/boolean").get());
 	}
 
 	@Test
 	public void testBooleanObject() throws Exception {
 		proxy.setBooleanObject(true);
 		assertEquals(true, proxy.getBooleanObject().booleanValue());
-		assertEquals("true", cf.get("A/booleanObject"));
+		assertEquals("true", cf.get("A/booleanObject").get());
 		assertObject(proxy.getBooleanObject()).isType(Boolean.class);
 	}
 
@@ -80,21 +80,21 @@ public class ConfigInterfaceTest {
 	public void testFloat() throws Exception {
 		proxy.setFloat(1f);
 		assertTrue(1f == proxy.getFloat());
-		assertEquals("1.0", cf.get("A/float"));
+		assertEquals("1.0", cf.get("A/float").get());
 	}
 
 	@Test
 	public void testFloatObject() throws Exception {
 		proxy.setFloatObject(1f);
 		assertTrue(1f == proxy.getFloatObject().floatValue());
-		assertEquals("1.0", cf.get("A/floatObject"));
+		assertEquals("1.0", cf.get("A/floatObject").get());
 		assertObject(proxy.getFloatObject()).isType(Float.class);
 	}
 
 	@Test
 	public void testInt3dArray() throws Exception {
 		proxy.setInt3dArray(new int[][][]{{{1,2},null},null});
-		assertEquals("[[[1,2],null],null]", cf.get("A/int3dArray"));
+		assertEquals("[[[1,2],null],null]", cf.get("A/int3dArray").get());
 		assertObject(proxy.getInt3dArray()).asJson().is("[[[1,2],null],null]");
 		assertObject(proxy.getInt3dArray()).isType(int[][][].class);
 	}
@@ -103,7 +103,7 @@ public class ConfigInterfaceTest {
 	public void testInteger3dArray() throws Exception {
 		proxy.setInteger3dArray(new Integer[][][]{{{1,null},null},null});
 		assertObject(proxy.getInteger3dArray()).asJson().is("[[[1,null],null],null]");
-		assertEquals("[[[1,null],null],null]", cf.get("A/integer3dArray"));
+		assertEquals("[[[1,null],null],null]", cf.get("A/integer3dArray").get());
 		assertObject(proxy.getInteger3dArray()[0][0][0]).isType(Integer.class);
 	}
 
@@ -111,14 +111,14 @@ public class ConfigInterfaceTest {
 	public void testString3dArray() throws Exception {
 		proxy.setString3dArray(new String[][][]{{{"foo",null},null},null});
 		assertObject(proxy.getString3dArray()).asJson().is("[[['foo',null],null],null]");
-		assertEquals("[[['foo',null],null],null]", cf.get("A/string3dArray"));
+		assertEquals("[[['foo',null],null],null]", cf.get("A/string3dArray").get());
 	}
 
 	@Test
 	public void testIntegerList() throws Exception {
 		proxy.setIntegerList(AList.of(1,null));
 		assertObject(proxy.getIntegerList()).asJson().is("[1,null]");
-		assertEquals("[1,null]", cf.get("A/integerList"));
+		assertEquals("[1,null]", cf.get("A/integerList").get());
 		assertObject(proxy.getIntegerList().get(0)).isType(Integer.class);
 	}
 
@@ -126,7 +126,7 @@ public class ConfigInterfaceTest {
 	public void testInteger3dList() throws Exception {
 		proxy.setInteger3dList(AList.of(AList.of(AList.of(1,null),null),null));
 		assertObject(proxy.getInteger3dList()).asJson().is("[[[1,null],null],null]");
-		assertEquals("[[[1,null],null],null]", cf.get("A/integer3dList"));
+		assertEquals("[[[1,null],null],null]", cf.get("A/integer3dList").get());
 		assertObject(proxy.getInteger3dList().get(0).get(0).get(0)).isType(Integer.class);
 	}
 
@@ -134,7 +134,7 @@ public class ConfigInterfaceTest {
 	public void testInteger1d3dList() throws Exception {
 		proxy.setInteger1d3dList(AList.of(new Integer[][][]{{{1,null},null},null},null));
 		assertObject(proxy.getInteger1d3dList()).asJson().is("[[[[1,null],null],null],null]");
-		assertEquals("[[[[1,null],null],null],null]", cf.get("A/integer1d3dList"));
+		assertEquals("[[[[1,null],null],null],null]", cf.get("A/integer1d3dList").get());
 		assertObject(proxy.getInteger1d3dList().get(0)[0][0][0]).isType(Integer.class);
 	}
 
@@ -142,7 +142,7 @@ public class ConfigInterfaceTest {
 	public void testInt1d3dList() throws Exception {
 		proxy.setInt1d3dList(AList.of(new int[][][]{{{1,2},null},null},null));
 		assertObject(proxy.getInt1d3dList()).asJson().is("[[[[1,2],null],null],null]");
-		assertEquals("[[[[1,2],null],null],null]", cf.get("A/int1d3dList"));
+		assertEquals("[[[[1,2],null],null],null]", cf.get("A/int1d3dList").get());
 		assertObject(proxy.getInt1d3dList().get(0)).isType(int[][][].class);
 	}
 
@@ -150,7 +150,7 @@ public class ConfigInterfaceTest {
 	public void testStringList() throws Exception {
 		proxy.setStringList(Arrays.asList("foo","bar",null));
 		assertObject(proxy.getStringList()).asJson().is("['foo','bar',null]");
-		assertEquals("['foo','bar',null]", cf.get("A/stringList"));
+		assertEquals("['foo','bar',null]", cf.get("A/stringList").get());
 	}
 
 	// Beans
@@ -159,7 +159,7 @@ public class ConfigInterfaceTest {
 	public void testBean() throws Exception {
 		proxy.setBean(ABean.get());
 		assertObject(proxy.getBean()).asJson().is("{a:1,b:'foo'}");
-		assertEquals("{a:1,b:'foo'}", cf.get("A/bean"));
+		assertEquals("{a:1,b:'foo'}", cf.get("A/bean").get());
 		assertObject(proxy.getBean()).isType(ABean.class);
 	}
 
@@ -167,7 +167,7 @@ public class ConfigInterfaceTest {
 	public void testBean3dArray() throws Exception {
 		proxy.setBean3dArray(new ABean[][][]{{{ABean.get(),null},null},null});
 		assertObject(proxy.getBean3dArray()).asJson().is("[[[{a:1,b:'foo'},null],null],null]");
-		assertEquals("[[[{a:1,b:'foo'},null],null],null]", cf.get("A/bean3dArray"));
+		assertEquals("[[[{a:1,b:'foo'},null],null],null]", cf.get("A/bean3dArray").get());
 		assertObject(proxy.getBean3dArray()[0][0][0]).isType(ABean.class);
 	}
 
@@ -175,7 +175,7 @@ public class ConfigInterfaceTest {
 	public void testBeanList() throws Exception {
 		proxy.setBeanList(Arrays.asList(ABean.get()));
 		assertObject(proxy.getBeanList()).asJson().is("[{a:1,b:'foo'}]");
-		assertEquals("[{a:1,b:'foo'}]", cf.get("A/beanList"));
+		assertEquals("[{a:1,b:'foo'}]", cf.get("A/beanList").get());
 		assertObject(proxy.getBeanList().get(0)).isType(ABean.class);
 	}
 
@@ -183,7 +183,7 @@ public class ConfigInterfaceTest {
 	public void testBean1d3dList() throws Exception {
 		proxy.setBean1d3dList(AList.of(new ABean[][][]{{{ABean.get(),null},null},null},null));
 		assertObject(proxy.getBean1d3dList()).asJson().is("[[[[{a:1,b:'foo'},null],null],null],null]");
-		assertEquals("[[[[{a:1,b:'foo'},null],null],null],null]", cf.get("A/bean1d3dList"));
+		assertEquals("[[[[{a:1,b:'foo'},null],null],null],null]", cf.get("A/bean1d3dList").get());
 		assertObject(proxy.getBean1d3dList().get(0)[0][0][0]).isType(ABean.class);
 	}
 
@@ -191,7 +191,7 @@ public class ConfigInterfaceTest {
 	public void testBeanMap() throws Exception {
 		proxy.setBeanMap(AMap.of("foo",ABean.get()));
 		assertObject(proxy.getBeanMap()).asJson().is("{foo:{a:1,b:'foo'}}");
-		assertEquals("{foo:{a:1,b:'foo'}}", cf.get("A/beanMap"));
+		assertEquals("{foo:{a:1,b:'foo'}}", cf.get("A/beanMap").get());
 		assertObject(proxy.getBeanMap().get("foo")).isType(ABean.class);
 	}
 
@@ -199,7 +199,7 @@ public class ConfigInterfaceTest {
 	public void testBeanListMap() throws Exception {
 		proxy.setBeanListMap(AMap.of("foo",Arrays.asList(ABean.get())));
 		assertObject(proxy.getBeanListMap()).asJson().is("{foo:[{a:1,b:'foo'}]}");
-		assertEquals("{foo:[{a:1,b:'foo'}]}", cf.get("A/beanListMap"));
+		assertEquals("{foo:[{a:1,b:'foo'}]}", cf.get("A/beanListMap").get());
 		assertObject(proxy.getBeanListMap().get("foo").get(0)).isType(ABean.class);
 	}
 
@@ -207,7 +207,7 @@ public class ConfigInterfaceTest {
 	public void testBean1d3dListMap() throws Exception {
 		proxy.setBean1d3dListMap(AMap.of("foo",AList.of(new ABean[][][]{{{ABean.get(),null},null},null},null)));
 		assertObject(proxy.getBean1d3dListMap()).asJson().is("{foo:[[[[{a:1,b:'foo'},null],null],null],null]}");
-		assertEquals("{foo:[[[[{a:1,b:'foo'},null],null],null],null]}", cf.get("A/bean1d3dListMap"));
+		assertEquals("{foo:[[[[{a:1,b:'foo'},null],null],null],null]}", cf.get("A/bean1d3dListMap").get());
 		assertObject(proxy.getBean1d3dListMap().get("foo").get(0)[0][0][0]).isType(ABean.class);
 	}
 
@@ -215,7 +215,7 @@ public class ConfigInterfaceTest {
 	public void testBeanListMapIntegerKeys() throws Exception {
 		proxy.setBeanListMapIntegerKeys(AMap.of(1,Arrays.asList(ABean.get())));
 		assertObject(proxy.getBeanListMapIntegerKeys()).asJson().is("{'1':[{a:1,b:'foo'}]}");
-		assertEquals("{'1':[{a:1,b:'foo'}]}", cf.get("A/beanListMapIntegerKeys"));
+		assertEquals("{'1':[{a:1,b:'foo'}]}", cf.get("A/beanListMapIntegerKeys").get());
 		assertObject(proxy.getBeanListMapIntegerKeys().get(1).get(0)).isType(ABean.class);
 	}
 
@@ -225,7 +225,7 @@ public class ConfigInterfaceTest {
 	public void testTypedBean() throws Exception {
 		proxy.setTypedBean(TypedBeanImpl.get());
 		assertObject(proxy.getTypedBean()).asJson().is("{a:1,b:'foo'}");
-		assertEquals("{_type:'TypedBeanImpl',a:1,b:'foo'}", cf.get("A/typedBean"));
+		assertEquals("{_type:'TypedBeanImpl',a:1,b:'foo'}", cf.get("A/typedBean").get());
 		assertObject(proxy.getTypedBean()).isType(TypedBeanImpl.class);
 	}
 
@@ -233,7 +233,7 @@ public class ConfigInterfaceTest {
 	public void testTypedBean3dArray() throws Exception {
 		proxy.setTypedBean3dArray(new TypedBean[][][]{{{TypedBeanImpl.get(),null},null},null});
 		assertObject(proxy.getTypedBean3dArray()).asJson().is("[[[{a:1,b:'foo'},null],null],null]");
-		assertEquals("[[[{_type:'TypedBeanImpl',a:1,b:'foo'},null],null],null]", cf.get("A/typedBean3dArray"));
+		assertEquals("[[[{_type:'TypedBeanImpl',a:1,b:'foo'},null],null],null]", cf.get("A/typedBean3dArray").get());
 		assertObject(proxy.getTypedBean3dArray()[0][0][0]).isType(TypedBeanImpl.class);
 	}
 
@@ -241,7 +241,7 @@ public class ConfigInterfaceTest {
 	public void testTypedBeanList() throws Exception {
 		proxy.setTypedBeanList(Arrays.asList((TypedBean)TypedBeanImpl.get()));
 		assertObject(proxy.getTypedBeanList()).asJson().is("[{a:1,b:'foo'}]");
-		assertEquals("[{_type:'TypedBeanImpl',a:1,b:'foo'}]", cf.get("A/typedBeanList"));
+		assertEquals("[{_type:'TypedBeanImpl',a:1,b:'foo'}]", cf.get("A/typedBeanList").get());
 		assertObject(proxy.getTypedBeanList().get(0)).isType(TypedBeanImpl.class);
 	}
 
@@ -249,7 +249,7 @@ public class ConfigInterfaceTest {
 	public void testTypedBean1d3dList() throws Exception {
 		proxy.setTypedBean1d3dList(AList.of(new TypedBean[][][]{{{TypedBeanImpl.get(),null},null},null},null));
 		assertObject(proxy.getTypedBean1d3dList()).asJson().is("[[[[{a:1,b:'foo'},null],null],null],null]");
-		assertEquals("[[[[{_type:'TypedBeanImpl',a:1,b:'foo'},null],null],null],null]", cf.get("A/typedBean1d3dList"));
+		assertEquals("[[[[{_type:'TypedBeanImpl',a:1,b:'foo'},null],null],null],null]", cf.get("A/typedBean1d3dList").get());
 		assertObject(proxy.getTypedBean1d3dList().get(0)[0][0][0]).isType(TypedBeanImpl.class);
 	}
 
@@ -257,7 +257,7 @@ public class ConfigInterfaceTest {
 	public void testTypedBeanMap() throws Exception {
 		proxy.setTypedBeanMap(AMap.of("foo",TypedBeanImpl.get()));
 		assertObject(proxy.getTypedBeanMap()).asJson().is("{foo:{a:1,b:'foo'}}");
-		assertEquals("{foo:{_type:'TypedBeanImpl',a:1,b:'foo'}}", cf.get("A/typedBeanMap"));
+		assertEquals("{foo:{_type:'TypedBeanImpl',a:1,b:'foo'}}", cf.get("A/typedBeanMap").get());
 		assertObject(proxy.getTypedBeanMap().get("foo")).isType(TypedBeanImpl.class);
 	}
 
@@ -265,7 +265,7 @@ public class ConfigInterfaceTest {
 	public void testTypedBeanListMap() throws Exception {
 		proxy.setTypedBeanListMap(AMap.of("foo",Arrays.asList((TypedBean)TypedBeanImpl.get())));
 		assertObject(proxy.getTypedBeanListMap()).asJson().is("{foo:[{a:1,b:'foo'}]}");
-		assertEquals("{foo:[{_type:'TypedBeanImpl',a:1,b:'foo'}]}", cf.get("A/typedBeanListMap"));
+		assertEquals("{foo:[{_type:'TypedBeanImpl',a:1,b:'foo'}]}", cf.get("A/typedBeanListMap").get());
 		assertObject(proxy.getTypedBeanListMap().get("foo").get(0)).isType(TypedBeanImpl.class);
 	}
 
@@ -273,7 +273,7 @@ public class ConfigInterfaceTest {
 	public void testTypedBean1d3dListMap() throws Exception {
 		proxy.setTypedBean1d3dListMap(AMap.of("foo",AList.of(new TypedBean[][][]{{{TypedBeanImpl.get(),null},null},null},null)));
 		assertObject(proxy.getTypedBean1d3dListMap()).asJson().is("{foo:[[[[{a:1,b:'foo'},null],null],null],null]}");
-		assertEquals("{foo:[[[[{_type:'TypedBeanImpl',a:1,b:'foo'},null],null],null],null]}", cf.get("A/typedBean1d3dListMap"));
+		assertEquals("{foo:[[[[{_type:'TypedBeanImpl',a:1,b:'foo'},null],null],null],null]}", cf.get("A/typedBean1d3dListMap").get());
 		assertObject(proxy.getTypedBean1d3dListMap().get("foo").get(0)[0][0][0]).isType(TypedBeanImpl.class);
 	}
 
@@ -281,7 +281,7 @@ public class ConfigInterfaceTest {
 	public void testTypedBeanListMapIntegerKeys() throws Exception {
 		proxy.setTypedBeanListMapIntegerKeys(AMap.of(1,Arrays.asList((TypedBean)TypedBeanImpl.get())));
 		assertObject(proxy.getTypedBeanListMapIntegerKeys()).asJson().is("{'1':[{a:1,b:'foo'}]}");
-		assertEquals("{'1':[{_type:'TypedBeanImpl',a:1,b:'foo'}]}", cf.get("A/typedBeanListMapIntegerKeys"));
+		assertEquals("{'1':[{_type:'TypedBeanImpl',a:1,b:'foo'}]}", cf.get("A/typedBeanListMapIntegerKeys").get());
 		assertObject(proxy.getTypedBeanListMapIntegerKeys().get(1).get(0)).isType(TypedBeanImpl.class);
 	}
 
@@ -291,7 +291,7 @@ public class ConfigInterfaceTest {
 	public void testSwappedObject() throws Exception {
 		proxy.setSwappedObject(new SwappedObject());
 		assertObject(proxy.getSwappedObject()).asJson().is("'swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/'");
-		assertEquals("swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/", cf.get("A/swappedObject"));
+		assertEquals("swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/", cf.get("A/swappedObject").get());
 		assertObject(proxy.getSwappedObject()).isType(SwappedObject.class);
 	}
 
@@ -299,7 +299,7 @@ public class ConfigInterfaceTest {
 	public void testSwappedObject3dArray() throws Exception {
 		proxy.setSwappedObject3dArray(new SwappedObject[][][]{{{new SwappedObject(),null},null},null});
 		assertObject(proxy.getSwappedObject3dArray()).asJson().is("[[['swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/',null],null],null]");
-		assertEquals("[[['swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/',null],null],null]", cf.get("A/swappedObject3dArray"));
+		assertEquals("[[['swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/',null],null],null]", cf.get("A/swappedObject3dArray").get());
 		assertObject(proxy.getSwappedObject3dArray()[0][0][0]).isType(SwappedObject.class);
 	}
 
@@ -307,7 +307,7 @@ public class ConfigInterfaceTest {
 	public void testSwappedObjectMap() throws Exception {
 		proxy.setSwappedObjectMap(AMap.of(new SwappedObject(), new SwappedObject()));
 		assertObject(proxy.getSwappedObjectMap()).asJson().is("{'swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/':'swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/'}");
-		assertEquals("{'swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/':'swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/'}", cf.get("A/swappedObjectMap"));
+		assertEquals("{'swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/':'swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/'}", cf.get("A/swappedObjectMap").get());
 		assertObject(proxy.getSwappedObjectMap().keySet().iterator().next()).isType(SwappedObject.class);
 		assertObject(proxy.getSwappedObjectMap().values().iterator().next()).isType(SwappedObject.class);
 	}
@@ -316,7 +316,7 @@ public class ConfigInterfaceTest {
 	public void testSwappedObject3dMap() throws Exception {
 		proxy.setSwappedObject3dMap(AMap.of(new SwappedObject(), new SwappedObject[][][]{{{new SwappedObject(),null},null},null}));
 		assertObject(proxy.getSwappedObject3dMap()).asJson().is("{'swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/':[[['swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/',null],null],null]}");
-		assertEquals("{'swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/':[[['swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/',null],null],null]}", cf.get("A/swappedObject3dMap"));
+		assertEquals("{'swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/':[[['swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/',null],null],null]}", cf.get("A/swappedObject3dMap").get());
 		assertObject(proxy.getSwappedObject3dMap().keySet().iterator().next()).isType(SwappedObject.class);
 		assertObject(proxy.getSwappedObject3dMap().values().iterator().next()[0][0][0]).isType(SwappedObject.class);
 	}
@@ -327,7 +327,7 @@ public class ConfigInterfaceTest {
 	public void testImplicitSwappedObject() throws Exception {
 		proxy.setImplicitSwappedObject(new ImplicitSwappedObject());
 		assertObject(proxy.getImplicitSwappedObject()).asJson().is("'swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/'");
-		assertEquals("swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/", cf.get("A/implicitSwappedObject"));
+		assertEquals("swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/", cf.get("A/implicitSwappedObject").get());
 		assertObject(proxy.getImplicitSwappedObject()).isType(ImplicitSwappedObject.class);
 	}
 
@@ -335,7 +335,7 @@ public class ConfigInterfaceTest {
 	public void testImplicitSwappedObject3dArray() throws Exception {
 		proxy.setImplicitSwappedObject3dArray(new ImplicitSwappedObject[][][]{{{new ImplicitSwappedObject(),null},null},null});
 		assertObject(proxy.getImplicitSwappedObject3dArray()).asJson().is("[[['swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/',null],null],null]");
-		assertEquals("[[['swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/',null],null],null]", cf.get("A/implicitSwappedObject3dArray"));
+		assertEquals("[[['swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/',null],null],null]", cf.get("A/implicitSwappedObject3dArray").get());
 		assertObject(proxy.getImplicitSwappedObject3dArray()[0][0][0]).isType(ImplicitSwappedObject.class);
 	}
 
@@ -343,7 +343,7 @@ public class ConfigInterfaceTest {
 	public void testImplicitSwappedObjectMap() throws Exception {
 		proxy.setImplicitSwappedObjectMap(AMap.of(new ImplicitSwappedObject(), new ImplicitSwappedObject()));
 		assertObject(proxy.getImplicitSwappedObjectMap()).asJson().is("{'swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/':'swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/'}");
-		assertEquals("{'swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/':'swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/'}", cf.get("A/implicitSwappedObjectMap"));
+		assertEquals("{'swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/':'swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/'}", cf.get("A/implicitSwappedObjectMap").get());
 		assertObject(proxy.getImplicitSwappedObjectMap().keySet().iterator().next()).isType(ImplicitSwappedObject.class);
 		assertObject(proxy.getImplicitSwappedObjectMap().values().iterator().next()).isType(ImplicitSwappedObject.class);
 	}
@@ -352,7 +352,7 @@ public class ConfigInterfaceTest {
 	public void testImplicitSwappedObject3dMap() throws Exception {
 		proxy.setImplicitSwappedObject3dMap(AMap.of(new ImplicitSwappedObject(), new ImplicitSwappedObject[][][]{{{new ImplicitSwappedObject(),null},null},null}));
 		assertObject(proxy.getImplicitSwappedObject3dMap()).asJson().is("{'swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/':[[['swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/',null],null],null]}");
-		assertEquals("{'swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/':[[['swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/',null],null],null]}", cf.get("A/implicitSwappedObject3dMap"));
+		assertEquals("{'swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/':[[['swap-~!@#$%^&*()_+`-={}[]|:;\"<,>.?/',null],null],null]}", cf.get("A/implicitSwappedObject3dMap").get());
 		assertObject(proxy.getImplicitSwappedObject3dMap().keySet().iterator().next()).isType(ImplicitSwappedObject.class);
 		assertObject(proxy.getImplicitSwappedObject3dMap().values().iterator().next()[0][0][0]).isType(ImplicitSwappedObject.class);
 	}
@@ -363,7 +363,7 @@ public class ConfigInterfaceTest {
 	public void testEnum() throws Exception {
 		proxy.setEnum(TestEnum.TWO);
 		assertObject(proxy.getEnum()).asJson().is("'TWO'");
-		assertEquals("TWO", cf.get("A/enum"));
+		assertEquals("TWO", cf.get("A/enum").get());
 		assertObject(proxy.getEnum()).isType(TestEnum.class);
 	}
 
@@ -371,7 +371,7 @@ public class ConfigInterfaceTest {
 	public void testEnum3d() throws Exception {
 		proxy.setEnum3d(new TestEnum[][][]{{{TestEnum.TWO,null},null},null});
 		assertObject(proxy.getEnum3d()).asJson().is("[[['TWO',null],null],null]");
-		assertEquals("[[['TWO',null],null],null]", cf.get("A/enum3d"));
+		assertEquals("[[['TWO',null],null],null]", cf.get("A/enum3d").get());
 		assertObject(proxy.getEnum3d()[0][0][0]).isType(TestEnum.class);
 	}
 
@@ -379,7 +379,7 @@ public class ConfigInterfaceTest {
 	public void testEnumList() throws Exception {
 		proxy.setEnumList(AList.of(TestEnum.TWO,null));
 		assertObject(proxy.getEnumList()).asJson().is("['TWO',null]");
-		assertEquals("['TWO',null]", cf.get("A/enumList"));
+		assertEquals("['TWO',null]", cf.get("A/enumList").get());
 		assertObject(proxy.getEnumList().get(0)).isType(TestEnum.class);
 	}
 
@@ -387,7 +387,7 @@ public class ConfigInterfaceTest {
 	public void testEnum3dList() throws Exception {
 		proxy.setEnum3dList(AList.of(AList.of(AList.of(TestEnum.TWO,null),null),null));
 		assertObject(proxy.getEnum3dList()).asJson().is("[[['TWO',null],null],null]");
-		assertEquals("[[['TWO',null],null],null]", cf.get("A/enum3dList"));
+		assertEquals("[[['TWO',null],null],null]", cf.get("A/enum3dList").get());
 		assertObject(proxy.getEnum3dList().get(0).get(0).get(0)).isType(TestEnum.class);
 	}
 
@@ -395,7 +395,7 @@ public class ConfigInterfaceTest {
 	public void testEnum1d3dList() throws Exception {
 		proxy.setEnum1d3dList(AList.of(new TestEnum[][][]{{{TestEnum.TWO,null},null},null},null));
 		assertObject(proxy.getEnum1d3dList()).asJson().is("[[[['TWO',null],null],null],null]");
-		assertEquals("[[[['TWO',null],null],null],null]", cf.get("A/enum1d3dList"));
+		assertEquals("[[[['TWO',null],null],null],null]", cf.get("A/enum1d3dList").get());
 		assertObject(proxy.getEnum1d3dList().get(0)[0][0][0]).isType(TestEnum.class);
 	}
 
@@ -403,7 +403,7 @@ public class ConfigInterfaceTest {
 	public void testEnumMap() throws Exception {
 		proxy.setEnumMap(AMap.of(TestEnum.ONE,TestEnum.TWO));
 		assertObject(proxy.getEnumMap()).asJson().is("{ONE:'TWO'}");
-		assertEquals("{ONE:'TWO'}", cf.get("A/enumMap"));
+		assertEquals("{ONE:'TWO'}", cf.get("A/enumMap").get());
 		assertObject(proxy.getEnumMap().keySet().iterator().next()).isType(TestEnum.class);
 		assertObject(proxy.getEnumMap().values().iterator().next()).isType(TestEnum.class);
 	}
@@ -412,7 +412,7 @@ public class ConfigInterfaceTest {
 	public void testEnum3dArrayMap() throws Exception {
 		proxy.setEnum3dArrayMap(AMap.of(TestEnum.ONE,new TestEnum[][][]{{{TestEnum.TWO,null},null},null}));
 		assertObject(proxy.getEnum3dArrayMap()).asJson().is("{ONE:[[['TWO',null],null],null]}");
-		assertEquals("{ONE:[[['TWO',null],null],null]}", cf.get("A/enum3dArrayMap"));
+		assertEquals("{ONE:[[['TWO',null],null],null]}", cf.get("A/enum3dArrayMap").get());
 		assertObject(proxy.getEnum3dArrayMap().keySet().iterator().next()).isType(TestEnum.class);
 		assertObject(proxy.getEnum3dArrayMap().values().iterator().next()[0][0][0]).isType(TestEnum.class);
 	}
@@ -421,7 +421,7 @@ public class ConfigInterfaceTest {
 	public void testEnum1d3dListMap() throws Exception {
 		proxy.setEnum1d3dListMap(AMap.of(TestEnum.ONE,AList.of(new TestEnum[][][]{{{TestEnum.TWO,null},null},null},null)));
 		assertObject(proxy.getEnum1d3dListMap()).asJson().is("{ONE:[[[['TWO',null],null],null],null]}");
-		assertEquals("{ONE:[[[['TWO',null],null],null],null]}", cf.get("A/enum1d3dListMap"));
+		assertEquals("{ONE:[[[['TWO',null],null],null],null]}", cf.get("A/enum1d3dListMap").get());
 		assertObject(proxy.getEnum1d3dListMap().keySet().iterator().next()).isType(TestEnum.class);
 		assertObject(proxy.getEnum1d3dListMap().values().iterator().next().get(0)[0][0][0]).isType(TestEnum.class);
 	}
diff --git a/juneau-utest/src/test/java/org/apache/juneau/config/ConfigTest.java b/juneau-utest/src/test/java/org/apache/juneau/config/ConfigTest.java
index 78baf20..f96bc98 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/config/ConfigTest.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/config/ConfigTest.java
@@ -47,12 +47,12 @@ public class ConfigTest {
 	public void get() throws Exception {
 		Config c = init("a=1", "[S]", "b=2");
 
-		assertEquals("1", c.get("a"));
-		assertEquals("1", c.get("a"));
-		assertEquals("2", c.get("S/b"));
-		assertNull(c.get("b"));
-		assertNull(c.get("S/c"));
-		assertNull(c.get("T/d"));
+		assertEquals("1", c.get("a").get());
+		assertEquals("1", c.get("a").get());
+		assertEquals("2", c.get("S/b").get());
+		assertNull(c.get("b").orElse(null));
+		assertNull(c.get("S/c").orElse(null));
+		assertNull(c.get("T/d").orElse(null));
 		assertThrown(()->c.get(null)).message().is("Argument 'key' cannot be null.");
 		c.close();
 	}
@@ -71,30 +71,30 @@ public class ConfigTest {
 		c.set("S/b2", "6");
 		c.set("T/c1", "7");
 
-		assertEquals("2", c.get("a1"));
-		assertEquals("3", c.get("a2"));
-		assertEquals("4", c.get("a3"));
-		assertEquals("5", c.get("S/b1"));
-		assertEquals("6", c.get("S/b2"));
-		assertEquals("7", c.get("T/c1"));
+		assertEquals("2", c.get("a1").get());
+		assertEquals("3", c.get("a2").get());
+		assertEquals("4", c.get("a3").get());
+		assertEquals("5", c.get("S/b1").get());
+		assertEquals("6", c.get("S/b2").get());
+		assertEquals("7", c.get("T/c1").get());
 
 		c.commit();
 
-		assertEquals("2", c.get("a1"));
-		assertEquals("3", c.get("a2"));
-		assertEquals("4", c.get("a3"));
-		assertEquals("5", c.get("S/b1"));
-		assertEquals("6", c.get("S/b2"));
-		assertEquals("7", c.get("T/c1"));
+		assertEquals("2", c.get("a1").get());
+		assertEquals("3", c.get("a2").get());
+		assertEquals("4", c.get("a3").get());
+		assertEquals("5", c.get("S/b1").get());
+		assertEquals("6", c.get("S/b2").get());
+		assertEquals("7", c.get("T/c1").get());
 
 		c = cb.build();
 
-		assertEquals("2", c.get("a1"));
-		assertEquals("3", c.get("a2"));
-		assertEquals("4", c.get("a3"));
-		assertEquals("5", c.get("S/b1"));
-		assertEquals("6", c.get("S/b2"));
-		assertEquals("7", c.get("T/c1"));
+		assertEquals("2", c.get("a1").get());
+		assertEquals("3", c.get("a2").get());
+		assertEquals("4", c.get("a3").get());
+		assertEquals("5", c.get("S/b1").get());
+		assertEquals("6", c.get("S/b2").get());
+		assertEquals("7", c.get("T/c1").get());
 
 		assertString(c).replaceAll("\\r?\\n", "|").is("a1 = 2|a2 = 3|a3 = 4|[S]|b1 = 5|b2 = 6|[T]|c1 = 7|");
 	}
@@ -113,30 +113,30 @@ public class ConfigTest {
 		c.set("S/b2", 6);
 		c.set("T/c1", 7);
 
-		assertEquals("2", c.get("a1"));
-		assertEquals("3", c.get("a2"));
-		assertEquals("4", c.get("a3"));
-		assertEquals("5", c.get("S/b1"));
-		assertEquals("6", c.get("S/b2"));
-		assertEquals("7", c.get("T/c1"));
+		assertEquals("2", c.get("a1").get());
+		assertEquals("3", c.get("a2").get());
+		assertEquals("4", c.get("a3").get());
+		assertEquals("5", c.get("S/b1").get());
+		assertEquals("6", c.get("S/b2").get());
+		assertEquals("7", c.get("T/c1").get());
 
 		c.commit();
 
-		assertEquals("2", c.get("a1"));
-		assertEquals("3", c.get("a2"));
-		assertEquals("4", c.get("a3"));
-		assertEquals("5", c.get("S/b1"));
-		assertEquals("6", c.get("S/b2"));
-		assertEquals("7", c.get("T/c1"));
+		assertEquals("2", c.get("a1").get());
+		assertEquals("3", c.get("a2").get());
+		assertEquals("4", c.get("a3").get());
+		assertEquals("5", c.get("S/b1").get());
+		assertEquals("6", c.get("S/b2").get());
+		assertEquals("7", c.get("T/c1").get());
 
 		c = cb.build();
 
-		assertEquals("2", c.get("a1"));
-		assertEquals("3", c.get("a2"));
-		assertEquals("4", c.get("a3"));
-		assertEquals("5", c.get("S/b1"));
-		assertEquals("6", c.get("S/b2"));
-		assertEquals("7", c.get("T/c1"));
+		assertEquals("2", c.get("a1").get());
+		assertEquals("3", c.get("a2").get());
+		assertEquals("4", c.get("a3").get());
+		assertEquals("5", c.get("S/b1").get());
+		assertEquals("6", c.get("S/b2").get());
+		assertEquals("7", c.get("T/c1").get());
 
 		assertString(c).replaceAll("\\r?\\n", "|").is("a1 = 2|a2 = 3|a3 = 4|[S]|b1 = 5|b2 = 6|[T]|c1 = 7|");
 	}
@@ -156,12 +156,12 @@ public class ConfigTest {
 		c.set("S/b2", b, UonSerializer.DEFAULT);
 		c.set("T/c1", b, UonSerializer.DEFAULT);
 
-		assertEquals("(foo=bar)", c.get("a1"));
-		assertEquals("(foo=bar)", c.get("a2"));
-		assertEquals("(foo=bar)", c.get("a3"));
-		assertEquals("(foo=bar)", c.get("S/b1"));
-		assertEquals("(foo=bar)", c.get("S/b2"));
-		assertEquals("(foo=bar)", c.get("T/c1"));
+		assertEquals("(foo=bar)", c.get("a1").get());
+		assertEquals("(foo=bar)", c.get("a2").get());
+		assertEquals("(foo=bar)", c.get("a3").get());
+		assertEquals("(foo=bar)", c.get("S/b1").get());
+		assertEquals("(foo=bar)", c.get("S/b2").get());
+		assertEquals("(foo=bar)", c.get("T/c1").get());
 	}
 
 	//====================================================================================================
@@ -185,12 +185,12 @@ public class ConfigTest {
 		c = cb.build();
 		assertString(c).replaceAll("\\r?\\n", "|").is("#c1|#c2|a1* = {RhMWWFIFVksf} # comment|#c1|#c2|a2* = {RhMWWFIFVksf} # comment|#c1|#c2|a3* = {RhMWWFIFVksf} # comment|[S]|#c1|#c2|b1* = {RhMWWFIFVksf} # comment|#c1|#c2|b2* = {RhMWWFIFVksf} # comment|[T]|#c1|#c2|c1* = {RhMWWFIFVksf} # comment|");
 
-		assertEquals("(foo=bar)", c.get("a1"));
-		assertEquals("(foo=bar)", c.get("a2"));
-		assertEquals("(foo=bar)", c.get("a3"));
-		assertEquals("(foo=bar)", c.get("S/b1"));
-		assertEquals("(foo=bar)", c.get("S/b2"));
-		assertEquals("(foo=bar)", c.get("T/c1"));
+		assertEquals("(foo=bar)", c.get("a1").get());
+		assertEquals("(foo=bar)", c.get("a2").get());
+		assertEquals("(foo=bar)", c.get("a3").get());
+		assertEquals("(foo=bar)", c.get("S/b1").get());
+		assertEquals("(foo=bar)", c.get("S/b2").get());
+		assertEquals("(foo=bar)", c.get("T/c1").get());
 	}
 
 	//====================================================================================================
@@ -220,13 +220,13 @@ public class ConfigTest {
 	public void xgetString1() throws Exception {
 		Config c = init("a1=1", "a2=2", "[S]", "b1=1", "b2=");
 
-		assertEquals("1", c.getString("a1"));
-		assertEquals("2", c.getString("a2"));
-		assertEquals(null, c.getString("a3"));
-		assertEquals("1", c.getString("S/b1"));
-		assertEquals("", c.getString("S/b2"));
-		assertEquals(null, c.getString("S/b3"));
-		assertEquals(null, c.getString("T/c1"));
+		assertEquals("1", c.get("a1").as(String.class).orElse(null));
+		assertEquals("2", c.get("a2").as(String.class).orElse(null));
+		assertEquals(null, c.get("a3").as(String.class).orElse(null));
+		assertEquals("1", c.get("S/b1").as(String.class).orElse(null));
+		assertEquals("", c.get("S/b2").as(String.class).orElse(null));
+		assertEquals(null, c.get("S/b3").as(String.class).orElse(null));
+		assertEquals(null, c.get("T/c1").as(String.class).orElse(null));
 	}
 
 	//====================================================================================================
@@ -235,13 +235,13 @@ public class ConfigTest {
 	@Test
 	public void getString2() throws Exception {
 		Config c = init("a1=1", "a2=2", "[S]", "b1=1", "b2=");
-		assertEquals("1", c.getString("a1", "foo"));
-		assertEquals("2", c.getString("a2", "foo"));
-		assertEquals("foo", c.getString("a3", "foo"));
-		assertEquals("1", c.getString("S/b1", "foo"));
-		assertEquals("foo", c.getString("S/b2", "foo"));
-		assertEquals("foo", c.getString("S/b3", "foo"));
-		assertEquals("foo", c.getString("T/c1", "foo"));
+		assertEquals("1", c.get("a1").orElse("foo"));
+		assertEquals("2", c.get("a2").orElse("foo"));
+		assertEquals("foo", c.get("a3").orElse("foo"));
+		assertEquals("1", c.get("S/b1").orElse("foo"));
+		assertEquals("", c.get("S/b2").orElse("foo"));
+		assertEquals("foo", c.get("S/b3").orElse("foo"));
+		assertEquals("foo", c.get("T/c1").orElse("foo"));
 	}
 
 	//====================================================================================================
@@ -250,13 +250,13 @@ public class ConfigTest {
 	@Test
 	public void getStringArray1() throws Exception {
 		Config c = init("a1=1,2", "a2= 2 , 3 ", "[S]", "b1=1", "b2=");
-		assertObject(c.getStringArray("a1")).asJson().is("['1','2']");
-		assertObject(c.getStringArray("a2")).asJson().is("['2','3']");
-		assertObject(c.getStringArray("a3")).asJson().is("[]");
-		assertObject(c.getStringArray("S/b1")).asJson().is("['1']");
-		assertObject(c.getStringArray("S/b2")).asJson().is("[]");
-		assertObject(c.getStringArray("S/b3")).asJson().is("[]");
-		assertObject(c.getStringArray("T/c1")).asJson().is("[]");
+		assertObject(c.get("a1").as(String[].class).orElse(null)).asJson().is("['1','2']");
+		assertObject(c.get("a2").as(String[].class).orElse(null)).asJson().is("['2','3']");
+		assertObject(c.get("a3").as(String[].class).orElse(null)).isNull();
+		assertObject(c.get("S/b1").as(String[].class).orElse(null)).asJson().is("['1']");
+		assertObject(c.get("S/b2").as(String[].class).orElse(null)).asJson().is("[]");
+		assertObject(c.get("S/b3").as(String[].class).orElse(null)).isNull();
+		assertObject(c.get("T/c1").as(String[].class).orElse(null)).isNull();
 	}
 
 	//====================================================================================================
@@ -265,13 +265,13 @@ public class ConfigTest {
 	@Test
 	public void getStringArray2() throws Exception {
 		Config c = init("a1=1,2", "a2= 2 , 3 ", "[S]", "b1=1", "b2=");
-		assertObject(c.getStringArray("a1", new String[] {"foo"})).asJson().is("['1','2']");
-		assertObject(c.getStringArray("a2", new String[] {"foo"})).asJson().is("['2','3']");
-		assertObject(c.getStringArray("a3", new String[] {"foo"})).asJson().is("['foo']");
-		assertObject(c.getStringArray("S/b1", new String[] {"foo"})).asJson().is("['1']");
-		assertObject(c.getStringArray("S/b2", new String[] {"foo"})).asJson().is("['foo']");
-		assertObject(c.getStringArray("S/b3", new String[] {"foo"})).asJson().is("['foo']");
-		assertObject(c.getStringArray("T/c1", new String[] {"foo"})).asJson().is("['foo']");
+		assertObject(c.get("a1").asStringArray().orElse(new String[] {"foo"})).asJson().is("['1','2']");
+		assertObject(c.get("a2").asStringArray().orElse(new String[] {"foo"})).asJson().is("['2','3']");
+		assertObject(c.get("a3").asStringArray().orElse(new String[] {"foo"})).asJson().is("['foo']");
+		assertObject(c.get("S/b1").asStringArray().orElse(new String[] {"foo"})).asJson().is("['1']");
+		assertObject(c.get("S/b2").asStringArray().orElse(new String[] {"foo"})).asJson().is("[]");
+		assertObject(c.get("S/b3").asStringArray().orElse(new String[] {"foo"})).asJson().is("['foo']");
+		assertObject(c.get("T/c1").asStringArray().orElse(new String[] {"foo"})).asJson().is("['foo']");
 	}
 
 	//====================================================================================================
@@ -280,22 +280,22 @@ public class ConfigTest {
 	@Test
 	public void getInt1() throws Exception {
 		Config c = init("a1=1", "a2=2", "[S]", "b1=1", "b2=");
-		assertEquals(1, c.getInt("a1"));
-		assertEquals(2, c.getInt("a2"));
-		assertEquals(0, c.getInt("a3"));
-		assertEquals(1, c.getInt("S/b1"));
-		assertEquals(0, c.getInt("S/b2"));
-		assertEquals(0, c.getInt("S/b3"));
-		assertEquals(0, c.getInt("T/c1"));
+		assertInteger(c.get("a1").asInteger().orElse(0)).is(1);
+		assertInteger(c.get("a2").asInteger().orElse(0)).is(2);
+		assertInteger(c.get("a3").asInteger().orElse(0)).is(0);
+		assertInteger(c.get("S/b1").asInteger().orElse(0)).is(1);
+		assertInteger(c.get("S/b2").asInteger().orElse(0)).is(0);
+		assertInteger(c.get("S/b3").asInteger().orElse(0)).is(0);
+		assertInteger(c.get("T/c1").asInteger().orElse(0)).is(0);
 	}
 
 	@Test
 	public void getInt1BadValues() throws Exception {
 		Config c = init("a1=foo", "a2=2.3", "a3=[1]", "a4=false");
-		assertThrown(()->c.getInt("a1")).exists();
-		assertThrown(()->c.getInt("a2")).exists();
-		assertThrown(()->c.getInt("a3")).exists();
-		assertThrown(()->c.getInt("a4")).exists();
+		assertThrown(()->c.get("a1").asInteger().orElse(0)).exists();
+		assertThrown(()->c.get("a2").asInteger().orElse(0)).exists();
+		assertThrown(()->c.get("a3").asInteger().orElse(0)).exists();
+		assertThrown(()->c.get("a4").asInteger().orElse(0)).exists();
 	}
 
 	//====================================================================================================
@@ -304,22 +304,22 @@ public class ConfigTest {
 	@Test
 	public void getInt2() throws Exception {
 		Config c = init("a1=1", "a2=2", "[S]", "b1=1", "b2=");
-		assertEquals(1, c.getInt("a1", -1));
-		assertEquals(2, c.getInt("a2", -1));
-		assertEquals(-1, c.getInt("a3", -1));
-		assertEquals(1, c.getInt("S/b1", -1));
-		assertEquals(-1, c.getInt("S/b2", -1));
-		assertEquals(-1, c.getInt("S/b3", -1));
-		assertEquals(-1, c.getInt("T/c1", -1));
+		assertInteger(c.get("a1").asInteger().orElse(-1)).is(1);
+		assertInteger(c.get("a2").asInteger().orElse(-1)).is(2);
+		assertInteger(c.get("a3").asInteger().orElse(-1)).is(-1);
+		assertInteger(c.get("S/b1").asInteger().orElse(-1)).is(1);
+		assertInteger(c.get("S/b2").asInteger().orElse(-1)).is(-1);
+		assertInteger(c.get("S/b3").asInteger().orElse(-1)).is(-1);
+		assertInteger(c.get("T/c1").asInteger().orElse(-1)).is(-1);
 	}
 
 	@Test
 	public void getInt2BadValues() throws Exception {
 		Config c = init("a1=foo", "a2=2.3", "a3=[1]", "a4=false");
-		assertThrown(()->c.getInt("a1", -1)).exists();
-		assertThrown(()->c.getInt("a2", -1)).exists();
-		assertThrown(()->c.getInt("a3", -1)).exists();
-		assertThrown(()->c.getInt("a4", -1)).exists();
+		assertThrown(()->c.get("a1").asInteger().orElse(-1)).exists();
+		assertThrown(()->c.get("a2").asInteger().orElse(-1)).exists();
+		assertThrown(()->c.get("a3").asInteger().orElse(-1)).exists();
+		assertThrown(()->c.get("a4").asInteger().orElse(-1)).exists();
 	}
 
 	//====================================================================================================
@@ -328,22 +328,22 @@ public class ConfigTest {
 	@Test
 	public void getBoolean1() throws Exception {
 		Config c = init("a1=true", "a2=false", "[S]", "b1=TRUE", "b2=");
-		assertEquals(true, c.getBoolean("a1"));
-		assertEquals(false, c.getBoolean("a2"));
-		assertEquals(false, c.getBoolean("a3"));
-		assertEquals(true, c.getBoolean("S/b1"));
-		assertEquals(false, c.getBoolean("S/b2"));
-		assertEquals(false, c.getBoolean("S/b3"));
-		assertEquals(false, c.getBoolean("T/c1"));
+		assertEquals(true, c.get("a1").asBoolean().orElse(false));
+		assertEquals(false, c.get("a2").asBoolean().orElse(false));
+		assertEquals(false, c.get("a3").asBoolean().orElse(false));
+		assertEquals(true, c.get("S/b1").asBoolean().orElse(false));
+		assertEquals(false, c.get("S/b2").asBoolean().orElse(false));
+		assertEquals(false, c.get("S/b3").asBoolean().orElse(false));
+		assertEquals(false, c.get("T/c1").asBoolean().orElse(false));
 	}
 
 	@Test
 	public void getBoolean1BadValues() throws Exception {
 		Config c = init("a1=foo", "a2=2.3", "a3=[1]", "a4=T");
-		assertEquals(false, c.getBoolean("a1"));
-		assertEquals(false, c.getBoolean("a2"));
-		assertEquals(false, c.getBoolean("a3"));
-		assertEquals(false, c.getBoolean("a4"));
+		assertEquals(false, c.get("a1").asBoolean().orElse(false));
+		assertEquals(false, c.get("a2").asBoolean().orElse(false));
+		assertEquals(false, c.get("a3").asBoolean().orElse(false));
+		assertEquals(false, c.get("a4").asBoolean().orElse(false));
 	}
 
 	//====================================================================================================
@@ -352,22 +352,22 @@ public class ConfigTest {
 	@Test
 	public void getBoolean2() throws Exception {
 		Config c = init("a1=true", "a2=false", "[S]", "b1=TRUE", "b2=");
-		assertEquals(true, c.getBoolean("a1", true));
-		assertEquals(false, c.getBoolean("a2", true));
-		assertEquals(true, c.getBoolean("a3", true));
-		assertEquals(true, c.getBoolean("S/b1", true));
-		assertEquals(true, c.getBoolean("S/b2", true));
-		assertEquals(true, c.getBoolean("S/b3", true));
-		assertEquals(true, c.getBoolean("T/c1", true));
+		assertEquals(true, c.get("a1").asBoolean().orElse(true));
+		assertEquals(false, c.get("a2").asBoolean().orElse(true));
+		assertEquals(true, c.get("a3").asBoolean().orElse(true));
+		assertEquals(true, c.get("S/b1").asBoolean().orElse(true));
+		assertEquals(true, c.get("S/b2").asBoolean().orElse(true));
+		assertEquals(true, c.get("S/b3").asBoolean().orElse(true));
+		assertEquals(true, c.get("T/c1").asBoolean().orElse(true));
 	}
 
 	@Test
 	public void getBoolean2BadValues() throws Exception {
 		Config c = init("a1=foo", "a2=2.3", "a3=[1]", "a4=T");
-		assertEquals(false, c.getBoolean("a1", true));
-		assertEquals(false, c.getBoolean("a2", true));
-		assertEquals(false, c.getBoolean("a3", true));
-		assertEquals(false, c.getBoolean("a4", true));
+		assertEquals(false, c.get("a1").asBoolean().orElse(true));
+		assertEquals(false, c.get("a2").asBoolean().orElse(true));
+		assertEquals(false, c.get("a3").asBoolean().orElse(true));
+		assertEquals(false, c.get("a4").asBoolean().orElse(true));
 	}
 
 	//====================================================================================================
@@ -376,22 +376,22 @@ public class ConfigTest {
 	@Test
 	public void getLong1() throws Exception {
 		Config c = init("a1=1", "a2=2", "[S]", "b1=1", "b2=");
-		assertEquals(1l, c.getLong("a1"));
-		assertEquals(2l, c.getLong("a2"));
-		assertEquals(0l, c.getLong("a3"));
-		assertEquals(1l, c.getLong("S/b1"));
-		assertEquals(0l, c.getLong("S/b2"));
-		assertEquals(0l, c.getLong("S/b3"));
-		assertEquals(0l, c.getLong("T/c1"));
+		assertLong(c.get("a1").asLong().orElse(0l)).is(1l);
+		assertLong(c.get("a2").asLong().orElse(0l)).is(2l);
+		assertLong(c.get("a3").asLong().orElse(0l)).is(0l);
+		assertLong(c.get("S/b1").asLong().orElse(0l)).is(1l);
+		assertLong(c.get("S/b2").asLong().orElse(0l)).is(0l);
+		assertLong(c.get("S/b3").asLong().orElse(0l)).is(0l);
+		assertLong(c.get("T/c1").asLong().orElse(0l)).is(0l);
 	}
 
 	@Test
 	public void getLong1BadValues() throws Exception {
 		Config c = init("a1=foo", "a2=2.3", "a3=[1]", "a4=false");
-		assertThrown(()->c.getLong("a1")).exists();
-		assertThrown(()->c.getLong("a2")).exists();
-		assertThrown(()->c.getLong("a3")).exists();
-		assertThrown(()->c.getLong("a4")).exists();
+		assertThrown(()->c.get("a1").as(long.class)).exists();
+		assertThrown(()->c.get("a2").as(long.class)).exists();
+		assertThrown(()->c.get("a3").as(long.class)).exists();
+		assertThrown(()->c.get("a4").as(long.class)).exists();
 	}
 
 	//====================================================================================================
@@ -400,23 +400,23 @@ public class ConfigTest {
 	@Test
 	public void getLong2() throws Exception {
 		Config c = init("a1=1", "a2=2", "[S]", "b1=1", "b2=");
-		assertEquals(1l, c.getLong("a1", Long.MAX_VALUE));
-		assertEquals(2l, c.getLong("a2", Long.MAX_VALUE));
-		assertEquals(Long.MAX_VALUE, c.getLong("a3", Long.MAX_VALUE));
-		assertEquals(1l, c.getLong("S/b1", Long.MAX_VALUE));
-		assertEquals(Long.MAX_VALUE, c.getLong("S/b2", Long.MAX_VALUE));
-		assertEquals(Long.MAX_VALUE, c.getLong("S/b3", Long.MAX_VALUE));
-		assertEquals(Long.MAX_VALUE, c.getLong("T/c1", Long.MAX_VALUE));
+		assertLong(c.get("a1").asLong().orElse(Long.MAX_VALUE)).is(1l);
+		assertLong(c.get("a2").asLong().orElse(Long.MAX_VALUE)).is(2l);
+		assertLong(c.get("a3").asLong().orElse(Long.MAX_VALUE)).is(Long.MAX_VALUE);
+		assertLong(c.get("S/b1").asLong().orElse(Long.MAX_VALUE)).is(1l);
+		assertLong(c.get("S/b2").asLong().orElse(Long.MAX_VALUE)).is(Long.MAX_VALUE);
+		assertLong(c.get("S/b3").asLong().orElse(Long.MAX_VALUE)).is(Long.MAX_VALUE);
+		assertLong(c.get("T/c1").asLong().orElse(Long.MAX_VALUE)).is(Long.MAX_VALUE);
 	}
 
 	@Test
 	public void getLong2BadValues() throws Exception {
 		Config c = init("a1=foo", "a2=2.3", "a3=[1]", "a4=false");
 
-		assertThrown(()->c.getLong("a1", -1l)).isType(NumberFormatException.class);
-		assertThrown(()->c.getLong("a2", -1l)).isType(NumberFormatException.class);
-		assertThrown(()->c.getLong("a3", -1l)).isType(NumberFormatException.class);
-		assertThrown(()->c.getLong("a4", -1l)).isType(NumberFormatException.class);
+		assertThrown(()->c.get("a1").asLong().orElse(-1l)).isType(NumberFormatException.class);
+		assertThrown(()->c.get("a2").asLong().orElse(-1l)).isType(NumberFormatException.class);
+		assertThrown(()->c.get("a3").asLong().orElse(-1l)).isType(NumberFormatException.class);
+		assertThrown(()->c.get("a4").asLong().orElse(-1l)).isType(NumberFormatException.class);
 	}
 
 	//====================================================================================================
@@ -426,10 +426,10 @@ public class ConfigTest {
 	public void getBytes1() throws Exception {
 		Config c = init("a1=Zm9v", "a2=Zm", "\t9v", "a3=");
 
-		assertObject(c.getBytes("a1")).asJson().is("[102,111,111]");
-		assertObject(c.getBytes("a2")).asJson().is("[102,111,111]");
-		assertObject(c.getBytes("a3")).asJson().is("[]");
-		assertNull(null, c.getBytes("a4"));
+		assertObject(c.get("a1").as(byte[].class)).asJson().is("[102,111,111]");
+		assertObject(c.get("a2").as(byte[].class)).asJson().is("[102,111,111]");
+		assertObject(c.get("a3").as(byte[].class)).asJson().is("[]");
+		assertNull(null, c.get("a4").to(byte[].class));
 	}
 
 	//====================================================================================================
@@ -439,10 +439,10 @@ public class ConfigTest {
 	public void getBytes2() throws Exception {
 		Config c = init("a1=Zm9v", "a2=Zm", "\t9v", "a3=");
 
-		assertObject(c.getBytes("a1", new byte[] {1})).asJson().is("[102,111,111]");
-		assertObject(c.getBytes("a2", new byte[] {1})).asJson().is("[102,111,111]");
-		assertObject(c.getBytes("a3", new byte[] {1})).asJson().is("[1]");
-		assertObject(c.getBytes("a4", new byte[] {1})).asJson().is("[1]");
+		assertObject(c.get("a1").asBytes().orElse(new byte[] {1})).asJson().is("[102,111,111]");
+		assertObject(c.get("a2").asBytes().orElse(new byte[] {1})).asJson().is("[102,111,111]");
+		assertObject(c.get("a3").asBytes().orElse(new byte[] {1})).asJson().is("[]");
+		assertObject(c.get("a4").asBytes().orElse(new byte[] {1})).asJson().is("[1]");
 	}
 
 	//====================================================================================================
@@ -459,29 +459,29 @@ public class ConfigTest {
 			"\t}"
 			);
 
-		Map<String,Integer> a1 = c.getObject("a1", Map.class, String.class, Integer.class);
+		Map<String,Integer> a1 = c.get("a1").to(Map.class, String.class, Integer.class);
 		assertObject(a1).asJson().is("{foo:123}");
 		assertObject(a1.keySet().iterator().next()).isType(String.class);
 		assertObject(a1.values().iterator().next()).isType(Integer.class);
 
-		List<Map<String,Integer>> a2a = c.getObject("a2", List.class, Map.class, String.class, Integer.class);
+		List<Map<String,Integer>> a2a = c.get("a2").to(List.class, Map.class, String.class, Integer.class);
 		assertObject(a2a).asJson().is("[{foo:123}]");
 		assertObject(a2a.get(0).keySet().iterator().next()).isType(String.class);
 		assertObject(a2a.get(0).values().iterator().next()).isType(Integer.class);
 
-		List<ABean> a2b = c.getObject("a2", List.class, ABean.class);
+		List<ABean> a2b = c.get("a2").to(List.class, ABean.class);
 		assertObject(a2b).asJson().is("[{foo:'123'}]");
 		assertObject(a2b.get(0)).isType(ABean.class);
 
-		Map<String,Integer> a3 = c.getObject("a3", Map.class, String.class, Integer.class);
+		Map<String,Integer> a3 = c.get("a3").to(Map.class, String.class, Integer.class);
 		assertNull(a3);
 
-		Map<String,Integer> a4a = c.getObject("a4", Map.class, String.class, Integer.class);
+		Map<String,Integer> a4a = c.get("a4").to(Map.class, String.class, Integer.class);
 		assertObject(a4a).asJson().is("{foo:123}");
 		assertObject(a4a.keySet().iterator().next()).isType(String.class);
 		assertObject(a4a.values().iterator().next()).isType(Integer.class);
 
-		ABean a4b = c.getObject("a4", ABean.class);
+		ABean a4b = c.get("a4").as(ABean.class).get();
 		assertObject(a4b).asJson().is("{foo:'123'}");
 		assertObject(a4b).isType(ABean.class);
 	}
@@ -500,29 +500,29 @@ public class ConfigTest {
 			"\t)"
 			);
 
-		Map<String,Integer> a1 = c.getObject("a1", UonParser.DEFAULT, Map.class, String.class, Integer.class);
+		Map<String,Integer> a1 = c.get("a1").to(UonParser.DEFAULT, Map.class, String.class, Integer.class);
 		assertObject(a1).asJson().is("{foo:123}");
 		assertObject(a1.keySet().iterator().next()).isType(String.class);
 		assertObject(a1.values().iterator().next()).isType(Integer.class);
 
-		List<Map<String,Integer>> a2a = c.getObject("a2", UonParser.DEFAULT, List.class, Map.class, String.class, Integer.class);
+		List<Map<String,Integer>> a2a = c.get("a2").to(UonParser.DEFAULT, List.class, Map.class, String.class, Integer.class);
 		assertObject(a2a).asJson().is("[{foo:123}]");
 		assertObject(a2a.get(0).keySet().iterator().next()).isType(String.class);
 		assertObject(a2a.get(0).values().iterator().next()).isType(Integer.class);
 
-		List<ABean> a2b = c.getObject("a2", UonParser.DEFAULT, List.class, ABean.class);
+		List<ABean> a2b = c.get("a2").to(UonParser.DEFAULT, List.class, ABean.class);
 		assertObject(a2b).asJson().is("[{foo:'123'}]");
 		assertObject(a2b.get(0)).isType(ABean.class);
 
-		Map<String,Integer> a3 = c.getObject("a3", UonParser.DEFAULT, Map.class, String.class, Integer.class);
+		Map<String,Integer> a3 = c.get("a3").to(UonParser.DEFAULT, Map.class, String.class, Integer.class);
 		assertNull(a3);
 
-		Map<String,Integer> a4a = c.getObject("a4", UonParser.DEFAULT, Map.class, String.class, Integer.class);
+		Map<String,Integer> a4a = c.get("a4").to(UonParser.DEFAULT, Map.class, String.class, Integer.class);
 		assertObject(a4a).asJson().is("{foo:123}");
 		assertObject(a4a.keySet().iterator().next()).isType(String.class);
 		assertObject(a4a.values().iterator().next()).isType(Integer.class);
 
-		ABean a4b = c.getObject("a4", UonParser.DEFAULT, ABean.class);
+		ABean a4b = c.get("a4").as(UonParser.DEFAULT, ABean.class).get();
 		assertObject(a4b).asJson().is("{foo:'123'}");
 		assertObject(a4b).isType(ABean.class);
 	}
@@ -542,25 +542,25 @@ public class ConfigTest {
 			"\t}"
 			);
 
-		Map a1 = c.getObject("a1", Map.class);
+		Map a1 = c.get("a1").as(Map.class).get();
 		assertObject(a1).asJson().is("{foo:123}");
 		assertObject(a1.keySet().iterator().next()).isType(String.class);
 		assertObject(a1.values().iterator().next()).isType(Integer.class);
 
-		List a2a = c.getObject("a2", List.class);
+		List a2a = c.get("a2").as(List.class).get();
 		assertObject(a2a).asJson().is("[{foo:123}]");
 		assertObject(((Map)a2a.get(0)).keySet().iterator().next()).isType(String.class);
 		assertObject(((Map)a2a.get(0)).values().iterator().next()).isType(Integer.class);
 
-		Map a3 = c.getObject("a3", Map.class);
+		Map a3 = c.get("a3").as(Map.class).orElse(null);
 		assertNull(a3);
 
-		Map a4a = c.getObject("a4", Map.class);
+		Map a4a = c.get("a4").as(Map.class).get();
 		assertObject(a4a).asJson().is("{foo:123}");
 		assertObject(a4a.keySet().iterator().next()).isType(String.class);
 		assertObject(a4a.values().iterator().next()).isType(Integer.class);
 
-		ABean a4b = c.getObject("a4", ABean.class);
+		ABean a4b = c.get("a4").as(ABean.class).orElse(null);
 		assertObject(a4b).asJson().is("{foo:'123'}");
 		assertObject(a4b).isType(ABean.class);
 	}
@@ -580,25 +580,25 @@ public class ConfigTest {
 			"\t)"
 		);
 
-		Map a1 = c.getObject("a1", UonParser.DEFAULT, Map.class);
+		Map a1 = c.get("a1").as(UonParser.DEFAULT, Map.class).get();
 		assertObject(a1).asJson().is("{foo:123}");
 		assertObject(a1.keySet().iterator().next()).isType(String.class);
 		assertObject(a1.values().iterator().next()).isType(Integer.class);
 
-		List a2a = c.getObject("a2", UonParser.DEFAULT, List.class);
+		List a2a = c.get("a2").as(UonParser.DEFAULT, List.class).get();
 		assertObject(a2a).asJson().is("[{foo:123}]");
 		assertObject(((Map)a2a.get(0)).keySet().iterator().next()).isType(String.class);
 		assertObject(((Map)a2a.get(0)).values().iterator().next()).isType(Integer.class);
 
-		Map a3 = c.getObject("a3", UonParser.DEFAULT, Map.class);
+		Map a3 = c.get("a3").as(UonParser.DEFAULT, Map.class).orElse(null);
 		assertNull(a3);
 
-		Map a4a = c.getObject("a4", UonParser.DEFAULT, Map.class);
+		Map a4a = c.get("a4").as(UonParser.DEFAULT, Map.class).get();
 		assertObject(a4a).asJson().is("{foo:123}");
 		assertObject(a4a.keySet().iterator().next()).isType(String.class);
 		assertObject(a4a.values().iterator().next()).isType(Integer.class);
 
-		ABean a4b = c.getObject("a4", UonParser.DEFAULT, ABean.class);
+		ABean a4b = c.get("a4").as(UonParser.DEFAULT, ABean.class).get();
 		assertObject(a4b).asJson().is("{foo:'123'}");
 		assertObject(a4b).isType(ABean.class);
 	}
@@ -618,34 +618,34 @@ public class ConfigTest {
 			"\t}"
 		);
 
-		Map a1 = c.getObjectWithDefault("a1", new OMap(), Map.class);
+		Map a1 = c.get("a1").as(Map.class).orElseGet(OMap::new);
 		assertObject(a1).asJson().is("{foo:123}");
 		assertObject(a1.keySet().iterator().next()).isType(String.class);
 		assertObject(a1.values().iterator().next()).isType(Integer.class);
 
-		Map a1b = c.getObjectWithDefault("a1b", new OMap(), Map.class);
+		Map a1b = c.get("a1b").as(Map.class).orElseGet(OMap::new);
 		assertObject(a1b).asJson().is("{}");
 
-		List a2a = c.getObjectWithDefault("a2", new OList(), List.class);
+		List a2a = c.get("a2").as(List.class).orElseGet(OList::new);
 		assertObject(a2a).asJson().is("[{foo:123}]");
 		assertObject(((Map)a2a.get(0)).keySet().iterator().next()).isType(String.class);
 		assertObject(((Map)a2a.get(0)).values().iterator().next()).isType(Integer.class);
 
-		List a2b = c.getObjectWithDefault("a2b", new OList(), List.class);
+		List a2b = c.get("a2b").as(List.class).orElseGet(OList::new);
 		assertObject(a2b).asJson().is("[]");
 
-		Map a3 = c.getObjectWithDefault("a3", new OMap(), Map.class);
+		Map a3 = c.get("a3").as(Map.class).orElseGet(OMap::new);
 		assertObject(a3).asJson().is("{}");
 
-		Map a4a = c.getObjectWithDefault("a4", new OMap(), Map.class);
+		Map a4a = c.get("a4").as(Map.class).orElseGet(OMap::new);
 		assertObject(a4a).asJson().is("{foo:123}");
 		assertObject(a4a.keySet().iterator().next()).isType(String.class);
 		assertObject(a4a.values().iterator().next()).isType(Integer.class);
 
-		Map a4b = c.getObjectWithDefault("a4b", new OMap(), Map.class);
+		Map a4b = c.get("a4b").as(Map.class).orElseGet(OMap::new);
 		assertObject(a4b).asJson().is("{}");
 
-		ABean a4c = c.getObjectWithDefault("a4c", new ABean().init(), ABean.class);
+		ABean a4c = c.get("a4c").as(ABean.class).orElse(new ABean().init());
 		assertObject(a4c).asJson().is("{foo:'bar'}");
 		assertObject(a4c).isType(ABean.class);
 	}
@@ -665,34 +665,34 @@ public class ConfigTest {
 			"\t)"
 		);
 
-		Map a1 = c.getObjectWithDefault("a1", UonParser.DEFAULT, new OMap(), Map.class);
+		Map a1 = c.get("a1").as(UonParser.DEFAULT, Map.class).orElseGet(OMap::new);
 		assertObject(a1).asJson().is("{foo:123}");
 		assertObject(a1.keySet().iterator().next()).isType(String.class);
 		assertObject(a1.values().iterator().next()).isType(Integer.class);
 
-		Map a1b = c.getObjectWithDefault("a1b", UonParser.DEFAULT, new OMap(), Map.class);
+		Map a1b = c.get("a1b").as(UonParser.DEFAULT, Map.class).orElseGet(OMap::new);
 		assertObject(a1b).asJson().is("{}");
 
-		List a2a = c.getObjectWithDefault("a2", UonParser.DEFAULT, new OList(), List.class);
+		List a2a = c.get("a2").as(UonParser.DEFAULT, List.class).orElseGet(OList::new);
 		assertObject(a2a).asJson().is("[{foo:123}]");
 		assertObject(((Map)a2a.get(0)).keySet().iterator().next()).isType(String.class);
 		assertObject(((Map)a2a.get(0)).values().iterator().next()).isType(Integer.class);
 
-		List a2b = c.getObjectWithDefault("a2b", UonParser.DEFAULT, new OList(), List.class);
+		List a2b = c.get("a2b").as(UonParser.DEFAULT, List.class).orElseGet(OList::new);
 		assertObject(a2b).asJson().is("[]");
 
-		Map a3 = c.getObjectWithDefault("a3", UonParser.DEFAULT, new OMap(), Map.class);
+		Map a3 = c.get("a3").as(UonParser.DEFAULT, Map.class).orElseGet(OMap::new);
 		assertObject(a3).asJson().is("{}");
 
-		Map a4a = c.getObjectWithDefault("a4", UonParser.DEFAULT, new OMap(), Map.class);
+		Map a4a = c.get("a4").as(UonParser.DEFAULT, Map.class).orElseGet(OMap::new);
 		assertObject(a4a).asJson().is("{foo:123}");
 		assertObject(a4a.keySet().iterator().next()).isType(String.class);
 		assertObject(a4a.values().iterator().next()).isType(Integer.class);
 
-		Map a4b = c.getObjectWithDefault("a4b", UonParser.DEFAULT, new OMap(), Map.class);
+		Map a4b = c.get("a4b").as(UonParser.DEFAULT, Map.class).orElseGet(OMap::new);
 		assertObject(a4b).asJson().is("{}");
 
-		ABean a4c = c.getObjectWithDefault("a4c", UonParser.DEFAULT, new ABean().init(), ABean.class);
+		ABean a4c = c.get("a4c").as(UonParser.DEFAULT, ABean.class).orElse(new ABean().init());
 		assertObject(a4c).asJson().is("{foo:'bar'}");
 		assertObject(a4c).isType(ABean.class);
 	}
@@ -700,6 +700,7 @@ public class ConfigTest {
 	//====================================================================================================
 	//	public <T> T getObjectWithDefault(String key, T def, Type type, Type...args) throws ParseException {
 	//====================================================================================================
+	@SuppressWarnings("unchecked")
 	@Test
 	public void getObjectWithDefault3() throws Exception {
 		Config c = init(
@@ -711,34 +712,34 @@ public class ConfigTest {
 			"\t}"
 		);
 
-		Map<String,Integer> a1 = c.getObjectWithDefault("a1", new HashMap<String,Integer>(), Map.class, String.class, Integer.class);
+		Map<String,Integer> a1 = (Map<String,Integer>) c.get("a1").as(Map.class, String.class, Integer.class).orElse(new HashMap<String,Integer>());
 		assertObject(a1).asJson().is("{foo:123}");
 		assertObject(a1.keySet().iterator().next()).isType(String.class);
 		assertObject(a1.values().iterator().next()).isType(Integer.class);
 
-		Map<String,Integer> a1b = c.getObjectWithDefault("a1b", new HashMap<String,Integer>(), Map.class, String.class, Integer.class);
+		Map<String,Integer> a1b = (Map<String,Integer>) c.get("a1b").as(Map.class, String.class, Integer.class).orElse(new HashMap<String,Integer>());
 		assertObject(a1b).asJson().is("{}");
 
-		List<Map<String,Integer>> a2a = c.getObjectWithDefault("a2", new ArrayList<Map<String,Integer>>(), List.class, Map.class, String.class, Integer.class);
+		List<Map<String,Integer>> a2a = (List<Map<String,Integer>>) c.get("a2").as(List.class, Map.class, String.class, Integer.class).orElse(new ArrayList<Map<String,Integer>>());
 		assertObject(a2a).asJson().is("[{foo:123}]");
 		assertObject(a2a.get(0).keySet().iterator().next()).isType(String.class);
 		assertObject(a2a.get(0).values().iterator().next()).isType(Integer.class);
 
-		List<ABean> a2b = c.getObjectWithDefault("a2b", new ArrayList<ABean>(), List.class, ABean.class);
+		List<ABean> a2b = (List<ABean>) c.get("a2b").as(List.class, ABean.class).orElse(new ArrayList<ABean>());
 		assertObject(a2b).asJson().is("[]");
 
-		Map<String,Object> a3 = c.getObjectWithDefault("a3", new OMap(), Map.class, String.class, Object.class);
+		Map<String,Object> a3 = (Map<String,Object>) c.get("a3").as(Map.class, String.class, Object.class).orElse(new OMap());
 		assertObject(a3).asJson().is("{}");
 
-		Map<String,Integer> a4a = c.getObjectWithDefault("a4", new HashMap<String,Integer>(), Map.class, String.class, Integer.class);
+		Map<String,Integer> a4a = (Map<String,Integer>) c.get("a4").as(Map.class, String.class, Integer.class).orElse(new HashMap<String,Integer>());
 		assertObject(a4a).asJson().is("{foo:123}");
 		assertObject(a4a.keySet().iterator().next()).isType(String.class);
 		assertObject(a4a.values().iterator().next()).isType(Integer.class);
 
-		Map<String,Integer> a4b = c.getObjectWithDefault("a4b", new HashMap<String,Integer>(), Map.class, String.class, Integer.class);
+		Map<String,Integer> a4b = (Map<String,Integer>) c.get("a4b").as(Map.class, String.class, Integer.class).orElse(new HashMap<String,Integer>());
 		assertObject(a4b).asJson().is("{}");
 
-		ABean a4c = c.getObjectWithDefault("a4c", new ABean().init(), ABean.class);
+		ABean a4c = c.get("a4c").as(ABean.class).orElse(new ABean().init());
 		assertObject(a4c).asJson().is("{foo:'bar'}");
 		assertObject(a4c).isType(ABean.class);
 	}
@@ -746,6 +747,7 @@ public class ConfigTest {
 	//====================================================================================================
 	//	public <T> T getObjectWithDefault(String key, Parser parser, T def, Type type, Type...args) throws ParseException {
 	//====================================================================================================
+	@SuppressWarnings("unchecked")
 	@Test
 	public void getObjectWithDefault4() throws Exception {
 		Config c = init(
@@ -757,34 +759,34 @@ public class ConfigTest {
 			"\t)"
 		);
 
-		Map<String,Integer> a1 = c.getObjectWithDefault("a1", UonParser.DEFAULT, new HashMap<String,Integer>(), Map.class, String.class, Integer.class);
+		Map<String,Integer> a1 = (Map<String,Integer>) c.get("a1").as(UonParser.DEFAULT, Map.class, String.class, Integer.class).orElse(new HashMap<String,Integer>());
 		assertObject(a1).asJson().is("{foo:123}");
 		assertObject(a1.keySet().iterator().next()).isType(String.class);
 		assertObject(a1.values().iterator().next()).isType(Integer.class);
 
-		Map<String,Integer> a1b = c.getObjectWithDefault("a1b", UonParser.DEFAULT, new HashMap<String,Integer>(), Map.class, String.class, Integer.class);
+		Map<String,Integer> a1b = (Map<String,Integer>) c.get("a1b").as(UonParser.DEFAULT, Map.class, String.class, Integer.class).orElse(new HashMap<String,Integer>());
 		assertObject(a1b).asJson().is("{}");
 
-		List<Map<String,Integer>> a2a = c.getObjectWithDefault("a2", UonParser.DEFAULT, new ArrayList<Map<String,Integer>>(), List.class, Map.class, String.class, Integer.class);
+		List<Map<String,Integer>> a2a = (List<Map<String,Integer>>) c.get("a2").as(UonParser.DEFAULT, List.class, Map.class, String.class, Integer.class).orElse(new ArrayList<Map<String,Integer>>());
 		assertObject(a2a).asJson().is("[{foo:123}]");
 		assertObject(a2a.get(0).keySet().iterator().next()).isType(String.class);
 		assertObject(a2a.get(0).values().iterator().next()).isType(Integer.class);
 
-		List<ABean> a2b = c.getObjectWithDefault("a2b", UonParser.DEFAULT, new ArrayList<ABean>(), List.class, ABean.class);
+		List<ABean> a2b = (List<ABean>) c.get("a2b").as(UonParser.DEFAULT, List.class, ABean.class).orElse(new ArrayList<ABean>());
 		assertObject(a2b).asJson().is("[]");
 
-		Map<String,Object> a3 = c.getObjectWithDefault("a3", UonParser.DEFAULT, new OMap(), Map.class, String.class, Object.class);
+		Map<String,Object> a3 = (Map<String,Object>) c.get("a3").as(UonParser.DEFAULT,Map.class, String.class, Object.class).orElse( new OMap());
 		assertObject(a3).asJson().is("{}");
 
-		Map<String,Integer> a4a = c.getObjectWithDefault("a4", UonParser.DEFAULT, new HashMap<String,Integer>(), Map.class, String.class, Integer.class);
+		Map<String,Integer> a4a = (Map<String,Integer>) c.get("a4").as(UonParser.DEFAULT, Map.class, String.class, Integer.class).orElse(new HashMap<String,Integer>());
 		assertObject(a4a).asJson().is("{foo:123}");
 		assertObject(a4a.keySet().iterator().next()).isType(String.class);
 		assertObject(a4a.values().iterator().next()).isType(Integer.class);
 
-		Map<String,Integer> a4b = c.getObjectWithDefault("a4b", UonParser.DEFAULT, new HashMap<String,Integer>(), Map.class, String.class, Integer.class);
+		Map<String,Integer> a4b = (Map<String,Integer>) c.get("a4b").as(UonParser.DEFAULT, Map.class, String.class, Integer.class).orElse(new HashMap<String,Integer>());
 		assertObject(a4b).asJson().is("{}");
 
-		ABean a4c = c.getObjectWithDefault("a4c", UonParser.DEFAULT, new ABean().init(), ABean.class);
+		ABean a4c = c.get("a4c").as(UonParser.DEFAULT, ABean.class).orElse(new ABean().init());
 		assertObject(a4c).asJson().is("{foo:'bar'}");
 		assertObject(a4c).isType(ABean.class);
 	}
@@ -1024,17 +1026,17 @@ public class ConfigTest {
 			"[section1]", "key1 = 2", "key2 = false", "key3 = [4,5,6]", "key4 = http://bar"
 		);
 
-		assertEquals(1, cf.getInt("key1"));
-		assertEquals(true, cf.getBoolean("key2"));
-		assertEquals(3, cf.getObject("key3", int[].class)[2]);
-		assertEquals(6, cf.getObjectWithDefault("xkey3", new int[]{4,5,6}, int[].class)[2]);
-		assertEquals(6, cf.getObjectWithDefault("X/key3", new int[]{4,5,6}, int[].class)[2]);
-		assertEquals(new URL("http://foo").toString(), cf.getObject("key4", URL.class).toString());
+		assertInteger(cf.get("key1").toInteger()).is(1);
+		assertBoolean(cf.get("key2").toBoolean()).isTrue();
+		assertInteger(cf.get("key3").to(int[].class)[2]).is(3);
+		assertInteger(cf.get("xkey3").as(int[].class).orElse(new int[]{4,5,6})[2]).is(6);
+		assertInteger(cf.get("X/key3").as(int[].class).orElse(new int[]{4,5,6})[2]).is(6);
+		assertEquals(new URL("http://foo").toString(), cf.get("key4").to(URL.class).toString());
 
-		assertEquals(2, cf.getInt("section1/key1"));
-		assertEquals(false, cf.getBoolean("section1/key2"));
-		assertEquals(6, cf.getObject("section1/key3", int[].class)[2]);
-		assertEquals(new URL("http://bar").toString(), cf.getObject("section1/key4", URL.class).toString());
+		assertInteger(cf.get("section1/key1").toInteger()).is(2);
+		assertBoolean(cf.get("section1/key2").toBoolean()).isFalse();
+		assertInteger(cf.get("section1/key3").to(int[].class)[2]).is(6);
+		assertEquals(new URL("http://bar").toString(), cf.get("section1/key4").to(URL.class).toString());
 
 		cf = init(
 			"# Default section",
@@ -1052,15 +1054,15 @@ public class ConfigTest {
 
 		cf.commit();
 
-		assertEquals(1, cf.getInt("key1"));
-		assertEquals(true, cf.getBoolean("key2"));
-		assertEquals(3, cf.getObject("key3", int[].class)[2]);
-		assertEquals(new URL("http://foo").toString(), cf.getObject("key4", URL.class).toString());
+		assertInteger(cf.get("key1").toInteger()).is(1);
+		assertBoolean(cf.get("key2").toBoolean()).isTrue();
+		assertInteger(cf.get("key3").to(int[].class)[2]).is(3);
+		assertEquals(new URL("http://foo").toString(), cf.get("key4").to(URL.class).toString());
 
-		assertEquals(2, cf.getInt("section1/key1"));
-		assertEquals(false, cf.getBoolean("section1/key2"));
-		assertEquals(6, cf.getObject("section1/key3", int[].class)[2]);
-		assertEquals(new URL("http://bar").toString(), cf.getObject("section1/key4", URL.class).toString());
+		assertInteger(cf.get("section1/key1").toInteger()).is(2);
+		assertBoolean(cf.get("section1/key2").toBoolean()).isFalse();
+		assertInteger(cf.get("section1/key3").to(int[].class)[2]).is(6);
+		assertEquals(new URL("http://bar").toString(), cf.get("section1/key4").to(URL.class).toString());
 	}
 
 	//====================================================================================================
@@ -1071,11 +1073,11 @@ public class ConfigTest {
 		Config cf = init(
 			"key1 = MINUTES"
 		);
-		assertEquals(TimeUnit.MINUTES, cf.getObject("key1", TimeUnit.class));
+		assertEquals(TimeUnit.MINUTES, cf.get("key1").to(TimeUnit.class));
 
 		cf.commit();
 
-		assertEquals(TimeUnit.MINUTES, cf.getObject("key1", TimeUnit.class));
+		assertEquals(TimeUnit.MINUTES, cf.get("key1").to(TimeUnit.class));
 	}
 
 	//====================================================================================================
@@ -1089,17 +1091,17 @@ public class ConfigTest {
 
 		cf.set("s1/foo", "mypassword");
 
-		assertEquals("mypassword", cf.getString("s1/foo"));
+		assertEquals("mypassword", cf.get("s1/foo").get());
 
 		cf.commit();
 
 		assertString(cf).replaceAll("\\r?\\n", "|").is("[s1]||foo* = {AwwJVhwUQFZEMg==}|");
 
-		assertEquals("mypassword", cf.getString("s1/foo"));
+		assertEquals("mypassword", cf.get("s1/foo").get());
 
 		cf.load(reader("[s1]\nfoo* = mypassword2\n"), true);
 
-		assertEquals("mypassword2", cf.getString("s1/foo"));
+		assertEquals("mypassword2", cf.get("s1/foo").get());
 
 		cf.set("s1/foo", "mypassword");
 
@@ -1141,27 +1143,27 @@ public class ConfigTest {
 		System.getProperties().remove("baz");
 		System.getProperties().remove("bing");
 
-		assertEquals("", cf.getString("s1/f1"));
-		assertEquals("bar", cf.getString("s1/f2"));
-		assertEquals("bar", cf.getString("s1/f3"));
+		assertEquals("", cf.get("s1/f1").get());
+		assertEquals("bar", cf.get("s1/f2").get());
+		assertEquals("bar", cf.get("s1/f3").get());
 
 		System.setProperty("foo", "123");
-		assertEquals("123", cf.getString("s1/f1"));
-		assertEquals("123", cf.getString("s1/f2"));
-		assertEquals("bar", cf.getString("s1/f3"));
+		assertEquals("123", cf.get("s1/f1").get());
+		assertEquals("123", cf.get("s1/f2").get());
+		assertEquals("bar", cf.get("s1/f3").get());
 
 		System.setProperty("foo", "$S{bar}");
 		System.setProperty("bar", "baz");
-		assertEquals("baz", cf.getString("s1/f1"));
-		assertEquals("baz", cf.getString("s1/f2"));
-		assertEquals("bar", cf.getString("s1/f3"));
+		assertEquals("baz", cf.get("s1/f1").get());
+		assertEquals("baz", cf.get("s1/f2").get());
+		assertEquals("bar", cf.get("s1/f3").get());
 
 		System.setProperty("bing", "$S{foo}");
-		assertEquals("baz", cf.getString("s1/f3"));
+		assertEquals("baz", cf.get("s1/f3").get());
 
 		System.setProperty("baz", "foo");
 		System.setProperty("foo", "123");
-		assertEquals("123", cf.getString("s1/f3"));
+		assertEquals("123", cf.get("s1/f3").get());
 	}
 
 	//====================================================================================================
@@ -1191,8 +1193,8 @@ public class ConfigTest {
 		Config cf = init().copy().binaryFormat(BinaryFormat.HEX).build();
 
 		cf.set("foo", "bar".getBytes("UTF-8"));
-		assertEquals("626172", cf.get("foo"));
-		assertObject(cf.getBytes("foo")).asJson().is("[98,97,114]");
+		assertEquals("626172", cf.get("foo").getValue());
+		assertObject(cf.get("foo").toBytes()).asJson().is("[98,97,114]");
 	}
 
 	//====================================================================================================
@@ -1203,8 +1205,8 @@ public class ConfigTest {
 		Config cf = init().copy().binaryFormat(BinaryFormat.SPACED_HEX).build();
 
 		cf.set("foo", "bar".getBytes("UTF-8"));
-		assertEquals("62 61 72", cf.get("foo"));
-		assertObject(cf.getBytes("foo")).asJson().is("[98,97,114]");
+		assertEquals("62 61 72", cf.get("foo").getValue());
+		assertObject(cf.get("foo").toBytes()).asJson().is("[98,97,114]");
 	}
 
 	//====================================================================================================
@@ -1217,7 +1219,7 @@ public class ConfigTest {
 			"f1 = x \n\ty \n\tz"
 		);
 
-		assertEquals("x \ny \nz", cf.getString("s1/f1"));
+		assertEquals("x \ny \nz", cf.get("s1/f1").get());
 
 		StringWriter sw = new StringWriter();
 		cf.writeTo(sw);
@@ -1236,10 +1238,10 @@ public class ConfigTest {
 			"f3 = 1 M",
 			"f4 = 1 K"
 		);
-		assertEquals(1048576, cf.getInt("s1/f1"));
-		assertEquals(1024, cf.getInt("s1/f2"));
-		assertEquals(1048576, cf.getInt("s1/f3"));
-		assertEquals(1024, cf.getInt("s1/f4"));
+		assertInteger(cf.get("s1/f1").toInteger()).is(1048576);
+		assertInteger(cf.get("s1/f2").toInteger()).is(1024);
+		assertInteger(cf.get("s1/f3").toInteger()).is(1048576);
+		assertInteger(cf.get("s1/f4").toInteger()).is(1024);
 	}
 
 	//====================================================================================================
@@ -1360,34 +1362,34 @@ public class ConfigTest {
 	@Test
 	public void testGetObjectArray() throws Exception {
 		Config cf = init("[A]", "a1=[1,2,3]");
-		assertObject(cf.getObject("A/a1", Integer[].class)).asJson().is("[1,2,3]");
-		assertObject(cf.getObjectWithDefault("A/a2", new Integer[]{4,5,6}, Integer[].class)).asJson().is("[4,5,6]");
-		assertObject(cf.getObjectWithDefault("B/a1", new Integer[]{7,8,9}, Integer[].class)).asJson().is("[7,8,9]");
-		assertNull(cf.getObject("B/a1", Integer[].class));
+		assertObject(cf.get("A/a1").to(Integer[].class)).asJson().is("[1,2,3]");
+		assertObject(cf.get("A/a2").as(Integer[].class).orElse(new Integer[]{4,5,6})).asJson().is("[4,5,6]");
+		assertObject(cf.get("B/a1").as(Integer[].class).orElse(new Integer[]{7,8,9})).asJson().is("[7,8,9]");
+		assertNull(cf.get("B/a1").to(Integer[].class));
 
 		cf = init("[A]", "a1 = [1 ,\n\t2 ,\n\t3] ");
-		assertObject(cf.getObject("A/a1", Integer[].class)).asJson().is("[1,2,3]");
+		assertObject(cf.get("A/a1").to(Integer[].class)).asJson().is("[1,2,3]");
 
 		// We cannot cast primitive arrays to Object[], so the following throws exceptions.
-		assertObject(cf.getObject("A/a1", int[].class)).asJson().is("[1,2,3]");
-		assertEquals("int", cf.getObject("A/a1", int[].class).getClass().getComponentType().getSimpleName());
-		assertNull(cf.getObject("B/a1", int[].class));
-		assertEquals("int", cf.getObjectWithDefault("B/a1", new int[0], int[].class).getClass().getComponentType().getSimpleName());
-		assertNull(cf.getObject("A/a2", int[].class));
-		assertEquals("int", cf.getObjectWithDefault("A/a2", new int[0], int[].class).getClass().getComponentType().getSimpleName());
-
-		assertObject(cf.getObjectWithDefault("A/a1", new int[]{4}, int[].class)).asJson().is("[1,2,3]");
-		assertEquals("int", cf.getObjectWithDefault("A/a1", new int[]{4}, int[].class).getClass().getComponentType().getSimpleName());
-		assertObject(cf.getObjectWithDefault("B/a1", new int[]{4}, int[].class)).asJson().is("[4]");
-		assertEquals("int", cf.getObjectWithDefault("B/a1", new int[]{4}, int[].class).getClass().getComponentType().getSimpleName());
-		assertObject(cf.getObjectWithDefault("A/a2", new int[]{4}, int[].class)).asJson().is("[4]");
-		assertEquals("int", cf.getObjectWithDefault("A/a2", new int[]{4}, int[].class).getClass().getComponentType().getSimpleName());
+		assertObject(cf.get("A/a1").to(int[].class)).asJson().is("[1,2,3]");
+		assertEquals("int", cf.get("A/a1").to(int[].class).getClass().getComponentType().getSimpleName());
+		assertNull(cf.get("B/a1").to(int[].class));
+		assertEquals("int", cf.get("B/a1").as(int[].class).orElse(new int[0]).getClass().getComponentType().getSimpleName());
+		assertNull(cf.get("A/a2").to(int[].class));
+		assertEquals("int", cf.get("A/a2").as(int[].class).orElse(new int[0]).getClass().getComponentType().getSimpleName());
+
+		assertObject(cf.get("A/a1").as(int[].class).orElse(new int[]{4})).asJson().is("[1,2,3]");
+		assertEquals("int", cf.get("A/a1").as(int[].class).orElse(new int[]{4}).getClass().getComponentType().getSimpleName());
+		assertObject(cf.get("B/a1").as(int[].class).orElse(new int[]{4})).asJson().is("[4]");
+		assertEquals("int", cf.get("B/a1").as(int[].class).orElse(new int[]{4}).getClass().getComponentType().getSimpleName());
+		assertObject(cf.get("A/a2").as(int[].class).orElse(new int[]{4})).asJson().is("[4]");
+		assertEquals("int", cf.get("A/a2").as(int[].class).orElse(new int[]{4}).getClass().getComponentType().getSimpleName());
 
 		System.setProperty("X", "[4,5,6]");
 		cf = init("x1=$C{A/a1}", "x2=$S{X}", "x3=$S{Y}", "[A]", "a1=[1,2,3]");
-		assertObject(cf.getObjectWithDefault("x1", new int[]{9}, int[].class)).asJson().is("[1,2,3]");
-		assertObject(cf.getObjectWithDefault("x2", new int[]{9}, int[].class)).asJson().is("[4,5,6]");
-		assertObject(cf.getObjectWithDefault("x3", new int[]{9}, int[].class)).asJson().is("[9]");
+		assertObject(cf.get("x1").as(int[].class).orElse(new int[]{9})).asJson().is("[1,2,3]");
+		assertObject(cf.get("x2").as(int[].class).orElse(new int[]{9})).asJson().is("[4,5,6]");
+		assertObject(cf.get("x3").as(int[].class).orElse(new int[]{9})).asJson().is("[]");
 		System.clearProperty("X");
 	}
 
@@ -1398,19 +1400,19 @@ public class ConfigTest {
 	@Test
 	public void testGetStringArray() throws Exception {
 		Config cf = init("[A]", "a1=1,2,3");
-		assertObject(cf.getStringArray("A/a1")).asJson().is("['1','2','3']");
-		assertObject(cf.getStringArray("A/a2", new String[]{"4","5","6"})).asJson().is("['4','5','6']");
-		assertObject(cf.getStringArray("B/a1", new String[]{"7","8","9"})).asJson().is("['7','8','9']");
-		assertObject(cf.getStringArray("B/a1")).asJson().is("[]");
+		assertObject(cf.get("A/a1").toStringArray()).asJson().is("['1','2','3']");
+		assertObject(cf.get("A/a2").asStringArray().orElse(new String[]{"4","5","6"})).asJson().is("['4','5','6']");
+		assertObject(cf.get("B/a1").asStringArray().orElse(new String[]{"7","8","9"})).asJson().is("['7','8','9']");
+		assertObject(cf.get("B/a1").toStringArray()).isNull();
 
 		cf = init("[A]", "a1 = 1 ,\n\t2 ,\n\t3 ");
-		assertObject(cf.getStringArray("A/a1")).asJson().is("['1','2','3']");
+		assertObject(cf.get("A/a1").toStringArray()).asJson().is("['1','2','3']");
 
 		System.setProperty("X", "4,5,6");
 		cf = init(null, "x1=$C{A/a1}", "x2=$S{X}", "x3=$S{Y}", "x4=$S{Y,$S{X}}", "[A]", "a1=1,2,3");
-		assertObject(cf.getStringArray("x1", new String[]{"9"})).asJson().is("['1','2','3']");
-		assertObject(cf.getStringArray("x2", new String[]{"9"})).asJson().is("['4','5','6']");
-		assertObject(cf.getStringArray("x3", new String[]{"9"})).asJson().is("['9']");
+		assertObject(cf.get("x1").asStringArray().orElse(new String[]{"9"})).asJson().is("['1','2','3']");
+		assertObject(cf.get("x2").asStringArray().orElse(new String[]{"9"})).asJson().is("['4','5','6']");
+		assertObject(cf.get("x9").asStringArray().orElse(new String[]{"9"})).asJson().is("['9']");
 
 		System.clearProperty("X");
 	}
@@ -1464,22 +1466,22 @@ public class ConfigTest {
 
 		cf = cf.resolving(vr.createSession());
 
-		assertEquals("aXa", cf.getString("a"));
-		assertEquals("bXb", cf.getString("b"));
-		assertEquals("abXba", cf.getString("c"));
-		assertEquals("baXab", cf.getString("d"));
-		assertEquals("$D{X}", cf.getString("e"));
+		assertEquals("aXa", cf.get("a").get());
+		assertEquals("bXb", cf.get("b").get());
+		assertEquals("abXba", cf.get("c").get());
+		assertEquals("baXab", cf.get("d").get());
+		assertEquals("$D{X}", cf.get("e").get());
 
 		// Create new resolver that addx $C and overrides $A
 		VarResolver vr2 = vr.copy().vars(AUVar.class, DUVar.class).build();
 
 		// true == augment by adding existing as parent to the new resolver
 		cf = cf.resolving(vr2.createSession());
-		assertEquals("AXA", cf.getString("a"));
-		assertEquals("bXb", cf.getString("b"));
-		assertEquals("AbXbA", cf.getString("c"));
-		assertEquals("bAXAb", cf.getString("d"));
-		assertEquals("DXD", cf.getString("e"));
+		assertEquals("AXA", cf.get("a").get());
+		assertEquals("bXb", cf.get("b").get());
+		assertEquals("AbXbA", cf.get("c").get());
+		assertEquals("bAXAb", cf.get("d").get());
+		assertEquals("DXD", cf.get("e").get());
 	}
 
 	public static class ALVar extends SimpleVar {
@@ -1536,12 +1538,12 @@ public class ConfigTest {
 		cf.commit();
 		assertString(cf).replaceAll("\\r?\\n", "|").is("a = a,\\u0023b,=c|[A]|a = a,\\u0023b,=c|");
 
-		assertEquals("a,#b,=c", cf.getString("a"));
-		assertEquals("a,#b,=c", cf.getString("A/a"));
+		assertEquals("a,#b,=c", cf.get("a").get());
+		assertEquals("a,#b,=c", cf.get("A/a").get());
 
 		cf.set("a", "a,#b,=c", null, (ConfigMod)null, "comment#comment", null);
 		assertString(cf).replaceAll("\\r?\\n", "|").is("a = a,\\u0023b,=c # comment#comment|[A]|a = a,\\u0023b,=c|");
-		assertEquals("a,#b,=c", cf.getString("a"));
+		assertEquals("a,#b,=c", cf.get("a").get());
 	}
 
 	public static class ABean {