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 2019/05/11 23:18:44 UTC

[juneau] branch master updated: @HtmlDocConfig annotation support.

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 9512c83  @HtmlDocConfig annotation support.
9512c83 is described below

commit 9512c83e9f67a1fd21f9787d66c6bf7b6d9e7480
Author: JamesBognar <ja...@apache.org>
AuthorDate: Sat May 11 19:17:54 2019 -0400

    @HtmlDocConfig annotation support.
---
 .../apache/juneau/BeanConfigAnnotationTest.java    |  79 ++++---
 .../src/test/java/org/apache/juneau/XVar.java}     |  29 ++-
 .../juneau/html/HtmlConfigAnnotationTest.java      |  24 +--
 .../juneau/html/HtmlDocConfigAnnotationTest.java   | 240 ++++++++++++++++++---
 .../juneau/jena/RdfConfigAnnotationTest.java       |  80 ++++---
 .../juneau/json/JsonConfigAnnotationTest.java      |  20 +-
 .../jsonschema/JsonSchemaConfigAnnotationTest.java |  24 +--
 .../msgpack/MsgPackConfigAnnotationTest.java       |  14 +-
 .../juneau/oapi/OpenApiConfigAnnotationTest.java   |  12 +-
 .../juneau/parser/ParserConfigAnnotationTest.java  |  28 +--
 .../plaintext/PlainTextConfigAnnotationTest.java   |  12 +-
 .../serializer/SerializerConfigAnnotationTest.java |  42 ++--
 .../juneau/soap/SoapXmlConfigAnnotationTest.java   |  14 +-
 .../apache/juneau/uon/UonConfigAnnotationTest.java |  22 +-
 .../UrlEncodingConfigAnnotationTest.java           |  14 +-
 .../apache/juneau/xml/XmlConfigAnnotationTest.java |  30 ++-
 .../java/org/apache/juneau/xml/XmlContentTest.java |   8 +-
 .../org/apache/juneau/jena/RdfParserBuilder.java   |   4 +-
 .../apache/juneau/jena/RdfSerializerBuilder.java   |   4 +-
 .../juneau/jena/annotation/RdfConfigApply.java     |   4 +-
 .../java/org/apache/juneau/BeanContextBuilder.java |   6 +-
 .../src/main/java/org/apache/juneau/BeanMap.java   |  11 +
 .../org/apache/juneau/BeanTraverseBuilder.java     |   4 +-
 .../main/java/org/apache/juneau/ConfigApply.java   |  10 +-
 .../java/org/apache/juneau/ContextBuilder.java     |   4 +-
 .../org/apache/juneau/PropertyStoreBuilder.java    |  42 +++-
 .../apache/juneau/annotation/BeanConfigApply.java  |   4 +-
 .../org/apache/juneau/csv/CsvParserBuilder.java    |   6 +-
 .../apache/juneau/csv/CsvSerializerBuilder.java    |   6 +-
 .../juneau/csv/annotation/CsvConfigApply.java      |   4 +-
 .../apache/juneau/html/BasicHtmlDocTemplate.java   |  26 +--
 .../org/apache/juneau/html/HtmlDocSerializer.java  |  89 ++++++++
 .../juneau/html/HtmlDocSerializerBuilder.java      |  81 ++++++-
 .../juneau/html/HtmlDocSerializerSession.java      |  22 ++
 .../org/apache/juneau/html/HtmlParserBuilder.java  |   6 +-
 .../juneau/html/HtmlSchemaSerializerBuilder.java   |   6 +-
 .../apache/juneau/html/HtmlSerializerBuilder.java  |   6 +-
 .../html/HtmlStrippedDocSerializerBuilder.java     |   6 +-
 .../java/org/apache/juneau/html/HtmlWidget.java    |  78 +++++++
 .../org/apache/juneau/html/HtmlWidgetVar.java}     |  48 +++--
 .../juneau/html/annotation/HtmlConfigApply.java    |   4 +-
 .../juneau/html/annotation/HtmlDocConfig.java      |  89 ++++----
 .../juneau/html/annotation/HtmlDocConfigApply.java |  81 +++++--
 .../org/apache/juneau/jso/JsoParserBuilder.java    |   6 +-
 .../apache/juneau/jso/JsoSerializerBuilder.java    |   6 +-
 .../juneau/jso/annotation/JsoConfigApply.java      |   4 +-
 .../org/apache/juneau/json/JsonParserBuilder.java  |   6 +-
 .../juneau/json/JsonSchemaSerializerBuilder.java   |   6 +-
 .../apache/juneau/json/JsonSerializerBuilder.java  |   6 +-
 .../juneau/json/annotation/JsonConfigApply.java    |   4 +-
 .../jsonschema/JsonSchemaGeneratorBuilder.java     |   4 +-
 .../annotation/JsonSchemaConfigApply.java          |   4 +-
 .../juneau/msgpack/MsgPackParserBuilder.java       |   6 +-
 .../juneau/msgpack/MsgPackSerializerBuilder.java   |   6 +-
 .../msgpack/annotation/MsgPackConfigApply.java     |   4 +-
 .../apache/juneau/oapi/OpenApiParserBuilder.java   |   6 +-
 .../juneau/oapi/OpenApiSerializerBuilder.java      |   6 +-
 .../juneau/oapi/annotation/OpenApiConfigApply.java |   4 +-
 .../juneau/parser/InputStreamParserBuilder.java    |   4 +-
 .../org/apache/juneau/parser/ParserBuilder.java    |   4 +-
 .../apache/juneau/parser/ParserGroupBuilder.java   |   4 +-
 .../apache/juneau/parser/ReaderParserBuilder.java  |   4 +-
 .../parser/annotation/ParserConfigApply.java       |   4 +-
 .../juneau/plaintext/PlainTextParserBuilder.java   |   4 +-
 .../plaintext/PlainTextSerializerBuilder.java      |   4 +-
 .../plaintext/annotation/PlainTextConfigApply.java |   4 +-
 .../serializer/OutputStreamSerializerBuilder.java  |   4 +-
 .../juneau/serializer/SerializerBuilder.java       |   4 +-
 .../juneau/serializer/SerializerGroupBuilder.java  |   4 +-
 .../juneau/serializer/SerializerSession.java       |  46 ++++
 .../juneau/serializer/SerializerSessionArgs.java   |  19 +-
 .../juneau/serializer/WriterSerializerBuilder.java |   4 +-
 .../annotation/SerializerConfigApply.java          |   4 +-
 .../juneau/soap/SoapXmlSerializerBuilder.java      |   4 +-
 .../juneau/soap/annotation/SoapXmlConfigApply.java |   4 +-
 .../java/org/apache/juneau/svl/DefaultingVar.java  |   0
 .../main/java/org/apache/juneau/svl/MapVar.java    |   0
 .../apache/juneau/svl/MultipartResolvingVar.java   |   0
 .../java/org/apache/juneau/svl/MultipartVar.java   |   0
 .../org/apache/juneau/svl/ResolvingObjectMap.java  |   0
 .../main/java/org/apache/juneau/svl/SimpleVar.java |   0
 .../java/org/apache/juneau/svl/StreamedVar.java    |   0
 .../src/main/java/org/apache/juneau/svl/Var.java   |  13 ++
 .../java/org/apache/juneau/svl/VarResolver.java    |   4 +-
 .../org/apache/juneau/svl/VarResolverBuilder.java  |   0
 .../org/apache/juneau/svl/VarResolverContext.java  |   0
 .../apache/juneau/svl/VarResolverException.java    |   0
 .../org/apache/juneau/svl/VarResolverSession.java  |   7 +-
 .../java/org/apache/juneau/svl/package-info.java   |   0
 .../java/org/apache/juneau/svl/vars/ArgsVar.java   |   0
 .../org/apache/juneau/svl/vars/CoalesceVar.java    |   0
 .../apache/juneau/svl/vars/EnvVariablesVar.java    |   0
 .../java/org/apache/juneau/svl/vars/IfVar.java     |   0
 .../java/org/apache/juneau/svl/vars/LenVar.java    |   0
 .../org/apache/juneau/svl/vars/LowerCaseVar.java   |   0
 .../apache/juneau/svl/vars/ManifestFileVar.java    |   0
 .../org/apache/juneau/svl/vars/NotEmptyVar.java    |   0
 .../apache/juneau/svl/vars/PatternExtractVar.java  |   0
 .../apache/juneau/svl/vars/PatternMatchVar.java    |   0
 .../apache/juneau/svl/vars/PatternReplaceVar.java  |   0
 .../org/apache/juneau/svl/vars/SubstringVar.java   |   0
 .../java/org/apache/juneau/svl/vars/SwitchVar.java |   0
 .../juneau/svl/vars/SystemPropertiesVar.java       |   0
 .../org/apache/juneau/svl/vars/UpperCaseVar.java   |   0
 .../org/apache/juneau/svl/vars/package-info.java   |   0
 .../org/apache/juneau/uon/UonParserBuilder.java    |   4 +-
 .../apache/juneau/uon/UonSerializerBuilder.java    |   4 +-
 .../juneau/uon/annotation/UonConfigApply.java      |   4 +-
 .../urlencoding/UrlEncodingParserBuilder.java      |   4 +-
 .../urlencoding/UrlEncodingSerializerBuilder.java  |   4 +-
 .../annotation/UrlEncodingConfigApply.java         |   4 +-
 .../org/apache/juneau/utils/StringResolver.java    |  37 ----
 .../org/apache/juneau/xml/XmlParserBuilder.java    |   6 +-
 .../apache/juneau/xml/XmlSerializerBuilder.java    |   4 +-
 .../juneau/xml/annotation/XmlConfigApply.java      |   4 +-
 .../xmlschema/XmlSchemaSerializerBuilder.java      |   4 +-
 .../juneau/rest/client/RestClientBuilder.java      |   4 +-
 .../juneau/rest/client/RestRequestEntity.java      |   2 +-
 .../org/apache/juneau/rest/jaxrs/BaseProvider.java |   2 +-
 .../org/apache/juneau/rest/RestJavaMethod.java     |   3 +-
 .../java/org/apache/juneau/rest/RestRequest.java   |   2 +-
 .../org/apache/juneau/rest/SwaggerGenerator.java   |   2 +-
 .../juneau/rest/reshandlers/DefaultHandler.java    |   2 +-
 .../apache/juneau/rest/widget/MenuItemWidget.java  |   2 +-
 124 files changed, 1093 insertions(+), 575 deletions(-)

diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/BeanConfigAnnotationTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/BeanConfigAnnotationTest.java
index 82f416c..a2f7848 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/BeanConfigAnnotationTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/BeanConfigAnnotationTest.java
@@ -23,8 +23,8 @@ import org.apache.juneau.internal.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.marshall.*;
 import org.apache.juneau.reflect.*;
+import org.apache.juneau.svl.*;
 import org.apache.juneau.transform.*;
-import org.apache.juneau.utils.*;
 import org.junit.*;
 
 /**
@@ -75,14 +75,7 @@ public class BeanConfigAnnotationTest {
 		}
 	};
 
-	static StringResolver sr = new StringResolver() {
-		@Override
-		public String resolve(String input) {
-			if (input != null && input.startsWith("$"))
-				input = input.substring(1);
-			return input;
-		}
-	};
+	static VarResolverSession sr = VarResolver.create().vars(XVar.class).build().createSession();
 
 	//-----------------------------------------------------------------------------------------------------------------
 	// Basic tests
@@ -110,54 +103,54 @@ public class BeanConfigAnnotationTest {
 	}
 
 	@BeanConfig(
-		beanClassVisibility="$PRIVATE",
-		beanConstructorVisibility="$PRIVATE",
+		beanClassVisibility="$X{PRIVATE}",
+		beanConstructorVisibility="$X{PRIVATE}",
 		beanDictionary={A1.class,A2.class},
 		beanDictionary_replace={A1.class,A2.class,A3.class},
 		beanDictionary_remove=A2.class,
-		beanFieldVisibility="$PRIVATE",
+		beanFieldVisibility="$X{PRIVATE}",
 		beanFilters={A1.class,A2.class},
 		beanFilters_replace={A1.class,A2.class,A3.class},
 		beanFilters_remove=A2.class,
-		beanMapPutReturnsOldValue="$true",
-		beanMethodVisibility="$PRIVATE",
-		beansRequireDefaultConstructor="$true",
-		beansRequireSerializable="$true",
-		beansRequireSettersForGetters="$true",
-		beansRequireSomeProperties="$true",
-		beanTypePropertyName="$foo",
-		debug="$true",
-		detectRecursions="$true",
-		examples="$A1: {foo:1}",
-		excludeProperties=@CS(k=A1.class,v="$foo"),
-		fluentSetters="$true",
-		ignoreInvocationExceptionsOnGetters="$true",
-		ignoreInvocationExceptionsOnSetters="$true",
-		ignorePropertiesWithoutSetters="$true",
-		ignoreRecursions="$true",
-		ignoreUnknownBeanProperties="$true",
-		ignoreUnknownNullBeanProperties="$true",
+		beanMapPutReturnsOldValue="$X{true}",
+		beanMethodVisibility="$X{PRIVATE}",
+		beansRequireDefaultConstructor="$X{true}",
+		beansRequireSerializable="$X{true}",
+		beansRequireSettersForGetters="$X{true}",
+		beansRequireSomeProperties="$X{true}",
+		beanTypePropertyName="$X{foo}",
+		debug="$X{true}",
+		detectRecursions="$X{true}",
+		examples="$X{A1}: {foo:1}",
+		excludeProperties=@CS(k=A1.class,v="$X{foo}"),
+		fluentSetters="$X{true}",
+		ignoreInvocationExceptionsOnGetters="$X{true}",
+		ignoreInvocationExceptionsOnSetters="$X{true}",
+		ignorePropertiesWithoutSetters="$X{true}",
+		ignoreRecursions="$X{true}",
+		ignoreUnknownBeanProperties="$X{true}",
+		ignoreUnknownNullBeanProperties="$X{true}",
 		implClasses=@CC(k=A1.class,v=A1.class),
-		includeProperties=@CS(k=A1.class,v="$foo"),
-		initialDepth="$1",
-		locale="$en-US",
-		maxDepth="$1",
-		mediaType="$text/foo",
+		includeProperties=@CS(k=A1.class,v="$X{foo}"),
+		initialDepth="$X{1}",
+		locale="$X{en-US}",
+		maxDepth="$X{1}",
+		mediaType="$X{text/foo}",
 		notBeanClasses={A1.class,A2.class},
 		notBeanClasses_replace={A1.class,A2.class,A3.class},
 		notBeanClasses_remove=A2.class,
-		notBeanPackages={"$foo1","$foo2"},
-		notBeanPackages_replace={"$foo1","$foo2","$foo3"},
-		notBeanPackages_remove={"$foo2"},
+		notBeanPackages={"$X{foo1}","$X{foo2}"},
+		notBeanPackages_replace={"$X{foo1}","$X{foo2}","$X{foo3}"},
+		notBeanPackages_remove={"$X{foo2}"},
 		pojoSwaps={AB1.class,AB2.class},
 		pojoSwaps_replace={AB1.class,AB2.class,AB3.class},
 		pojoSwaps_remove=AB2.class,
 		propertyNamer=PropertyNamerULC.class,
-		sortProperties="$true",
-		timeZone="$z",
-		useEnumNames="$true",
-		useInterfaceProxies="$true",
-		useJavaBeanIntrospector="$true"
+		sortProperties="$X{true}",
+		timeZone="$X{z}",
+		useEnumNames="$X{true}",
+		useInterfaceProxies="$X{true}",
+		useJavaBeanIntrospector="$X{true}"
 	)
 	static class A {}
 	static ClassInfo a = ClassInfo.of(A.class);
diff --git a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/CoalesceVar.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/XVar.java
similarity index 78%
copy from juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/CoalesceVar.java
copy to juneau-core/juneau-core-test/src/test/java/org/apache/juneau/XVar.java
index 4e5e0ff..05b004e 100644
--- a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/CoalesceVar.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/XVar.java
@@ -10,36 +10,31 @@
 // * "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.svl.vars;
+package org.apache.juneau;
+
+import java.io.*;
 
 import org.apache.juneau.svl.*;
 
 /**
- * A basic variable resolver that returns the first non-null value.
- *
- * <p>
- * The format for this var is <js>"$CO{arg1[,arg2...]}"</js>.
- *
- *
- * <h5 class='section'>See Also:</h5>
- * <ul>
- * 	<li class='link'>{@doc juneau-svl.SvlVariables}
- * </ul>
+ * Dummy variable for resolving <code>$X{...}</code> variables.
  */
-public class CoalesceVar extends MultipartResolvingVar {
-
-	/** The name of this variable. */
-	public static final String NAME = "CO";
+public class XVar extends Var {
 
 	/**
 	 * Constructor.
 	 */
-	public CoalesceVar() {
-		super(NAME);
+	public XVar() {
+		super("X", false);
 	}
 
 	@Override
 	public String resolve(VarResolverSession session, String arg) throws Exception {
 		return arg;
 	}
+
+	@Override
+	public void resolveTo(VarResolverSession session, Writer w, String arg) throws Exception {
+		w.append(arg);
+	}
 }
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/html/HtmlConfigAnnotationTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/html/HtmlConfigAnnotationTest.java
index daed405..8fa238d 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/html/HtmlConfigAnnotationTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/html/HtmlConfigAnnotationTest.java
@@ -16,9 +16,10 @@ import static org.junit.Assert.*;
 
 import java.util.function.*;
 
+import org.apache.juneau.*;
 import org.apache.juneau.html.annotation.*;
 import org.apache.juneau.reflect.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 import org.junit.*;
 
 /**
@@ -39,26 +40,19 @@ public class HtmlConfigAnnotationTest {
 		}
 	};
 
-	static StringResolver sr = new StringResolver() {
-		@Override
-		public String resolve(String input) {
-			if (input.startsWith("$"))
-				input = input.substring(1);
-			return input;
-		}
-	};
+	static VarResolverSession sr = VarResolver.create().vars(XVar.class).build().createSession();
 
 	//-----------------------------------------------------------------------------------------------------------------
 	// Basic tests
 	//-----------------------------------------------------------------------------------------------------------------
 
 	@HtmlConfig(
-		addBeanTypes="$true",
-		addKeyValueTableHeaders="$true",
-		detectLabelParameters="$true",
-		detectLinksInStrings="$true",
-		labelParameter="$foo",
-		uriAnchorText="$TO_STRING"
+		addBeanTypes="$X{true}",
+		addKeyValueTableHeaders="$X{true}",
+		detectLabelParameters="$X{true}",
+		detectLinksInStrings="$X{true}",
+		labelParameter="$X{foo}",
+		uriAnchorText="$X{TO_STRING}"
 	)
 	static class A {}
 	static ClassInfo a = ClassInfo.of(A.class);
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/html/HtmlDocConfigAnnotationTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/html/HtmlDocConfigAnnotationTest.java
index fc31a65..599ca18 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/html/HtmlDocConfigAnnotationTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/html/HtmlDocConfigAnnotationTest.java
@@ -13,15 +13,17 @@
 package org.apache.juneau.html;
 
 import static org.junit.Assert.*;
+import static org.apache.juneau.testutils.TestUtils.*;
 
 import java.util.*;
 import java.util.function.*;
 import java.util.stream.*;
 
+import org.apache.juneau.*;
 import org.apache.juneau.html.annotation.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.reflect.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 import org.junit.*;
 
 /**
@@ -49,35 +51,24 @@ public class HtmlDocConfigAnnotationTest {
 		}
 	};
 
-	static StringResolver sr = new StringResolver() {
-		@Override
-		public String resolve(String input) {
-			if (input.startsWith("$"))
-				input = input.substring(1);
-			return input;
-		}
-	};
+	static VarResolverSession sr = VarResolver.create().vars(XVar.class).build().createSession();
 
 	//-----------------------------------------------------------------------------------------------------------------
 	// Basic tests
 	//-----------------------------------------------------------------------------------------------------------------
 
 	@HtmlDocConfig(
-		aside="$foo",
-		footer="$foo",
-		head="$foo",
-		header="$foo",
-		nav="$foo",
-		navlinks="$foo1",
-		navlinks_replace="$foo2",
-		noResultsMessage="$foo",
-		nowrap="$true",
-		script="$foo1",
-		script_replace="$foo2",
-		style="$foo1",
-		style_replace="$foo2",
-		stylesheet="$foo1",
-		stylesheet_replace="$foo2",
+		aside="$X{foo}",
+		footer="$X{foo}",
+		head="$X{foo}",
+		header="$X{foo}",
+		nav="$X{foo}",
+		navlinks="$X{foo1}",
+		noResultsMessage="$X{foo}",
+		nowrap="$X{true}",
+		script="$X{foo1}",
+		style="$X{foo1}",
+		stylesheet="$X{foo1}",
 		template=BasicHtmlDocTemplate.class
 	)
 	static class A {}
@@ -92,12 +83,12 @@ public class HtmlDocConfigAnnotationTest {
 		check("foo", x.getHead());
 		check("foo", x.getHeader());
 		check("foo", x.getNav());
-		check("foo2", x.getNavlinks());
+		check("foo1", x.getNavlinks());
 		check("foo", x.getNoResultsMessage());
 		check("true", x.isNowrap());
-		check("foo2", x.getScript());
-		check("foo2", x.getStyle());
-		check("foo2", x.getStylesheet());
+		check("foo1", x.getScript());
+		check("foo1", x.getStyle());
+		check("foo1", x.getStylesheet());
 		check("BasicHtmlDocTemplate", x.getTemplate());
 	}
 
@@ -151,4 +142,197 @@ public class HtmlDocConfigAnnotationTest {
 		check("", x.getStylesheet());
 		check("BasicHtmlDocTemplate", x.getTemplate());
 	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// Inheritance tests
+	//-----------------------------------------------------------------------------------------------------------------
+
+	@HtmlDocConfig(
+		aside={"$X{foo2}","$X{INHERIT}"},
+		footer={"$X{foo2}","$X{INHERIT}"},
+		head={"$X{foo2}","$X{INHERIT}"},
+		header={"$X{foo2}","$X{INHERIT}"},
+		nav={"$X{foo2}","$X{INHERIT}"},
+		navlinks={"$X{foo2}","$X{INHERIT}"},
+		script={"$X{foo2}","$X{INHERIT}"},
+		style={"$X{foo2}","$X{INHERIT}"},
+		stylesheet={"$X{foo2}","$X{INHERIT}"}
+	)
+	static class D1 extends A {}
+	static ClassInfo d1 = ClassInfo.of(D1.class);
+
+	@Test
+	public void inheritance1() throws Exception {
+		AnnotationsMap m = d1.getAnnotationsMapParentFirst();
+		HtmlDocSerializerSession x = HtmlDocSerializer.create().applyAnnotations(m, sr).build().createSession();
+		check("foo2,foo", x.getAside());
+		check("foo2,foo", x.getFooter());
+		check("foo2,foo", x.getHead());
+		check("foo2,foo", x.getHeader());
+		check("foo2,foo", x.getNav());
+		check("foo2,foo1", x.getNavlinks());
+		check("foo2,foo1", x.getScript());
+		check("foo2,foo1", x.getStyle());
+		check("foo2,foo1", x.getStylesheet());
+	}
+
+	@HtmlDocConfig(
+		aside={"$X{INHERIT}","$X{foo2}"},
+		footer={"$X{INHERIT}","$X{foo2}"},
+		head={"$X{INHERIT}","$X{foo2}"},
+		header={"$X{INHERIT}","$X{foo2}"},
+		nav={"$X{INHERIT}","$X{foo2}"},
+		navlinks={"$X{INHERIT}","$X{foo2}"},
+		script={"$X{INHERIT}","$X{foo2}"},
+		style={"$X{INHERIT}","$X{foo2}"},
+		stylesheet={"$X{INHERIT}","$X{foo2}"}
+	)
+	static class D2 extends A {}
+	static ClassInfo d2 = ClassInfo.of(D2.class);
+
+	@Test
+	public void inheritance2() throws Exception {
+		AnnotationsMap m = d2.getAnnotationsMapParentFirst();
+		HtmlDocSerializerSession x = HtmlDocSerializer.create().applyAnnotations(m, sr).build().createSession();
+		check("foo,foo2", x.getAside());
+		check("foo,foo2", x.getFooter());
+		check("foo,foo2", x.getHead());
+		check("foo,foo2", x.getHeader());
+		check("foo,foo2", x.getNav());
+		check("foo1,foo2", x.getNavlinks());
+		check("foo1,foo2", x.getScript());
+		check("foo1,foo2", x.getStyle());
+		check("foo1,foo2", x.getStylesheet());
+	}
+
+	@HtmlDocConfig(
+		aside={"$X{foo2}"},
+		footer={"$X{foo2}"},
+		head={"$X{foo2}"},
+		header={"$X{foo2}"},
+		nav={"$X{foo2}"},
+		navlinks={"$X{foo2}"},
+		script={"$X{foo2}"},
+		style={"$X{foo2}"},
+		stylesheet={"$X{foo2}"}
+	)
+	static class D3 extends A {}
+	static ClassInfo d3 = ClassInfo.of(D3.class);
+
+	@Test
+	public void inheritance3() throws Exception {
+		AnnotationsMap m = d3.getAnnotationsMapParentFirst();
+		HtmlDocSerializerSession x = HtmlDocSerializer.create().applyAnnotations(m, sr).build().createSession();
+		check("foo2", x.getAside());
+		check("foo2", x.getFooter());
+		check("foo2", x.getHead());
+		check("foo2", x.getHeader());
+		check("foo2", x.getNav());
+		check("foo2", x.getNavlinks());
+		check("foo2", x.getScript());
+		check("foo2", x.getStyle());
+		check("foo2", x.getStylesheet());
+	}
+
+	@HtmlDocConfig(
+		aside={"NONE"},
+		footer={"NONE"},
+		head={"NONE"},
+		header={"NONE"},
+		nav={"NONE"},
+		navlinks={"NONE"},
+		script={"NONE"},
+		style={"NONE"},
+		stylesheet={"NONE"}
+	)
+	static class D4 extends A {}
+	static ClassInfo d4 = ClassInfo.of(D4.class);
+
+	@Test
+	public void inheritance4() throws Exception {
+		AnnotationsMap m = d4.getAnnotationsMapParentFirst();
+		HtmlDocSerializerSession x = HtmlDocSerializer.create().applyAnnotations(m, sr).build().createSession();
+		check("", x.getAside());
+		check("", x.getFooter());
+		check("", x.getHead());
+		check("", x.getHeader());
+		check("", x.getNav());
+		check("", x.getNavlinks());
+		check("", x.getScript());
+		check("", x.getStyle());
+		check("", x.getStylesheet());
+	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// Widgets
+	//-----------------------------------------------------------------------------------------------------------------
+
+	@HtmlDocConfig(
+		aside="$W{E}",
+		footer="$W{E}",
+		head="$W{E}",
+		header="$W{E}",
+		nav="$W{E}",
+		navlinks="$W{E}",
+		noResultsMessage="$W{E}",
+		nowrap="$W{E}",
+		script="$W{E}",
+		style="$W{E}",
+		stylesheet="$W{E}",
+		widgets=EWidget.class
+	)
+	static class E {}
+	static ClassInfo e = ClassInfo.of(E.class);
+
+	public static class EWidget implements HtmlWidget {
+		@Override
+		public String getName() {
+			return "E";
+		}
+		@Override
+		public String getHtml(VarResolverSession session) throws Exception {
+			return "xxx";
+		}
+		@Override
+		public String getScript(VarResolverSession session) throws Exception {
+			return "yyy";
+		}
+		@Override
+		public String getStyle(VarResolverSession session) throws Exception {
+			return "zzz";
+		}
+	}
+
+	@Test
+	public void widgets_basic() throws Exception {
+		AnnotationsMap m = e.getAnnotationsMapParentFirst();
+		HtmlDocSerializerSession x = HtmlDocSerializer.create().applyAnnotations(m, sr).build().createSession();
+		check("$W{E}", x.getAside());
+		check("$W{E}", x.getFooter());
+		check("$W{E}", x.getHead());
+		check("$W{E}", x.getHeader());
+		check("$W{E}", x.getNav());
+		check("$W{E}", x.getNavlinks());
+		check("$W{E}", x.getNoResultsMessage());
+		check("false", x.isNowrap());
+		check("$W{E}", x.getScript());
+		check("$W{E}", x.getStyle());
+		check("$W{E}", x.getStylesheet());
+		check("BasicHtmlDocTemplate", x.getTemplate());
+	}
+
+	@Test
+	public void widgets_resolution() throws Exception {
+		AnnotationsMap m = e.getAnnotationsMapParentFirst();
+		HtmlDocSerializerSession x = HtmlDocSerializer.create().applyAnnotations(m, sr).build().createSession();
+		String r = x.serialize(null).replaceAll("[\r\n]+", "|");
+		assertContains(r,
+			"<aside>xxx</aside>",
+			"<footer>xxx</footer>",
+			"<head>xxx",
+			"<style>@import \"xxx\"; xxx zzz</style>",
+			"<nav><ol><li>xxx</li></ol>xxx</nav>",
+			"<script>xxx| yyy|</script>"
+		);
+	}
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/jena/RdfConfigAnnotationTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/jena/RdfConfigAnnotationTest.java
index 77c4a10..5d43e00 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/jena/RdfConfigAnnotationTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/jena/RdfConfigAnnotationTest.java
@@ -19,11 +19,12 @@ import java.util.*;
 import java.util.function.*;
 import java.util.stream.*;
 
+import org.apache.juneau.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.jena.annotation.*;
 import org.apache.juneau.marshall.*;
 import org.apache.juneau.reflect.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 import org.junit.*;
 
 /**
@@ -51,54 +52,47 @@ public class RdfConfigAnnotationTest {
 		}
 	};
 
-	static StringResolver sr = new StringResolver() {
-		@Override
-		public String resolve(String input) {
-			if (input.startsWith("$"))
-				input = input.substring(1);
-			return input;
-		}
-	};
+	static VarResolverSession sr = VarResolver.create().vars(XVar.class).build().createSession();
 
 	//-----------------------------------------------------------------------------------------------------------------
 	// Basic tests
 	//-----------------------------------------------------------------------------------------------------------------
 
 	@RdfConfig(
-		addBeanTypes="$true",
-		addLiteralTypes="$true",
-		addRootProperty="$true",
-		arp_embedding="$true",
-		arp_errorMode="$strict",
-		arp_iriRules="$strict",
-		autoDetectNamespaces="$true",
-		collectionFormat="$SEQ",
-		juneauBpNs="$foo:http://foo",
-		juneauNs="$foo:http://foo",
-		language="$N3",
-		looseCollections="$true",
-		n3_abbrevBaseUri="$true",
-		n3_indentProperty="$1",
-		n3_minGap="$1",
-		n3_objectLists="$true",
-		n3_propertyColumn="$1",
-		n3_subjectColumn="$1",
-		n3_useDoubles="$true",
-		n3_usePropertySymbols="$true",
-		n3_useTripleQuotedStrings="$true",
-		n3_widePropertyLen="$1",
-		namespaces="$foo:http://foo",
-		rdfxml_allowBadUris="$true",
-		rdfxml_attributeQuoteChar="$'",
-		rdfxml_blockRules="$foo",
-		rdfxml_longId="$true",
-		rdfxml_relativeUris="$absolute",
-		rdfxml_showDoctypeDeclaration="$true",
-		rdfxml_showXmlDeclaration="$true",
-		rdfxml_tab="$1",
-		rdfxml_xmlBase="$foo",
-		trimWhitespace="$true",
-		useXmlNamespaces="$true"
+		addBeanTypes="$X{true}",
+		addLiteralTypes="$X{true}",
+		addRootProperty="$X{true}",
+		arp_embedding="$X{true}",
+		arp_errorMode="$X{strict}",
+		arp_iriRules="$X{strict}",
+		autoDetectNamespaces="$X{true}",
+		collectionFormat="$X{SEQ}",
+		juneauBpNs="$X{foo:http://foo}",
+		juneauNs="$X{foo:http://foo}",
+		language="$X{N3}",
+		looseCollections="$X{true}",
+		n3_abbrevBaseUri="$X{true}",
+		n3_indentProperty="$X{1}",
+		n3_minGap="$X{1}",
+		n3_objectLists="$X{true}",
+		n3_propertyColumn="$X{1}",
+		n3_subjectColumn="$X{1}",
+		n3_useDoubles="$X{true}",
+		n3_usePropertySymbols="$X{true}",
+		n3_useTripleQuotedStrings="$X{true}",
+		n3_widePropertyLen="$X{1}",
+		namespaces="$X{foo:http://foo}",
+		rdfxml_allowBadUris="$X{true}",
+		rdfxml_attributeQuoteChar="$X{'}",
+		rdfxml_blockRules="$X{foo}",
+		rdfxml_longId="$X{true}",
+		rdfxml_relativeUris="$X{absolute}",
+		rdfxml_showDoctypeDeclaration="$X{true}",
+		rdfxml_showXmlDeclaration="$X{true}",
+		rdfxml_tab="$X{1}",
+		rdfxml_xmlBase="$X{foo}",
+		trimWhitespace="$X{true}",
+		useXmlNamespaces="$X{true}"
 	)
 	static class A {}
 	static ClassInfo a = ClassInfo.of(A.class);
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/json/JsonConfigAnnotationTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/json/JsonConfigAnnotationTest.java
index abd0bf4..d2ee201 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/json/JsonConfigAnnotationTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/json/JsonConfigAnnotationTest.java
@@ -16,9 +16,10 @@ import static org.junit.Assert.*;
 
 import java.util.function.*;
 
+import org.apache.juneau.*;
 import org.apache.juneau.json.annotation.*;
 import org.apache.juneau.reflect.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 import org.junit.*;
 
 /**
@@ -37,24 +38,17 @@ public class JsonConfigAnnotationTest {
 		}
 	};
 
-	static StringResolver sr = new StringResolver() {
-		@Override
-		public String resolve(String input) {
-			if (input.startsWith("$"))
-				input = input.substring(1);
-			return input;
-		}
-	};
+	static VarResolverSession sr = VarResolver.create().vars(XVar.class).build().createSession();
 
 	//-----------------------------------------------------------------------------------------------------------------
 	// Basic tests
 	//-----------------------------------------------------------------------------------------------------------------
 
 	@JsonConfig(
-		addBeanTypes="$true",
-		escapeSolidus="$true",
-		simpleMode="$true",
-		validateEnd="$true"
+		addBeanTypes="$X{true}",
+		escapeSolidus="$X{true}",
+		simpleMode="$X{true}",
+		validateEnd="$X{true}"
 	)
 	static class A {}
 	static ClassInfo a = ClassInfo.of(A.class);
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/jsonschema/JsonSchemaConfigAnnotationTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/jsonschema/JsonSchemaConfigAnnotationTest.java
index 79bf167..bd64fc9 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/jsonschema/JsonSchemaConfigAnnotationTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/jsonschema/JsonSchemaConfigAnnotationTest.java
@@ -18,10 +18,11 @@ import java.util.*;
 import java.util.function.*;
 import java.util.stream.*;
 
+import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.jsonschema.annotation.*;
 import org.apache.juneau.reflect.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 import org.junit.*;
 
 /**
@@ -47,28 +48,21 @@ public class JsonSchemaConfigAnnotationTest {
 		}
 	};
 
-	static StringResolver sr = new StringResolver() {
-		@Override
-		public String resolve(String input) {
-			if (input.startsWith("$"))
-				input = input.substring(1);
-			return input;
-		}
-	};
+	static VarResolverSession sr = VarResolver.create().vars(XVar.class).build().createSession();
 
 	//-----------------------------------------------------------------------------------------------------------------
 	// Basic tests
 	//-----------------------------------------------------------------------------------------------------------------
 
 	@JsonSchemaConfig(
-		addDescriptionsTo="$BEAN",
-		addExamplesTo="$BEAN",
-		allowNestedDescriptions="$true",
-		allowNestedExamples="$true",
+		addDescriptionsTo="$X{BEAN}",
+		addExamplesTo="$X{BEAN}",
+		allowNestedDescriptions="$X{true}",
+		allowNestedExamples="$X{true}",
 		beanDefMapper=BasicBeanDefMapper.class,
 		defaultSchemas=@CS(k=A.class,v="{foo:'bar'}"),
-		ignoreTypes="$foo",
-		useBeanDefs="$true"
+		ignoreTypes="$X{foo}",
+		useBeanDefs="$X{true}"
 	)
 	static class A {}
 	static ClassInfo a = ClassInfo.of(A.class);
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/msgpack/MsgPackConfigAnnotationTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/msgpack/MsgPackConfigAnnotationTest.java
index 1ecbed6..6da6dfe 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/msgpack/MsgPackConfigAnnotationTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/msgpack/MsgPackConfigAnnotationTest.java
@@ -16,9 +16,10 @@ import static org.junit.Assert.*;
 
 import java.util.function.*;
 
+import org.apache.juneau.*;
 import org.apache.juneau.msgpack.annotation.*;
 import org.apache.juneau.reflect.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 import org.junit.*;
 
 /**
@@ -37,21 +38,14 @@ public class MsgPackConfigAnnotationTest {
 		}
 	};
 
-	static StringResolver sr = new StringResolver() {
-		@Override
-		public String resolve(String input) {
-			if (input.startsWith("$"))
-				input = input.substring(1);
-			return input;
-		}
-	};
+	static VarResolverSession sr = VarResolver.create().vars(XVar.class).build().createSession();
 
 	//-----------------------------------------------------------------------------------------------------------------
 	// Basic tests
 	//-----------------------------------------------------------------------------------------------------------------
 
 	 @MsgPackConfig(
-		addBeanTypes="$true"
+		addBeanTypes="$X{true}"
 	)
 	static class A {}
 	static ClassInfo a = ClassInfo.of(A.class);
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/oapi/OpenApiConfigAnnotationTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/oapi/OpenApiConfigAnnotationTest.java
index b64b2b6..c95f474 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/oapi/OpenApiConfigAnnotationTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/oapi/OpenApiConfigAnnotationTest.java
@@ -12,9 +12,10 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.oapi;
 
+import org.apache.juneau.*;
 import org.apache.juneau.oapi.annotation.*;
 import org.apache.juneau.reflect.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 import org.junit.*;
 
 /**
@@ -22,14 +23,7 @@ import org.junit.*;
  */
 public class OpenApiConfigAnnotationTest {
 
-	static StringResolver sr = new StringResolver() {
-		@Override
-		public String resolve(String input) {
-			if (input.startsWith("$"))
-				input = input.substring(1);
-			return input;
-		}
-	};
+	static VarResolverSession sr = VarResolver.create().vars(XVar.class).build().createSession();
 
 	//-----------------------------------------------------------------------------------------------------------------
 	// Annotation with no values.
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/parser/ParserConfigAnnotationTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/parser/ParserConfigAnnotationTest.java
index 6e4d524..5082094 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/parser/ParserConfigAnnotationTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/parser/ParserConfigAnnotationTest.java
@@ -16,11 +16,12 @@ import static org.junit.Assert.*;
 
 import java.util.function.*;
 
+import org.apache.juneau.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.msgpack.*;
 import org.apache.juneau.parser.annotation.*;
 import org.apache.juneau.reflect.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 import org.junit.*;
 
 /**
@@ -43,14 +44,7 @@ public class ParserConfigAnnotationTest {
 		}
 	};
 
-	static StringResolver sr = new StringResolver() {
-		@Override
-		public String resolve(String input) {
-			if (input.startsWith("$"))
-				input = input.substring(1);
-			return input;
-		}
-	};
+	static VarResolverSession sr = VarResolver.create().vars(XVar.class).build().createSession();
 
 	//-----------------------------------------------------------------------------------------------------------------
 	// Basic tests
@@ -59,15 +53,15 @@ public class ParserConfigAnnotationTest {
 	public static class AA extends ParserListener {}
 
 	@ParserConfig(
-		autoCloseStreams="$true",
-		binaryFormat="HEX",
-		debugOutputLines="$1",
-		fileCharset="$foo",
-		inputStreamCharset="$foo",
+		autoCloseStreams="$X{true}",
+		binaryFormat="$X{HEX}",
+		debugOutputLines="$X{1}",
+		fileCharset="$X{foo}",
+		inputStreamCharset="$X{foo}",
 		listener=AA.class,
-		strict="$true",
-		trimStrings="$true",
-		unbuffered="$true"
+		strict="$X{true}",
+		trimStrings="$X{true}",
+		unbuffered="$X{true}"
 	)
 	static class A {}
 	static ClassInfo a = ClassInfo.of(A.class);
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/plaintext/PlainTextConfigAnnotationTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/plaintext/PlainTextConfigAnnotationTest.java
index af162de..8f4aac1 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/plaintext/PlainTextConfigAnnotationTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/plaintext/PlainTextConfigAnnotationTest.java
@@ -12,9 +12,10 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.plaintext;
 
+import org.apache.juneau.*;
 import org.apache.juneau.plaintext.annotation.*;
 import org.apache.juneau.reflect.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 import org.junit.*;
 
 /**
@@ -22,14 +23,7 @@ import org.junit.*;
  */
 public class PlainTextConfigAnnotationTest {
 
-	static StringResolver sr = new StringResolver() {
-		@Override
-		public String resolve(String input) {
-			if (input.startsWith("$"))
-				input = input.substring(1);
-			return input;
-		}
-	};
+	static VarResolverSession sr = VarResolver.create().vars(XVar.class).build().createSession();
 
 	//-----------------------------------------------------------------------------------------------------------------
 	// Annotation with no values.
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/serializer/SerializerConfigAnnotationTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/serializer/SerializerConfigAnnotationTest.java
index 4b3fbd8..c778460 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/serializer/SerializerConfigAnnotationTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/serializer/SerializerConfigAnnotationTest.java
@@ -16,11 +16,12 @@ import static org.junit.Assert.*;
 
 import java.util.function.*;
 
+import org.apache.juneau.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.msgpack.*;
 import org.apache.juneau.reflect.*;
 import org.apache.juneau.serializer.annotation.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 import org.junit.*;
 
 /**
@@ -43,14 +44,7 @@ public class SerializerConfigAnnotationTest {
 		}
 	};
 
-	static StringResolver sr = new StringResolver() {
-		@Override
-		public String resolve(String input) {
-			if (input.startsWith("$"))
-				input = input.substring(1);
-			return input;
-		}
-	};
+	static VarResolverSession sr = VarResolver.create().vars(XVar.class).build().createSession();
 
 	//-----------------------------------------------------------------------------------------------------------------
 	// Basic tests
@@ -59,22 +53,22 @@ public class SerializerConfigAnnotationTest {
 	public static class AA extends SerializerListener {}
 
 	@SerializerConfig(
-		addBeanTypes="$true",
-		addRootType="$true",
-		binaryFormat="$HEX",
+		addBeanTypes="$X{true}",
+		addRootType="$X{true}",
+		binaryFormat="$X{HEX}",
 		listener=AA.class,
-		maxIndent="$1",
-		quoteChar="$'",
-		sortCollections="$true",
-		sortMaps="$true",
-		trimEmptyCollections="$true",
-		trimEmptyMaps="$true",
-		trimNullProperties="$true",
-		trimStrings="$true",
-		uriContext="${}",
-		uriRelativity="$RESOURCE",
-		uriResolution="$ABSOLUTE",
-		useWhitespace="$true"
+		maxIndent="$X{1}",
+		quoteChar="$X{'}",
+		sortCollections="$X{true}",
+		sortMaps="$X{true}",
+		trimEmptyCollections="$X{true}",
+		trimEmptyMaps="$X{true}",
+		trimNullProperties="$X{true}",
+		trimStrings="$X{true}",
+		uriContext="{}",
+		uriRelativity="$X{RESOURCE}",
+		uriResolution="$X{ABSOLUTE}",
+		useWhitespace="$X{true}"
 	)
 	static class A {}
 	static ClassInfo a = ClassInfo.of(A.class);
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/soap/SoapXmlConfigAnnotationTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/soap/SoapXmlConfigAnnotationTest.java
index a695936..1a6b157 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/soap/SoapXmlConfigAnnotationTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/soap/SoapXmlConfigAnnotationTest.java
@@ -16,9 +16,10 @@ import static org.junit.Assert.*;
 
 import java.util.function.*;
 
+import org.apache.juneau.*;
 import org.apache.juneau.reflect.*;
 import org.apache.juneau.soap.annotation.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 import org.junit.*;
 
 /**
@@ -37,21 +38,14 @@ public class SoapXmlConfigAnnotationTest {
 		}
 	};
 
-	static StringResolver sr = new StringResolver() {
-		@Override
-		public String resolve(String input) {
-			if (input.startsWith("$"))
-				input = input.substring(1);
-			return input;
-		}
-	};
+	static VarResolverSession sr = VarResolver.create().vars(XVar.class).build().createSession();
 
 	//-----------------------------------------------------------------------------------------------------------------
 	// Basic tests
 	//-----------------------------------------------------------------------------------------------------------------
 
 	@SoapXmlConfig(
-		soapAction="$foo"
+		soapAction="$X{foo}"
 	)
 	static class A {}
 	static ClassInfo a = ClassInfo.of(A.class);
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/uon/UonConfigAnnotationTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/uon/UonConfigAnnotationTest.java
index 16e9f6c..43f449f 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/uon/UonConfigAnnotationTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/uon/UonConfigAnnotationTest.java
@@ -16,9 +16,10 @@ import static org.junit.Assert.*;
 
 import java.util.function.*;
 
+import org.apache.juneau.*;
 import org.apache.juneau.reflect.*;
+import org.apache.juneau.svl.*;
 import org.apache.juneau.uon.annotation.*;
-import org.apache.juneau.utils.*;
 import org.junit.*;
 
 /**
@@ -37,25 +38,18 @@ public class UonConfigAnnotationTest {
 		}
 	};
 
-	static StringResolver sr = new StringResolver() {
-		@Override
-		public String resolve(String input) {
-			if (input.startsWith("$"))
-				input = input.substring(1);
-			return input;
-		}
-	};
+	static VarResolverSession sr = VarResolver.create().vars(XVar.class).build().createSession();
 
 	//-----------------------------------------------------------------------------------------------------------------
 	// Basic tests
 	//-----------------------------------------------------------------------------------------------------------------
 
 	@UonConfig(
-		addBeanTypes="$true",
-		decoding="$true",
-		encoding="$true",
-		paramFormat="$UON",
-		validateEnd="$true"
+		addBeanTypes="$X{true}",
+		decoding="$X{true}",
+		encoding="$X{true}",
+		paramFormat="$X{UON}",
+		validateEnd="$X{true}"
 	)
 	static class A {}
 	static ClassInfo a = ClassInfo.of(A.class);
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/UrlEncodingConfigAnnotationTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/UrlEncodingConfigAnnotationTest.java
index 39ab201..306baad 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/UrlEncodingConfigAnnotationTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/UrlEncodingConfigAnnotationTest.java
@@ -16,9 +16,10 @@ import static org.junit.Assert.*;
 
 import java.util.function.*;
 
+import org.apache.juneau.*;
 import org.apache.juneau.reflect.*;
+import org.apache.juneau.svl.*;
 import org.apache.juneau.urlencoding.annotation.*;
-import org.apache.juneau.utils.*;
 import org.junit.*;
 
 /**
@@ -37,21 +38,14 @@ public class UrlEncodingConfigAnnotationTest {
 		}
 	};
 
-	static StringResolver sr = new StringResolver() {
-		@Override
-		public String resolve(String input) {
-			if (input.startsWith("$"))
-				input = input.substring(1);
-			return input;
-		}
-	};
+	static VarResolverSession sr = VarResolver.create().vars(XVar.class).build().createSession();
 
 	//-----------------------------------------------------------------------------------------------------------------
 	// Basic tests
 	//-----------------------------------------------------------------------------------------------------------------
 
 	@UrlEncodingConfig(
-		expandedParams="$true"
+		expandedParams="$X{true}"
 	)
 	static class A {}
 	static ClassInfo a = ClassInfo.of(A.class);
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/xml/XmlConfigAnnotationTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/xml/XmlConfigAnnotationTest.java
index 9f90283..0975e6c 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/xml/XmlConfigAnnotationTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/xml/XmlConfigAnnotationTest.java
@@ -20,9 +20,10 @@ import javax.xml.stream.*;
 import javax.xml.stream.events.*;
 import javax.xml.stream.util.*;
 
+import org.apache.juneau.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.reflect.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 import org.apache.juneau.xml.annotation.*;
 import org.junit.*;
 
@@ -52,14 +53,7 @@ public class XmlConfigAnnotationTest {
 		}
 	};
 
-	static StringResolver sr = new StringResolver() {
-		@Override
-		public String resolve(String input) {
-			if (input.startsWith("$"))
-				input = input.substring(1);
-			return input;
-		}
-	};
+	static VarResolverSession sr = VarResolver.create().vars(XVar.class).build().createSession();
 
 	//-----------------------------------------------------------------------------------------------------------------
 	// Basic tests
@@ -91,18 +85,18 @@ public class XmlConfigAnnotationTest {
 	}
 
 	@XmlConfig(
-		addBeanTypes="$true",
-		addNamespaceUrisToRoot="$true",
-		autoDetectNamespaces="$true",
-		defaultNamespace="$foo",
-		enableNamespaces="$true",
+		addBeanTypes="$X{true}",
+		addNamespaceUrisToRoot="$X{true}",
+		autoDetectNamespaces="$X{true}",
+		defaultNamespace="$X{foo}",
+		enableNamespaces="$X{true}",
 		eventAllocator=AA.class,
-		namespaces="$foo",
-		preserveRootElement="$true",
+		namespaces="$X{foo}",
+		preserveRootElement="$X{true}",
 		reporter=AB.class,
 		resolver=AC.class,
-		validating="$true",
-		xsNamespace="$foo"
+		validating="$X{true}",
+		xsNamespace="$X{foo}"
 	)
 	static class A {}
 	static ClassInfo a = ClassInfo.of(A.class);
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/xml/XmlContentTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/xml/XmlContentTest.java
index d727635..6a0cb0e 100755
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/xml/XmlContentTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/xml/XmlContentTest.java
@@ -44,7 +44,7 @@ public class XmlContentTest {
 		t.f2 = null;
 
 		sw = new StringWriter();
-		session = s1.createSession(new SerializerSessionArgs(null, null, null, null, null, null, null, null, null));
+		session = s1.createSession(new SerializerSessionArgs(null, null, null, null, null, null, null, null, null, null));
 		session.serialize(t, sw);
 		r = sw.toString();
 		assertEquals("<A f1='f1'>_x0000_</A>", r);
@@ -52,7 +52,7 @@ public class XmlContentTest {
 		assertEqualObjects(t, t2);
 
 		sw = new StringWriter();
-		session = s2.createSession(new SerializerSessionArgs(null, null, null, null, null, null, null, null, null));
+		session = s2.createSession(new SerializerSessionArgs(null, null, null, null, null, null, null, null, null, null));
 		session.serialize(t, sw);
 		r = sw.toString();
 		assertEquals("<A f1='f1'>_x0000_</A>\n", r);
@@ -152,7 +152,7 @@ public class XmlContentTest {
 		t.f2 = null;
 
 		sw = new StringWriter();
-		session = s1.createSession(new SerializerSessionArgs(null, null, null, null, null, null, null, null, null));
+		session = s1.createSession(new SerializerSessionArgs(null, null, null, null, null, null, null, null, null, null));
 		session.serialize(t, sw);
 		r = sw.toString();
 		assertEquals("<A f1='f1'>_x0000_</A>", r);
@@ -160,7 +160,7 @@ public class XmlContentTest {
 		assertEqualObjects(t, t2);
 
 		sw = new StringWriter();
-		session = s2.createSession(new SerializerSessionArgs(null, null, null, null, null, null, null, null, null));
+		session = s2.createSession(new SerializerSessionArgs(null, null, null, null, null, null, null, null, null, null));
 		session.serialize(t, sw);
 		r = sw.toString();
 		assertEquals("<A f1='f1'>_x0000_</A>\n", r);
diff --git a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfParserBuilder.java b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfParserBuilder.java
index 1e5d26a..5f5ebdc 100644
--- a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfParserBuilder.java
+++ b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfParserBuilder.java
@@ -21,7 +21,7 @@ import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.reflect.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 import org.apache.juneau.xml.*;
 
 /**
@@ -1261,7 +1261,7 @@ public class RdfParserBuilder extends ReaderParserBuilder {
 	}
 
 	@Override
-	public RdfParserBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public RdfParserBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerBuilder.java b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerBuilder.java
index 32fed99..1d68f71 100644
--- a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerBuilder.java
+++ b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerBuilder.java
@@ -22,7 +22,7 @@ import org.apache.juneau.http.*;
 import org.apache.juneau.jena.annotation.*;
 import org.apache.juneau.reflect.*;
 import org.apache.juneau.serializer.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 import org.apache.juneau.xml.*;
 import org.apache.juneau.xml.annotation.*;
 
@@ -1497,7 +1497,7 @@ public class RdfSerializerBuilder extends WriterSerializerBuilder {
 	}
 
 	@Override
-	public RdfSerializerBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public RdfSerializerBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/annotation/RdfConfigApply.java b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/annotation/RdfConfigApply.java
index c44ba5d..676242e 100644
--- a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/annotation/RdfConfigApply.java
+++ b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/annotation/RdfConfigApply.java
@@ -17,7 +17,7 @@ import static org.apache.juneau.jena.RdfSerializer.*;
 import static org.apache.juneau.jena.RdfParser.*;
 
 import org.apache.juneau.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Applies {@link RdfConfig} annotations to a {@link PropertyStoreBuilder}.
@@ -30,7 +30,7 @@ public class RdfConfigApply extends ConfigApply<RdfConfig> {
 	 * @param c The annotation class.
 	 * @param r The resolver for resolving values in annotations.
 	 */
-	public RdfConfigApply(Class<RdfConfig> c, StringResolver r) {
+	public RdfConfigApply(Class<RdfConfig> c, VarResolverSession r) {
 		super(c, r);
 	}
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContextBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContextBuilder.java
index 70ac369..343fe47 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContextBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContextBuilder.java
@@ -25,8 +25,8 @@ import org.apache.juneau.marshall.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.reflect.*;
 import org.apache.juneau.serializer.*;
+import org.apache.juneau.svl.*;
 import org.apache.juneau.transform.*;
-import org.apache.juneau.utils.*;
 
 /**
  * Builder class for building instances of serializers, parsers, and bean contexts.
@@ -1705,9 +1705,9 @@ public class BeanContextBuilder extends ContextBuilder {
 		super.apply(copyFrom);
 		return this;
 	}
-	
+
 	@Override
-	public BeanContextBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public BeanContextBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMap.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMap.java
index 13cce3b..17fb7f7 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMap.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMap.java
@@ -78,6 +78,17 @@ public class BeanMap<T> extends AbstractMap<String,Object> implements Delegate<T
 	private final String beanTypePropertyName;
 
 	/**
+	 * Convenience method for wrapping a bean inside a {@link BeanMap}.
+	 *
+	 * @param <T> The bean type.
+	 * @param bean The bean being wrapped.
+	 * @return A new {@link BeanMap} instance wrapping the bean.
+	 */
+	public static <T> BeanMap<T> create(T bean) {
+		return BeanContext.DEFAULT.createBeanSession().toBeanMap(bean);
+	}
+
+	/**
 	 * Instance of this class are instantiated through the BeanContext class.
 	 *
 	 * @param session The bean session object that created this bean map.
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanTraverseBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanTraverseBuilder.java
index fcab304..43d8b9b 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanTraverseBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanTraverseBuilder.java
@@ -18,7 +18,7 @@ import java.util.*;
 
 import org.apache.juneau.http.*;
 import org.apache.juneau.reflect.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Builder class for building instances of bean traversals.
@@ -620,7 +620,7 @@ public class BeanTraverseBuilder extends BeanContextBuilder {
 	}
 
 	@Override
-	public BeanTraverseBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public BeanTraverseBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ConfigApply.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ConfigApply.java
index 0dfc337..facb75a 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ConfigApply.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ConfigApply.java
@@ -18,16 +18,16 @@ import java.lang.annotation.*;
 import java.util.*;
 
 import org.apache.juneau.annotation.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Class used to add properties to a {@link PropertyStore} from an annotation (e.g. {@link BeanConfig}).
- * 
+ *
  * @param <T> The annotation that this <code>ConfigApply</code> reads from.
  */
 public abstract class ConfigApply<T extends Annotation> {
 
-	private final StringResolver r;
+	private final VarResolverSession r;
 	private final Class<T> c;
 
 	/**
@@ -36,8 +36,8 @@ public abstract class ConfigApply<T extends Annotation> {
 	 * @param c The annotation class.
 	 * @param r The string resolver to use for resolving strings.
 	 */
-	protected ConfigApply(Class<T> c, StringResolver r) {
-		this.r = r == null ? StringResolver.NOOP : r;
+	protected ConfigApply(Class<T> c, VarResolverSession r) {
+		this.r = r == null ? VarResolver.DEFAULT.createSession() : r;
 		this.c = c;
 	}
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextBuilder.java
index dfd990a..57c0e86 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextBuilder.java
@@ -15,7 +15,7 @@ package org.apache.juneau;
 import java.util.*;
 
 import org.apache.juneau.reflect.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Builder class for building instances of serializers and parsers.
@@ -95,7 +95,7 @@ public abstract class ContextBuilder {
 	 * @param r The string resolver for resolving variables in annotation values.
 	 * @return This object (for method chaining).
 	 */
-	public ContextBuilder applyAnnotations(AnnotationsMap annotationsMap, StringResolver r) {
+	public ContextBuilder applyAnnotations(AnnotationsMap annotationsMap, VarResolverSession r) {
 		this.psb.applyAnnotations(annotationsMap, r);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/PropertyStoreBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/PropertyStoreBuilder.java
index 301ff64..8eeeec2 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/PropertyStoreBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/PropertyStoreBuilder.java
@@ -24,8 +24,9 @@ import org.apache.juneau.PropertyStore.*;
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.json.*;
+import org.apache.juneau.marshall.*;
 import org.apache.juneau.reflect.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * A builder for {@link PropertyStore} objects.
@@ -107,13 +108,13 @@ public class PropertyStoreBuilder {
 	 * @param r The string resolver used to resolve any variables in the annotations.
 	 * @return This object (for method chaining).
 	 */
-	public PropertyStoreBuilder applyAnnotations(AnnotationsMap annotationsMap, StringResolver r) {
+	public PropertyStoreBuilder applyAnnotations(AnnotationsMap annotationsMap, VarResolverSession r) {
 		for (Map.Entry<Class<? extends Annotation>,List<Annotation>> e : annotationsMap.entrySet()) {
 			Class<? extends Annotation> ac = e.getKey();
 			PropertyStoreApply apply = ac.getAnnotation(PropertyStoreApply.class);
 			if (apply != null) {
 				try {
-					ConfigApply<Annotation> ca = apply.value().getConstructor(Class.class, StringResolver.class).newInstance(ac, r);
+					ConfigApply<Annotation> ca = apply.value().getConstructor(Class.class, VarResolverSession.class).newInstance(ac, r);
 					for (Annotation a : e.getValue()) {
 						ca.apply(a, this);
 					}
@@ -349,6 +350,21 @@ public class PropertyStoreBuilder {
 	}
 
 	/**
+	 * Same as {@link #peek(String)} but converts the value to the specified type.
+	 *
+	 * @param <T> The type to convert to.
+	 * @param c The type to convert to.
+	 * @param key The property key.
+	 * @return The property value, or <jk>null</jk> if it doesn't exist.
+	 */
+	public <T> T peek(Class<T> c, String key)  {
+		Object o = peek(key);
+		if (o == null)
+			return null;
+		return BeanContext.DEFAULT.createBeanSession().convertToType(o, c);
+	}
+
+	/**
 	 * Clears all entries in this property store.
 	 */
 	public synchronized void clear() {
@@ -437,6 +453,16 @@ public class PropertyStoreBuilder {
 		synchronized PropertyGroup build() {
 			return new PropertyGroup(properties);
 		}
+
+		/**
+		 * Used by the <code>toString()</code> method for debugging.
+		 *
+		 * @param bs The bean session.
+		 * @return This object converted to a map.
+		 */
+		public Map<String,MutableProperty> swap(BeanSession bs) {
+			return properties;
+		}
 	}
 
 	//-------------------------------------------------------------------------------------------------------------------
@@ -506,6 +532,11 @@ public class PropertyStoreBuilder {
 		Object convert(Object value) {
 			return value == null ? null : type.converter.convert(value);
 		}
+
+		@Override /* Object */
+		public String toString() {
+			return StringUtils.stringify(peek());
+		}
 	}
 
 	//-------------------------------------------------------------------------------------------------------------------
@@ -906,4 +937,9 @@ public class PropertyStoreBuilder {
 		}
 		return false;
 	}
+
+	@Override /* Object */
+	public String toString() {
+		return SimpleJson.DEFAULT_READABLE.toString(groups);
+	}
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeanConfigApply.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeanConfigApply.java
index 4670a52..bb28970 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeanConfigApply.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeanConfigApply.java
@@ -21,7 +21,7 @@ import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.marshall.*;
 import org.apache.juneau.parser.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Applies {@link BeanConfig} annotations to a {@link PropertyStoreBuilder}.
@@ -34,7 +34,7 @@ public class BeanConfigApply extends ConfigApply<BeanConfig> {
 	 * @param c The annotation class.
 	 * @param r The resolver for resolving values in annotations.
 	 */
-	public BeanConfigApply(Class<BeanConfig> c, StringResolver r) {
+	public BeanConfigApply(Class<BeanConfig> c, VarResolverSession r) {
 		super(c, r);
 	}
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvParserBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvParserBuilder.java
index c7b0bc4..f179d6d 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvParserBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvParserBuilder.java
@@ -18,7 +18,7 @@ import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.reflect.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Builder class for building instances of CSV parsers.
@@ -565,9 +565,9 @@ public class CsvParserBuilder extends ReaderParserBuilder {
 		super.apply(copyFrom);
 		return this;
 	}
-	
+
 	@Override
-	public CsvParserBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public CsvParserBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java
index a31d2e7..580b972 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java
@@ -18,7 +18,7 @@ import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.reflect.*;
 import org.apache.juneau.serializer.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Builder class for building instances of CSV serializers.
@@ -678,9 +678,9 @@ public class CsvSerializerBuilder extends WriterSerializerBuilder {
 		super.apply(copyFrom);
 		return this;
 	}
-	
+
 	@Override
-	public CsvSerializerBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public CsvSerializerBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/annotation/CsvConfigApply.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/annotation/CsvConfigApply.java
index f2ccaac..e76d116 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/annotation/CsvConfigApply.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/annotation/CsvConfigApply.java
@@ -13,7 +13,7 @@
 package org.apache.juneau.csv.annotation;
 
 import org.apache.juneau.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Applies {@link CsvConfig} annotations to a {@link PropertyStoreBuilder}.
@@ -26,7 +26,7 @@ public class CsvConfigApply extends ConfigApply<CsvConfig> {
 	 * @param c The annotation class.
 	 * @param r The resolver for resolving values in annotations.
 	 */
-	public CsvConfigApply(Class<CsvConfig> c, StringResolver r) {
+	public CsvConfigApply(Class<CsvConfig> c, VarResolverSession r) {
 		super(c, r);
 	}
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/BasicHtmlDocTemplate.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/BasicHtmlDocTemplate.java
index 8e989e8..40faf9c 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/BasicHtmlDocTemplate.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/BasicHtmlDocTemplate.java
@@ -46,7 +46,7 @@ public class BasicHtmlDocTemplate implements HtmlDocTemplate {
 
 		String[] head = session.getHead();
 		for (int i = 0; i < head.length; i++)
-			w.sIf(i > 0).appendln(2, head[i]);
+			w.sIf(i > 0).appendln(2, session.resolve(head[i]));
 
 		if (hasStyle(session)) {
 			w.sTag(2, "style").nl(2);
@@ -69,16 +69,15 @@ public class BasicHtmlDocTemplate implements HtmlDocTemplate {
 	 * @throws Exception Any exception can be thrown.
 	 */
 	protected void style(HtmlDocSerializerSession session, HtmlWriter w, Object o) throws Exception {
-
 		int i = 0;
 		for (String s : session.getStylesheet())
-			w.sIf(i++ > 0).append(3, "@import ").q().append(session.resolveUri(s)).q().appendln(";");
-
+			w.sIf(i++ > 0).append(3, "@import ").q().append(session.resolveUri(session.resolve(s))).q().appendln(";");
 		if (session.isNowrap())
 			w.appendln(3, "div.data * {white-space:nowrap;} ");
-
 		for (String s : session.getStyle())
-			w.sIf(i > 0).appendln(3, s);
+			w.sIf(i++ > 0).appendln(3, session.resolve(s));
+		for (HtmlWidget hw : session.getWidgets())
+			w.sIf(i++ > 0).appendln(3, session.resolve(hw.getStyle(session.getVarResolver())));
 	}
 
 	/**
@@ -92,7 +91,9 @@ public class BasicHtmlDocTemplate implements HtmlDocTemplate {
 	protected void script(HtmlDocSerializerSession session, HtmlWriter w, Object o) throws Exception {
 		int i = 0;
 		for (String s : session.getScript())
-			w.sIf(i++ > 0).append(3, s).append('\n'); // Must always append a newline even if whitespace disabled!
+			w.sIf(i++ > 0).append(3, session.resolve(s)).append('\n'); // Must always append a newline even if whitespace disabled!
+		for (HtmlWidget hw : session.getWidgets())
+			w.sIf(i++ > 0).append(3, session.resolve(hw.getScript(session.getVarResolver()))).append('\n'); // Must always append a newline even if whitespace disabled!
 	}
 
 	/**
@@ -150,7 +151,7 @@ public class BasicHtmlDocTemplate implements HtmlDocTemplate {
 		// Write the title of the page.
 		String[] header = session.getHeader();
 		for (int i = 0; i < header.length; i++)
-			w.sIf(i > 0).appendln(3, header[i]);
+			w.sIf(i > 0).appendln(3, session.resolve(header[i]));
 	}
 
 	/**
@@ -167,6 +168,7 @@ public class BasicHtmlDocTemplate implements HtmlDocTemplate {
 			w.sTag(3, "ol").nl(3);
 			for (String l : links) {
 				w.sTag(4, "li");
+				l = session.resolve(l);
 				if (l.matches("(?s)\\S+\\:.*")) {
 					int i = l.indexOf(':');
 					String key = l.substring(0, i);
@@ -186,7 +188,7 @@ public class BasicHtmlDocTemplate implements HtmlDocTemplate {
 		String[] nav = session.getNav();
 		if (nav.length > 0) {
 			for (int i = 0; i < nav.length; i++)
-				w.sIf(i > 0).appendln(3, nav[i]);
+				w.sIf(i > 0).appendln(3, session.resolve(nav[i]));
 		}
 	}
 
@@ -201,7 +203,7 @@ public class BasicHtmlDocTemplate implements HtmlDocTemplate {
 	protected void aside(HtmlDocSerializerSession session, HtmlWriter w, Object o) throws Exception {
 		String[] aside = session.getAside();
 		for (int i = 0; i < aside.length; i++)
-			w.sIf(i > 0).appendln(4, aside[i]);
+			w.sIf(i > 0).appendln(4, session.resolve(aside[i]));
 	}
 
 	/**
@@ -223,7 +225,7 @@ public class BasicHtmlDocTemplate implements HtmlDocTemplate {
 		} else if (ObjectUtils.isEmpty(o)){
 			String m = session.getNoResultsMessage();
 			if (exists(m))
-				w.append(6, m).nl(6);
+				w.append(6, session.resolve(m)).nl(6);
 		} else {
 			session.indent = 6;
 			w.flush();
@@ -245,7 +247,7 @@ public class BasicHtmlDocTemplate implements HtmlDocTemplate {
 	protected void footer(HtmlDocSerializerSession session, HtmlWriter w, Object o) throws Exception {
 		String[] footer = session.getFooter();
 		for (int i = 0; i < footer.length; i++)
-			w.sIf(i > 0).appendln(3, footer[i]);
+			w.sIf(i > 0).appendln(3, session.resolve(footer[i]));
 	}
 
 	/**
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
index b32b36e..2072ba2 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
@@ -12,8 +12,12 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.html;
 
+import java.util.*;
+
 import org.apache.juneau.*;
+import org.apache.juneau.html.annotation.*;
 import org.apache.juneau.serializer.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Serializes POJOs to HTTP responses as HTML documents.
@@ -502,6 +506,74 @@ public class HtmlDocSerializer extends HtmlStrippedDocSerializer {
 	 */
 	public static final String HTMLDOC_template = PREFIX + "template.c";
 
+	/**
+	 * Configuration property:  HTML Widgets.
+	 *
+	 * <h5 class='section'>Property:</h5>
+	 * <ul>
+	 * 	<li><b>Name:</b>  <js>"HtmlDocSerializer.widgets.lo"</js>
+	 * 	<li><b>Data type:</b>  <code>List&lt;{@link HtmlWidget} | Class&lt;? <jk>extends</jk> {@link HtmlWidget}&gt;&gt;</code>
+	 * 	<li><b>Default:</b>  empty list
+	 * 	<li><b>Session property:</b>  <jk>false</jk>
+	 * 	<li><b>Annotations:</b>
+	 * 		<ul>
+	 * 			<li class='ja'>{@link HtmlDocConfig#widgets()}
+	 * 		</ul>
+	 * 	<li><b>Methods:</b>
+	 * 		<ul>
+	 * 			<li class='jm'>{@link HtmlDocSerializerBuilder#widgets(Class...)}
+	 * 			<li class='jm'>{@link HtmlDocSerializerBuilder#widgets(HtmlWidget...)}
+	 * 			<li class='jm'>{@link HtmlDocSerializerBuilder#widgetsReplace(Class...)}
+	 * 			<li class='jm'>{@link HtmlDocSerializerBuilder#widgetsReplace(HtmlWidget...)}
+	 * 		</ul>
+	 * </ul>
+	 *
+	 * <h5 class='section'>Description:</h5>
+	 * <p>
+	 * Defines widgets that can be used in conjunction with string variables of the form <js>"$W{name}"</js>to quickly
+	 * generate arbitrary replacement text.
+	 *
+	 * Widgets resolve the following variables:
+	 * <ul class='spaced-list'>
+	 * 	<li><js>"$W{name}"</js> - Contents returned by {@link HtmlWidget#getHtml(VarResolverSession)}.
+	 * 	<li><js>"$W{name.script}"</js> - Contents returned by {@link HtmlWidget#getScript(VarResolverSession)}.
+	 * 		<br>The script contents are automatically inserted into the <xt>&lt;head/script&gt;</xt> section
+	 * 			 in the HTML page.
+	 * 	<li><js>"$W{name.style}"</js> - Contents returned by {@link HtmlWidget#getStyle(VarResolverSession)}.
+	 * 		<br>The styles contents are automatically inserted into the <xt>&lt;head/style&gt;</xt> section
+	 * 			 in the HTML page.
+	 * </ul>
+	 *
+	 * <p>
+	 * The following examples shows how to associate a widget with a REST method and then have it rendered in the links
+	 * and aside section of the page:
+	 *
+	 * <p class='bcode w800'>
+	 * 	<ja>@HtmlDocSerializer</ja>(
+	 * 		widgets={
+	 * 			MyWidget.<jk>class</jk>
+	 * 		},
+	 * 		navlinks={
+	 * 			<js>"$W{MyWidget}"</js>
+	 * 		},
+	 * 		aside={
+	 * 			<js>"Check out this widget:  $W{MyWidget}"</js>
+	 * 		}
+	 * 	)
+	 * </p>
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		Widgets are inherited from super classes, but can be overridden by reusing the widget name.
+	 * </ul>
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='link'>{@doc juneau-rest-server.HtmlDocAnnotation.Widgets}
+	 * </ul>
+	 */
+	public static final String HTMLDOC_widgets = PREFIX + "widgets.lo";
 
 	//-------------------------------------------------------------------------------------------------------------------
 	// Predefined instances
@@ -519,6 +591,7 @@ public class HtmlDocSerializer extends HtmlStrippedDocSerializer {
 	private final String noResultsMessage;
 	private final boolean nowrap;
 	private final HtmlDocTemplate template;
+	private final Map<String,HtmlWidget> widgets;
 
 	private volatile HtmlSchemaDocSerializer schemaSerializer;
 
@@ -572,6 +645,11 @@ public class HtmlDocSerializer extends HtmlStrippedDocSerializer {
 		navlinks = getArrayProperty(HTMLDOC_navlinks, String.class);
 		noResultsMessage = getStringProperty(HTMLDOC_noResultsMessage, "<p>no results</p>");
 		template = getInstanceProperty(HTMLDOC_template, HtmlDocTemplate.class, BasicHtmlDocTemplate.class);
+
+		Map<String,HtmlWidget> widgets = new HashMap<>();
+		for (HtmlWidget w : getInstanceArrayProperty(HTMLDOC_widgets, HtmlWidget.class, new HtmlWidget[0]))
+			widgets.put(w.getName(), w);
+		this.widgets = Collections.unmodifiableMap(widgets);
 	}
 
 	@Override /* Context */
@@ -748,6 +826,17 @@ public class HtmlDocSerializer extends HtmlStrippedDocSerializer {
 		return template;
 	}
 
+	/**
+	 * Configuration property:  HTML widgets.
+	 *
+	 * @see #HTMLDOC_widgets
+	 * @return
+	 * 	Widgets defined on this serializers.
+	 */
+	protected final Map<String,HtmlWidget> getWidgets() {
+		return widgets;
+	}
+
 	//-----------------------------------------------------------------------------------------------------------------
 	// Other methods
 	//-----------------------------------------------------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerBuilder.java
index f569d60..669dc4e 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerBuilder.java
@@ -20,7 +20,7 @@ import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.reflect.*;
 import org.apache.juneau.serializer.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 import org.apache.juneau.xml.*;
 
 /**
@@ -416,6 +416,81 @@ public class HtmlDocSerializerBuilder extends HtmlStrippedDocSerializerBuilder {
 		return this;
 	}
 
+	/**
+	 * Configuration property:  HTML Widgets.
+	 *
+	 * <p>
+	 * Defines widgets that can be used in conjunction with string variables of the form <js>"$W{name}"</js>to quickly
+	 * generate arbitrary replacement text.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='jf'>{@link HtmlDocSerializer#HTMLDOC_widgets}
+	 * </ul>
+	 *
+	 * @param values The values to add to this setting.
+	 * @return This object (for method chaining).
+	 */
+	@SuppressWarnings("unchecked")
+	public HtmlDocSerializerBuilder widgets(Class<? extends HtmlWidget>...values) {
+		return addTo(HTMLDOC_widgets, values);
+	}
+
+	/**
+	 * Configuration property:  HTML Widgets.
+	 *
+	 * <p>
+	 * Same as {@link #widgets(Class...)} but replaces any previous values.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='jf'>{@link HtmlDocSerializer#HTMLDOC_widgets}
+	 * </ul>
+	 *
+	 * @param values The values to set on this setting.
+	 * @return This object (for method chaining).
+	 */
+	@SuppressWarnings("unchecked")
+	public HtmlDocSerializerBuilder widgetsReplace(Class<? extends HtmlWidget>...values) {
+		return set(HTMLDOC_widgets, values);
+	}
+
+	/**
+	 * Configuration property:  HTML Widgets.
+	 *
+	 * <p>
+	 * Same as {@link #widgets(Class...)} except input is pre-constructed instances.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='jf'>{@link HtmlDocSerializer#HTMLDOC_widgets}
+	 * </ul>
+	 *
+	 * @param values The values to add to this setting.
+	 * @return This object (for method chaining).
+	 */
+	public HtmlDocSerializerBuilder widgets(HtmlWidget...values) {
+		return addTo(HTMLDOC_widgets, values);
+	}
+
+	/**
+	 * Configuration property:  HTML Widgets.
+	 *
+	 * <p>
+	 * Same as {@link #widgets(HtmlWidget...)} except allows you to overwrite the previous value.
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='jf'>{@link HtmlDocSerializer#HTMLDOC_widgets}
+	 * </ul>
+	 *
+	 * @param values The values to add to this setting.
+	 * @return This object (for method chaining).
+	 */
+	public HtmlDocSerializerBuilder widgetsReplace(HtmlWidget...values) {
+		return set(HTMLDOC_widgets, values);
+	}
+
 	@Override /* HtmlSerializerBuilder */
 	public HtmlDocSerializerBuilder addKeyValueTableHeaders(boolean value) {
 		super.addKeyValueTableHeaders(value);
@@ -1128,9 +1203,9 @@ public class HtmlDocSerializerBuilder extends HtmlStrippedDocSerializerBuilder {
 		super.apply(copyFrom);
 		return this;
 	}
-	
+
 	@Override
-	public HtmlDocSerializerBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public HtmlDocSerializerBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
index 8834998..c05035d 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
@@ -18,6 +18,7 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.serializer.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Context object that lives for the duration of a single serialization of {@link HtmlSerializer} and its subclasses.
@@ -30,6 +31,8 @@ import org.apache.juneau.serializer.*;
  */
 public class HtmlDocSerializerSession extends HtmlStrippedDocSerializerSession {
 
+	private static final VarResolver DEFAULT_VR = VarResolver.create().defaultVars().vars(HtmlWidgetVar.class).build();
+
 	private final HtmlDocSerializer ctx;
 	private final String[] navlinks, head, header, nav, aside, footer;
 	private final Set<String> style, stylesheet, script;
@@ -59,6 +62,13 @@ public class HtmlDocSerializerSession extends HtmlStrippedDocSerializerSession {
 		script = new LinkedHashSet<>(Arrays.asList(getProperty(HTMLDOC_script, String[].class, ctx.getScript())));
 
 		head = getProperty(HTMLDOC_head, String[].class, ctx.getHead());
+
+		varSessionObject(HtmlWidgetVar.SESSION_htmlWidgets, ctx.getWidgets());
+	}
+
+	@Override /* SerializerSession */
+	protected VarResolverSession createDefaultVarResolverSession() {
+		return DEFAULT_VR.createSession();
 	}
 
 	@Override /* Session */
@@ -245,4 +255,16 @@ public class HtmlDocSerializerSession extends HtmlStrippedDocSerializerSession {
 	protected final HtmlDocTemplate getTemplate() {
 		return ctx.getTemplate();
 	}
+
+	/**
+	 * Configuration property:  Page navigation links.
+	 *
+	 * @see HtmlDocSerializer#HTMLDOC_navlinks
+	 * @return
+	 * 	Navigation links to add to the HTML page.
+	 */
+	protected final Collection<HtmlWidget> getWidgets() {
+		return ctx.getWidgets().values();
+	}
+
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlParserBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlParserBuilder.java
index 6df038b..660822d 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlParserBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlParserBuilder.java
@@ -21,7 +21,7 @@ import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.reflect.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 import org.apache.juneau.xml.*;
 
 /**
@@ -587,9 +587,9 @@ public class HtmlParserBuilder extends XmlParserBuilder {
 		super.apply(copyFrom);
 		return this;
 	}
-	
+
 	@Override
-	public HtmlParserBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public HtmlParserBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSchemaSerializerBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSchemaSerializerBuilder.java
index 282f34b..bae681a 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSchemaSerializerBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSchemaSerializerBuilder.java
@@ -22,7 +22,7 @@ import org.apache.juneau.http.*;
 import org.apache.juneau.jsonschema.*;
 import org.apache.juneau.reflect.*;
 import org.apache.juneau.serializer.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Builder class for building instances of HTML Schema serializers.
@@ -818,9 +818,9 @@ public class HtmlSchemaSerializerBuilder extends HtmlSerializerBuilder {
 		super.apply(copyFrom);
 		return this;
 	}
-	
+
 	@Override
-	public HtmlSchemaSerializerBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public HtmlSchemaSerializerBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializerBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializerBuilder.java
index 9548019..9dc6df6 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializerBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializerBuilder.java
@@ -20,7 +20,7 @@ import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.reflect.*;
 import org.apache.juneau.serializer.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 import org.apache.juneau.xml.*;
 
 /**
@@ -859,9 +859,9 @@ public class HtmlSerializerBuilder extends XmlSerializerBuilder {
 		super.apply(copyFrom);
 		return this;
 	}
-	
+
 	@Override
-	public HtmlSerializerBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public HtmlSerializerBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlStrippedDocSerializerBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlStrippedDocSerializerBuilder.java
index 1e25303..e73a72d 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlStrippedDocSerializerBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlStrippedDocSerializerBuilder.java
@@ -18,7 +18,7 @@ import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.reflect.*;
 import org.apache.juneau.serializer.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 import org.apache.juneau.xml.*;
 
 /**
@@ -763,9 +763,9 @@ public class HtmlStrippedDocSerializerBuilder extends HtmlSerializerBuilder {
 		super.apply(copyFrom);
 		return this;
 	}
-	
+
 	@Override
-	public HtmlStrippedDocSerializerBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public HtmlStrippedDocSerializerBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlWidget.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlWidget.java
new file mode 100644
index 0000000..da854f6
--- /dev/null
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlWidget.java
@@ -0,0 +1,78 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.html;
+
+import org.apache.juneau.svl.*;
+
+/**
+ * Defines an interface for resolvers of <js>"$W{...}"</js> string variables.
+ *
+ * <p>
+ * Widgets must provide one of the following public constructors:
+ * <ul>
+ * 	<li><code><jk>public</jk> Widget();</code>
+ * </ul>
+ *
+ * <p>
+ * Widgets can be defined as inner classes of REST resource classes.
+ *
+ * <h5 class='section'>See Also:</h5>
+ * <ul>
+ * 	<li class='link'>{@doc juneau-rest-server.HtmlDocAnnotation.Widgets}
+ * </ul>
+ */
+public interface HtmlWidget {
+
+	/**
+	 * The name for this widget.
+	 *
+	 * @return A unique identifying name for this widget.
+	 */
+	public String getName();
+
+	/**
+	 * Resolves the HTML content for this widget.
+	 *
+	 * <p>
+	 * A returned value of <jk>null</jk> will cause nothing to be added to the page.
+	 *
+	 * @param session The current serializer session.
+	 * @return The HTML content of this widget.
+	 * @throws Exception
+	 */
+	public String getHtml(VarResolverSession session) throws Exception;
+
+	/**
+	 * Resolves any Javascript that should be added to the <xt>&lt;head&gt;/&lt;script&gt;</xt> element.
+	 *
+	 * <p>
+	 * A returned value of <jk>null</jk> will cause nothing to be added to the page.
+	 *
+	 * @param session The current serializer session.
+	 * @return The Javascript needed by this widget.
+	 * @throws Exception
+	 */
+	public String getScript(VarResolverSession session) throws Exception;
+
+	/**
+	 * Resolves any CSS styles that should be added to the <xt>&lt;head&gt;/&lt;style&gt;</xt> element.
+	 *
+	 * <p>
+	 * A returned value of <jk>null</jk> will cause nothing to be added to the page.
+	 *
+	 * @param session The current serializer session.
+	 * @return The CSS styles needed by this widget.
+	 * @throws Exception
+	 */
+	public String getStyle(VarResolverSession session) throws Exception;
+}
diff --git a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/UpperCaseVar.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlWidgetVar.java
similarity index 58%
copy from juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/UpperCaseVar.java
copy to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlWidgetVar.java
index 69f1b79..12c7383 100644
--- a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/UpperCaseVar.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlWidgetVar.java
@@ -10,42 +10,66 @@
 // * "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.svl.vars;
+package org.apache.juneau.html;
 
+import java.util.*;
+
+import org.apache.juneau.html.annotation.*;
 import org.apache.juneau.svl.*;
 
 /**
- * Upper-case variable resolver.
+ * HTML widget variable resolver.
  *
  * <p>
- * The format for this var is <js>"$UC{stringValue}"</js>.
+ * The format for this var is <js>"$W{widgetName}"</js>.
  *
  * <p>
- * This variable simply converts to value to upper-case.
+ * Widgets are simple class that produce some sort of string based on a passed-in HTTP request.
  *
  * <p>
- * Since this is a {@link SimpleVar}, any variables contained in the result will be recursively resolved.
- * Likewise, if the arguments contain any variables, those will be resolved before they are passed to this var.
+ * They're registered via the following mechanisms:
+ * <ul>
+ * 	<li>{@link HtmlDocConfig#widgets() @HtmlDocConfig(widgets)}
+ * </ul>
  *
  * <h5 class='section'>See Also:</h5>
  * <ul>
  * 	<li class='link'>{@doc juneau-rest-server.SvlVariables}
  * </ul>
  */
-public class UpperCaseVar extends SimpleVar {
+public class HtmlWidgetVar extends SimpleVar {
+
+	/**
+	 * The name of the session or context object that identifies the object containing the widgets to resolve.
+	 */
+	public static final String SESSION_htmlWidgets = "htmlWidgets";
 
-	/** The name of this variable. */
-	public static final String NAME = "UC";
+	/**
+	 * The name of this variable.
+	 */
+	public static final String NAME = "W";
 
 	/**
 	 * Constructor.
 	 */
-	public UpperCaseVar() {
+	public HtmlWidgetVar() {
 		super(NAME);
 	}
 
+	@SuppressWarnings("unchecked")
 	@Override /* Parameter */
-	public String resolve(VarResolverSession session, String key) {
-		return key.toUpperCase();
+	public String resolve(VarResolverSession session, String key) throws Exception {
+		Map<String,HtmlWidget> widgets = (Map<String,HtmlWidget>)session.getSessionObject(Object.class, SESSION_htmlWidgets, false);
+
+		HtmlWidget w = widgets.get(key);
+		if (w == null)
+			return "unknown-widget-"+key;
+
+		return w.getHtml(session);
+	}
+
+	@Override
+	public boolean canResolve(VarResolverSession session) {
+		return session.getSessionObject(Object.class, SESSION_htmlWidgets, false) != null;
 	}
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlConfigApply.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlConfigApply.java
index 099e640..9a58bef 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlConfigApply.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlConfigApply.java
@@ -14,7 +14,7 @@ package org.apache.juneau.html.annotation;
 
 import static org.apache.juneau.html.HtmlSerializer.*;
 import org.apache.juneau.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Applies {@link HtmlConfig} annotations to a {@link PropertyStoreBuilder}.
@@ -27,7 +27,7 @@ public class HtmlConfigApply extends ConfigApply<HtmlConfig> {
 	 * @param c The annotation class.
 	 * @param r The resolver for resolving values in annotations.
 	 */
-	public HtmlConfigApply(Class<HtmlConfig> c, StringResolver r) {
+	public HtmlConfigApply(Class<HtmlConfig> c, VarResolverSession r) {
 		super(c, r);
 	}
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlDocConfig.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlDocConfig.java
index eb4b6bc..6a5594f 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlDocConfig.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlDocConfig.java
@@ -22,6 +22,7 @@ import java.lang.annotation.*;
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.html.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Annotation for specifying config properties defined in {@link HtmlSerializer}, {@link HtmlParser}, and {@link HtmlDocSerializer}.
@@ -211,16 +212,6 @@ public @interface HtmlDocConfig {
 	String[] navlinks() default {};
 
 	/**
-	 * Configuration property:  Add to the {@link #HTMLDOC_navlinks} property.
-	 *
-	 * <h5 class='section'>See Also:</h5>
-	 * <ul>
-	 * 	<li class='jf'>{@link HtmlDocSerializer#HTMLDOC_navlinks}
-	 * </ul>
-	 */
-	String[] navlinks_replace() default {};
-
-	/**
 	 * Configuration property:  No-results message.
 	 *
 	 * <p>
@@ -285,16 +276,6 @@ public @interface HtmlDocConfig {
 	String[] script() default {};
 
 	/**
-	 * Configuration property:  Add to the {@link #HTMLDOC_script} property.
-	 *
-	 * <h5 class='section'>See Also:</h5>
-	 * <ul>
-	 * 	<li class='jf'>{@link HtmlDocSerializer#HTMLDOC_script}
-	 * </ul>
-	 */
-	String[] script_replace() default {};
-
-	/**
 	 * Configuration property:  CSS style code.
 	 *
 	 * <p>
@@ -317,16 +298,6 @@ public @interface HtmlDocConfig {
 	String[] style() default {};
 
 	/**
-	 * Configuration property:  Add to the {@link #HTMLDOC_style} property.
-	 *
-	 * <h5 class='section'>See Also:</h5>
-	 * <ul>
-	 * 	<li class='jf'>{@link HtmlDocSerializer#HTMLDOC_style}
-	 * </ul>
-	 */
-	String[] style_replace() default {};
-
-	/**
 	 * Configuration property:  Stylesheet import URLs.
 	 *
 	 * <p>
@@ -343,16 +314,6 @@ public @interface HtmlDocConfig {
 	String[] stylesheet() default {};
 
 	/**
-	 * Configuration property:  Add to the {@link #HTMLDOC_stylesheet} property.
-	 *
-	 * <h5 class='section'>See Also:</h5>
-	 * <ul>
-	 * 	<li class='jf'>{@link HtmlDocSerializer#HTMLDOC_stylesheet}
-	 * </ul>
-	 */
-	String[] stylesheet_replace() default {};
-
-	/**
 	 * Configuration property:  HTML document template.
 	 *
 	 * <p>
@@ -375,4 +336,52 @@ public @interface HtmlDocConfig {
 	 * </ul>
 	 */
 	Class<? extends HtmlDocTemplate> template() default HtmlDocTemplate.Null.class;
+
+	/**
+	 * Configuration property:  HTML Widgets.
+	 *
+	 * <p>
+	 * Defines widgets that can be used in conjunction with string variables of the form <js>"$W{name}"</js>to quickly
+	 * generate arbitrary replacement text.
+	 *
+	 * <p>
+	 * Widgets resolve the following variables:
+	 *
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		<js>"$W{name}"</js> - Contents returned by {@link HtmlWidget#getHtml(VarResolverSession)}.
+	 * </ul>
+	 *
+	 * <p>
+	 * The following examples shows how to associate a widget with a REST method and then have it rendered in the links
+	 * and aside section of the page:
+	 *
+	 * <p class='bcode w800'>
+	 * 	<ja>@HtmlDocConfig</ja>(
+	 * 		widgets={
+	 * 			MyWidget.<jk>class</jk>
+	 * 		}
+	 * 		navlinks={
+	 * 			<js>"$W{MyWidget}"</js>
+	 * 		},
+	 * 		aside={
+	 * 			<js>"Check out this widget:  $W{MyWidget}"</js>
+	 * 		}
+	 * 	)
+	 * </p>
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		Widgets are inherited from parent to child, but can be overridden by reusing the widget name.
+	 * 	<li>
+	 * 		Values are appended to the existing list.
+	 * </ul>
+	 *
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='link'>{@doc juneau-rest-server.HtmlDocAnnotation.Widgets}
+	 * </ul>
+	 */
+	Class<? extends HtmlWidget>[] widgets() default {};
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlDocConfigApply.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlDocConfigApply.java
index 33ffc2a..c2264e1 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlDocConfigApply.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlDocConfigApply.java
@@ -13,9 +13,14 @@
 package org.apache.juneau.html.annotation;
 
 import static org.apache.juneau.html.HtmlDocSerializer.*;
+import static org.apache.juneau.internal.StringUtils.*;
+
+import java.util.*;
+import java.util.regex.*;
+
 import org.apache.juneau.*;
 import org.apache.juneau.html.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Applies {@link HtmlDocConfig} annotations to a {@link PropertyStoreBuilder}.
@@ -28,43 +33,81 @@ public class HtmlDocConfigApply extends ConfigApply<HtmlDocConfig> {
 	 * @param c The annotation class.
 	 * @param r The resolver for resolving values in annotations.
 	 */
-	public HtmlDocConfigApply(Class<HtmlDocConfig> c, StringResolver r) {
+	public HtmlDocConfigApply(Class<HtmlDocConfig> c, VarResolverSession r) {
 		super(c, r);
 	}
 
 	@Override
 	public void apply(HtmlDocConfig a, PropertyStoreBuilder psb) {
 		if (a.aside().length > 0)
-			psb.set(HTMLDOC_aside, strings(a.aside()));
+			psb.set(HTMLDOC_aside, resolveList(a.aside(), psb.peek(String[].class, HTMLDOC_aside)));
 		if (a.footer().length > 0)
-			psb.set(HTMLDOC_footer, strings(a.footer()));
+			psb.set(HTMLDOC_footer, resolveList(a.footer(), psb.peek(String[].class, HTMLDOC_footer)));
 		if (a.head().length > 0)
-			psb.set(HTMLDOC_head, strings(a.head()));
+			psb.set(HTMLDOC_head, resolveList(a.head(), psb.peek(String[].class, HTMLDOC_head)));
 		if (a.header().length > 0)
-			psb.set(HTMLDOC_header, strings(a.header()));
+			psb.set(HTMLDOC_header, resolveList(a.header(), psb.peek(String[].class, HTMLDOC_header)));
 		if (a.nav().length > 0)
-			psb.set(HTMLDOC_nav, strings(a.nav()));
+			psb.set(HTMLDOC_nav, resolveList(a.nav(), psb.peek(String[].class, HTMLDOC_nav)));
 		if (a.navlinks().length > 0)
-			psb.addTo(HTMLDOC_navlinks, strings(a.navlinks()));
-		if (a.navlinks_replace().length > 0)
-			psb.set(HTMLDOC_navlinks, strings(a.navlinks_replace()));
+			psb.set(HTMLDOC_navlinks, resolveLinks(a.navlinks(), psb.peek(String[].class, HTMLDOC_navlinks)));
 		if (! a.noResultsMessage().isEmpty())
 			psb.set(HTMLDOC_noResultsMessage, string(a.noResultsMessage()));
 		if (! a.nowrap().isEmpty())
 			psb.set(HTMLDOC_nowrap, bool(a.nowrap()));
 		if (a.script().length > 0)
-			psb.addTo(HTMLDOC_script, strings(a.script()));
-		if (a.script_replace().length > 0)
-			psb.set(HTMLDOC_script, strings(a.script_replace()));
+			psb.set(HTMLDOC_script, resolveList(a.script(), psb.peek(String[].class, HTMLDOC_script)));
 		if (a.style().length > 0)
-			psb.addTo(HTMLDOC_style, strings(a.style()));
-		if (a.style_replace().length > 0)
-			psb.set(HTMLDOC_style, strings(a.style_replace()));
+			psb.set(HTMLDOC_style, resolveList(a.style(), psb.peek(String[].class, HTMLDOC_style)));
 		if (a.stylesheet().length > 0)
-			psb.addTo(HTMLDOC_stylesheet, strings(a.stylesheet()));
-		if (a.stylesheet_replace().length > 0)
-			psb.set(HTMLDOC_stylesheet, strings(a.stylesheet_replace()));
+			psb.set(HTMLDOC_stylesheet, resolveList(a.stylesheet(), psb.peek(String[].class, HTMLDOC_stylesheet)));
 		if (a.template() != HtmlDocTemplate.Null.class)
 			psb.set(HTMLDOC_template, a.template());
+		for (Class<? extends HtmlWidget> w : a.widgets()) {
+			try {
+				psb.addTo(HTMLDOC_widgets, w.newInstance());
+			} catch (Exception e) {
+				e.printStackTrace();
+			}
+		}
+	}
+
+	private static final Pattern INDEXED_LINK_PATTERN = Pattern.compile("(?s)(\\S*)\\[(\\d+)\\]\\:(.*)");
+
+	private String[] resolveLinks(Object[] value, String[] prev) {
+		List<String> list = new ArrayList<>();
+		for (Object v : value) {
+			String s = string(stringify(v));
+			if ("INHERIT".equals(s)) {
+				if (prev != null)
+					list.addAll(Arrays.asList(prev));
+			} else if (s.indexOf('[') != -1 && INDEXED_LINK_PATTERN.matcher(s).matches()) {
+				Matcher lm = INDEXED_LINK_PATTERN.matcher(s);
+				lm.matches();
+				String key = lm.group(1);
+				int index = Math.min(list.size(), Integer.parseInt(lm.group(2)));
+				String remainder = lm.group(3);
+				list.add(index, key.isEmpty() ? remainder : key + ":" + remainder);
+			} else {
+				list.add(s);
+			}
+		}
+		return list.toArray(new String[list.size()]);
+	}
+
+	private String[] resolveList(Object[] value, String[] prev) {
+		Set<String> set = new LinkedHashSet<>();
+		for (Object v : value) {
+			String s = string(stringify(v));
+			if ("INHERIT".equals(s)) {
+				if (prev != null)
+					set.addAll(Arrays.asList(prev));
+			} else if ("NONE".equals(s)) {
+				return new String[0];
+			} else {
+				set.add(s);
+			}
+		}
+		return set.toArray(new String[set.size()]);
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jso/JsoParserBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jso/JsoParserBuilder.java
index 46b7e5b..6193f10 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jso/JsoParserBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jso/JsoParserBuilder.java
@@ -18,7 +18,7 @@ import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.reflect.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Builder class for building instances of Java Serialized Object parsers.
@@ -559,9 +559,9 @@ public class JsoParserBuilder extends InputStreamParserBuilder {
 		super.apply(copyFrom);
 		return this;
 	}
-	
+
 	@Override
-	public JsoParserBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public JsoParserBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jso/JsoSerializerBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jso/JsoSerializerBuilder.java
index 6e4148e..8228059 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jso/JsoSerializerBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jso/JsoSerializerBuilder.java
@@ -18,7 +18,7 @@ import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.reflect.*;
 import org.apache.juneau.serializer.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Builder class for building instances of Java Serialized Object serializers.
@@ -648,9 +648,9 @@ public class JsoSerializerBuilder extends OutputStreamSerializerBuilder {
 		super.apply(copyFrom);
 		return this;
 	}
-	
+
 	@Override
-	public JsoSerializerBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public JsoSerializerBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jso/annotation/JsoConfigApply.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jso/annotation/JsoConfigApply.java
index 12b5233..f39878b 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jso/annotation/JsoConfigApply.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jso/annotation/JsoConfigApply.java
@@ -13,7 +13,7 @@
 package org.apache.juneau.jso.annotation;
 
 import org.apache.juneau.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Applies {@link JsoConfig} annotations to a {@link PropertyStoreBuilder}.
@@ -26,7 +26,7 @@ public class JsoConfigApply extends ConfigApply<JsoConfig> {
 	 * @param c The annotation class.
 	 * @param r The resolver for resolving values in annotations.
 	 */
-	public JsoConfigApply(Class<JsoConfig> c, StringResolver r) {
+	public JsoConfigApply(Class<JsoConfig> c, VarResolverSession r) {
 		super(c, r);
 	}
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParserBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParserBuilder.java
index d848454..ec1db5b 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParserBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParserBuilder.java
@@ -20,7 +20,7 @@ import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.reflect.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Builder class for building instances of JSON parsers.
@@ -605,9 +605,9 @@ public class JsonParserBuilder extends ReaderParserBuilder {
 		super.apply(copyFrom);
 		return this;
 	}
-	
+
 	@Override
-	public JsonParserBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public JsonParserBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSchemaSerializerBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSchemaSerializerBuilder.java
index 38dc36c..527b9d4 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSchemaSerializerBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSchemaSerializerBuilder.java
@@ -22,7 +22,7 @@ import org.apache.juneau.http.*;
 import org.apache.juneau.jsonschema.*;
 import org.apache.juneau.reflect.*;
 import org.apache.juneau.serializer.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Builder class for building instances of JSON Schema serializers.
@@ -884,9 +884,9 @@ public class JsonSchemaSerializerBuilder extends JsonSerializerBuilder {
 		super.apply(copyFrom);
 		return this;
 	}
-	
+
 	@Override
-	public JsonSchemaSerializerBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public JsonSchemaSerializerBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java
index 7804599..cc6fb16 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java
@@ -20,7 +20,7 @@ import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.reflect.*;
 import org.apache.juneau.serializer.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Builder class for building instances of JSON serializers.
@@ -773,9 +773,9 @@ public class JsonSerializerBuilder extends WriterSerializerBuilder {
 		super.apply(copyFrom);
 		return this;
 	}
-	
+
 	@Override
-	public JsonSerializerBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public JsonSerializerBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/annotation/JsonConfigApply.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/annotation/JsonConfigApply.java
index dee4363..dadfc56 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/annotation/JsonConfigApply.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/annotation/JsonConfigApply.java
@@ -15,7 +15,7 @@ package org.apache.juneau.json.annotation;
 import static org.apache.juneau.json.JsonSerializer.*;
 import static org.apache.juneau.json.JsonParser.*;
 import org.apache.juneau.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Applies {@link JsonConfig} annotations to a {@link PropertyStoreBuilder}.
@@ -28,7 +28,7 @@ public class JsonConfigApply extends ConfigApply<JsonConfig> {
 	 * @param c The annotation class.
 	 * @param r The resolver for resolving values in annotations.
 	 */
-	public JsonConfigApply(Class<JsonConfig> c, StringResolver r) {
+	public JsonConfigApply(Class<JsonConfig> c, VarResolverSession r) {
 		super(c, r);
 	}
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaGeneratorBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaGeneratorBuilder.java
index 871e374..f07a38f 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaGeneratorBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaGeneratorBuilder.java
@@ -20,7 +20,7 @@ import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.reflect.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Builder class for building instances of JSON Schema generators.
@@ -763,7 +763,7 @@ public class JsonSchemaGeneratorBuilder extends BeanTraverseBuilder {
 	}
 
 	@Override
-	public JsonSchemaGeneratorBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public JsonSchemaGeneratorBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/annotation/JsonSchemaConfigApply.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/annotation/JsonSchemaConfigApply.java
index b273724..160b281 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/annotation/JsonSchemaConfigApply.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/annotation/JsonSchemaConfigApply.java
@@ -16,7 +16,7 @@ import static org.apache.juneau.jsonschema.JsonSchemaGenerator.*;
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.jsonschema.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Applies {@link JsonSchemaConfig} annotations to a {@link PropertyStoreBuilder}.
@@ -29,7 +29,7 @@ public class JsonSchemaConfigApply extends ConfigApply<JsonSchemaConfig> {
 	 * @param c The annotation class.
 	 * @param r The resolver for resolving values in annotations.
 	 */
-	public JsonSchemaConfigApply(Class<JsonSchemaConfig> c, StringResolver r) {
+	public JsonSchemaConfigApply(Class<JsonSchemaConfig> c, VarResolverSession r) {
 		super(c, r);
 	}
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParserBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParserBuilder.java
index 1340a92..edf9834 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParserBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParserBuilder.java
@@ -18,7 +18,7 @@ import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.reflect.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Builder class for building instances of MessagePack parsers.
@@ -559,9 +559,9 @@ public class MsgPackParserBuilder extends InputStreamParserBuilder {
 		super.apply(copyFrom);
 		return this;
 	}
-	
+
 	@Override
-	public MsgPackParserBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public MsgPackParserBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerBuilder.java
index 9173481..5f53bf1 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerBuilder.java
@@ -18,7 +18,7 @@ import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.reflect.*;
 import org.apache.juneau.serializer.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Builder class for building instances of MessagePack serializers.
@@ -648,9 +648,9 @@ public class MsgPackSerializerBuilder extends OutputStreamSerializerBuilder {
 		super.apply(copyFrom);
 		return this;
 	}
-	
+
 	@Override
-	public MsgPackSerializerBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public MsgPackSerializerBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/annotation/MsgPackConfigApply.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/annotation/MsgPackConfigApply.java
index ca27f85..7f78845 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/annotation/MsgPackConfigApply.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/annotation/MsgPackConfigApply.java
@@ -14,7 +14,7 @@ package org.apache.juneau.msgpack.annotation;
 
 import static org.apache.juneau.msgpack.MsgPackSerializer.*;
 import org.apache.juneau.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Applies {@link MsgPackConfig} annotations to a {@link PropertyStoreBuilder}.
@@ -27,7 +27,7 @@ public class MsgPackConfigApply extends ConfigApply<MsgPackConfig> {
 	 * @param c The annotation class.
 	 * @param r The resolver for resolving values in annotations.
 	 */
-	public MsgPackConfigApply(Class<MsgPackConfig> c, StringResolver r) {
+	public MsgPackConfigApply(Class<MsgPackConfig> c, VarResolverSession r) {
 		super(c, r);
 	}
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiParserBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiParserBuilder.java
index 33e94b5..c77c262 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiParserBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiParserBuilder.java
@@ -18,8 +18,8 @@ import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.reflect.*;
+import org.apache.juneau.svl.*;
 import org.apache.juneau.uon.*;
-import org.apache.juneau.utils.*;
 
 /**
  * Builder class for building instances of {@link OpenApiParser}.
@@ -541,9 +541,9 @@ public class OpenApiParserBuilder extends UonParserBuilder {
 		super.apply(copyFrom);
 		return this;
 	}
-	
+
 	@Override
-	public OpenApiParserBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public OpenApiParserBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiSerializerBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiSerializerBuilder.java
index 7161a30..5ff9856 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiSerializerBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiSerializerBuilder.java
@@ -18,8 +18,8 @@ import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.reflect.*;
 import org.apache.juneau.serializer.*;
+import org.apache.juneau.svl.*;
 import org.apache.juneau.uon.*;
-import org.apache.juneau.utils.*;
 
 /**
  * Builder class for building instances of {@link OpenApiSerializer}.
@@ -679,9 +679,9 @@ public class OpenApiSerializerBuilder extends UonSerializerBuilder {
 		super.apply(copyFrom);
 		return this;
 	}
-	
+
 	@Override
-	public OpenApiSerializerBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public OpenApiSerializerBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/annotation/OpenApiConfigApply.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/annotation/OpenApiConfigApply.java
index cb49800..8f0b6f6 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/annotation/OpenApiConfigApply.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/annotation/OpenApiConfigApply.java
@@ -13,7 +13,7 @@
 package org.apache.juneau.oapi.annotation;
 
 import org.apache.juneau.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Applies {@link OpenApiConfig} annotations to a {@link PropertyStoreBuilder}.
@@ -26,7 +26,7 @@ public class OpenApiConfigApply extends ConfigApply<OpenApiConfig> {
 	 * @param c The annotation class.
 	 * @param r The resolver for resolving values in annotations.
 	 */
-	public OpenApiConfigApply(Class<OpenApiConfig> c, StringResolver r) {
+	public OpenApiConfigApply(Class<OpenApiConfig> c, VarResolverSession r) {
 		super(c, r);
 	}
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParserBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParserBuilder.java
index aeecfae..596f013 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParserBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParserBuilder.java
@@ -19,7 +19,7 @@ import java.util.*;
 import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.reflect.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Base builder class for building instances of stream-based parsers.
@@ -593,7 +593,7 @@ public class InputStreamParserBuilder extends ParserBuilder {
 	}
 
 	@Override
-	public InputStreamParserBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public InputStreamParserBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserBuilder.java
index 238f2b7..e536c27 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserBuilder.java
@@ -19,7 +19,7 @@ import java.util.*;
 import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.reflect.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Builder class for building instances of parsers.
@@ -680,7 +680,7 @@ public class ParserBuilder extends BeanContextBuilder {
 	}
 
 	@Override
-	public ParserBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public ParserBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserGroupBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserGroupBuilder.java
index a51a9ec..2d2a956 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserGroupBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserGroupBuilder.java
@@ -22,7 +22,7 @@ import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.reflect.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Builder class for creating instances of {@link ParserGroup}.
@@ -826,7 +826,7 @@ public class ParserGroupBuilder extends BeanContextBuilder {
 	}
 
 	@Override
-	public ParserGroupBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public ParserGroupBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParserBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParserBuilder.java
index 8dbfdc8..70d17f8 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParserBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParserBuilder.java
@@ -20,7 +20,7 @@ import java.util.*;
 import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.reflect.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Base builder class for building instances of reader-based parsers.
@@ -632,7 +632,7 @@ public abstract class ReaderParserBuilder extends ParserBuilder {
 	}
 
 	@Override
-	public ReaderParserBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public ReaderParserBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/annotation/ParserConfigApply.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/annotation/ParserConfigApply.java
index 779f379..c0c3d98 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/annotation/ParserConfigApply.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/annotation/ParserConfigApply.java
@@ -18,7 +18,7 @@ import static org.apache.juneau.parser.InputStreamParser.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.parser.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Applies {@link ParserConfig} annotations to a {@link PropertyStoreBuilder}.
@@ -31,7 +31,7 @@ public class ParserConfigApply extends ConfigApply<ParserConfig> {
 	 * @param c The annotation class.
 	 * @param r The resolver for resolving values in annotations.
 	 */
-	public ParserConfigApply(Class<ParserConfig> c, StringResolver r) {
+	public ParserConfigApply(Class<ParserConfig> c, VarResolverSession r) {
 		super(c, r);
 	}
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextParserBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextParserBuilder.java
index 7aad6ac..814519f 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextParserBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextParserBuilder.java
@@ -18,7 +18,7 @@ import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.reflect.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Builder class for building instances of plain-text parsers.
@@ -567,7 +567,7 @@ public class PlainTextParserBuilder extends ReaderParserBuilder {
 	}
 
 	@Override
-	public PlainTextParserBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public PlainTextParserBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerBuilder.java
index 4315bf5..bc7c82f 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerBuilder.java
@@ -18,7 +18,7 @@ import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.reflect.*;
 import org.apache.juneau.serializer.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Builder class for building instances of plain-text serializers.
@@ -680,7 +680,7 @@ public class PlainTextSerializerBuilder extends WriterSerializerBuilder {
 	}
 
 	@Override
-	public PlainTextSerializerBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public PlainTextSerializerBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/annotation/PlainTextConfigApply.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/annotation/PlainTextConfigApply.java
index e7076a4..464415e 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/annotation/PlainTextConfigApply.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/annotation/PlainTextConfigApply.java
@@ -13,7 +13,7 @@
 package org.apache.juneau.plaintext.annotation;
 
 import org.apache.juneau.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Applies {@link PlainTextConfig} annotations to a {@link PropertyStoreBuilder}.
@@ -26,7 +26,7 @@ public class PlainTextConfigApply extends ConfigApply<PlainTextConfig> {
 	 * @param c The annotation class.
 	 * @param r The resolver for resolving values in annotations.
 	 */
-	public PlainTextConfigApply(Class<PlainTextConfig> c, StringResolver r) {
+	public PlainTextConfigApply(Class<PlainTextConfig> c, VarResolverSession r) {
 		super(c, r);
 	}
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/OutputStreamSerializerBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/OutputStreamSerializerBuilder.java
index 9a8d286..e80fab7 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/OutputStreamSerializerBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/OutputStreamSerializerBuilder.java
@@ -19,7 +19,7 @@ import java.util.*;
 import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.reflect.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Base class for all stream-based serializer builders.
@@ -531,7 +531,7 @@ public class OutputStreamSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override
-	public OutputStreamSerializerBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public OutputStreamSerializerBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerBuilder.java
index 40b2746..52a7e81 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerBuilder.java
@@ -19,7 +19,7 @@ import java.util.*;
 import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.reflect.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Builder class for building instances of serializers.
@@ -1020,7 +1020,7 @@ public class SerializerBuilder extends BeanTraverseBuilder {
 	}
 
 	@Override
-	public SerializerBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public SerializerBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerGroupBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerGroupBuilder.java
index 5010237..a62d60b 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerGroupBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerGroupBuilder.java
@@ -22,7 +22,7 @@ import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.reflect.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Builder class for creating instances of {@link SerializerGroup}.
@@ -1099,7 +1099,7 @@ public class SerializerGroupBuilder extends BeanTraverseBuilder {
 	}
 
 	@Override
-	public SerializerGroupBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public SerializerGroupBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerSession.java
index 324b066..6a6ff95 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerSession.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerSession.java
@@ -24,6 +24,7 @@ import org.apache.juneau.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.reflect.*;
 import org.apache.juneau.soap.*;
+import org.apache.juneau.svl.*;
 import org.apache.juneau.transform.*;
 
 /**
@@ -50,6 +51,7 @@ public abstract class SerializerSession extends BeanTraverseSession {
 
 	private final Serializer ctx;
 	private final UriResolver uriResolver;
+	private VarResolverSession vrs;
 
 	private final Method javaMethod;                                                // Java method that invoked this serializer.
 
@@ -78,6 +80,40 @@ public abstract class SerializerSession extends BeanTraverseSession {
 		this.uriResolver = new UriResolver(ctx.getUriResolution(), ctx.getUriRelativity(), args.uriContext == null ? ctx.getUriContext() : args.uriContext);
 		this.listener = castOrCreate(SerializerListener.class, ctx.getListener());
 		this.useWhitespace = args.useWhitespace != null ? args.useWhitespace : ctx.isUseWhitespace();
+		this.vrs = args.resolver;
+
+	}
+
+	/**
+	 * Adds a session object to the {@link VarResolverSession} in this session.
+	 *
+	 * @param name The session object key.
+	 * @param value The session object.
+	 * @return This object (for method chaining).
+	 */
+	public SerializerSession varSessionObject(String name, Object value) {
+		getVarResolver().sessionObject(name, value);
+		return this;
+	}
+
+	/**
+	 * Adds a session object to the {@link VarResolverSession} in this session.
+	 *
+	 * @return This object (for method chaining).
+	 */
+	protected VarResolverSession createDefaultVarResolverSession() {
+		return VarResolver.DEFAULT.createSession();
+	}
+
+	/**
+	 * Returns the variable resolver session.
+	 *
+	 * @return The variable resolver session.
+	 */
+	public VarResolverSession getVarResolver() {
+		if (vrs == null)
+			vrs = createDefaultVarResolverSession();
+		return vrs;
 	}
 
 	/**
@@ -592,6 +628,16 @@ public abstract class SerializerSession extends BeanTraverseSession {
 		return (T)listener;
 	}
 
+	/**
+	 * Resolves any variables in the specified string.
+	 *
+	 * @param string The string to resolve values in.
+	 * @return The string with variables resolved.
+	 */
+	public String resolve(String string) {
+		return getVarResolver().resolve(string);
+	}
+
 	//-----------------------------------------------------------------------------------------------------------------
 	// Properties
 	//-----------------------------------------------------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerSessionArgs.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerSessionArgs.java
index 594de3d..95453af 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerSessionArgs.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerSessionArgs.java
@@ -18,6 +18,7 @@ import java.util.*;
 import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.httppart.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Runtime arguments common to all serializer sessions.
@@ -35,6 +36,7 @@ public final class SerializerSessionArgs extends BeanSessionArgs {
 	Method javaMethod;
 	UriContext uriContext;
 	Boolean useWhitespace;
+	VarResolverSession resolver;
 
 	/**
 	 * Constructor
@@ -71,12 +73,15 @@ public final class SerializerSessionArgs extends BeanSessionArgs {
 	 * 	<br>Identifies the current request URI used for resolution of URIs to absolute or root-relative form.
 	 * @param useWhitespace
 	 * 	Override the use-whitespace flag on the serializer.
+	 * @param resolver
+	 * 	String variable resolver.
 	 */
-	public SerializerSessionArgs(ObjectMap properties, Method javaMethod, Locale locale, TimeZone timeZone, MediaType mediaType, HttpPartSchema schema, Boolean debug, UriContext uriContext, Boolean useWhitespace) {
+	public SerializerSessionArgs(ObjectMap properties, Method javaMethod, Locale locale, TimeZone timeZone, MediaType mediaType, HttpPartSchema schema, Boolean debug, UriContext uriContext, Boolean useWhitespace, VarResolverSession resolver) {
 		super(properties, locale, timeZone, mediaType, schema, debug);
 		this.javaMethod = javaMethod;
 		this.uriContext = uriContext;
 		this.useWhitespace = useWhitespace;
+		this.resolver = resolver == null ? null : resolver;
 	}
 
 	/**
@@ -118,6 +123,18 @@ public final class SerializerSessionArgs extends BeanSessionArgs {
 		return this;
 	}
 
+	/**
+	 * String variable resolver.
+	 *
+	 * @param value
+	 * 	String variable resolver.
+	 * @return This object (for method chaining).
+	 */
+	public SerializerSessionArgs resolver(VarResolverSession value) {
+		this.resolver = value;
+		return this;
+	}
+
 	@Override /* BeanSessionArgs */
 	public SerializerSessionArgs locale(Locale locale) {
 		super.locale(locale);
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializerBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializerBuilder.java
index e9ee3fd..695848e 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializerBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializerBuilder.java
@@ -19,7 +19,7 @@ import java.util.*;
 import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.reflect.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Base class for all writer-based serializer builders.
@@ -548,7 +548,7 @@ public class WriterSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override
-	public WriterSerializerBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public WriterSerializerBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/annotation/SerializerConfigApply.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/annotation/SerializerConfigApply.java
index 35fff74..f6c5b92 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/annotation/SerializerConfigApply.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/annotation/SerializerConfigApply.java
@@ -18,7 +18,7 @@ import static org.apache.juneau.serializer.WriterSerializer.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.serializer.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Applies {@link SerializerConfig} annotations to a {@link PropertyStoreBuilder}.
@@ -31,7 +31,7 @@ public class SerializerConfigApply extends ConfigApply<SerializerConfig> {
 	 * @param c The annotation class.
 	 * @param r The resolver for resolving values in annotations.
 	 */
-	public SerializerConfigApply(Class<SerializerConfig> c, StringResolver r) {
+	public SerializerConfigApply(Class<SerializerConfig> c, VarResolverSession r) {
 		super(c, r);
 	}
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/soap/SoapXmlSerializerBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/soap/SoapXmlSerializerBuilder.java
index 765e893..475a1b2 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/soap/SoapXmlSerializerBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/soap/SoapXmlSerializerBuilder.java
@@ -20,7 +20,7 @@ import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.reflect.*;
 import org.apache.juneau.serializer.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 import org.apache.juneau.xml.*;
 
 /**
@@ -700,7 +700,7 @@ public class SoapXmlSerializerBuilder extends XmlSerializerBuilder {
 	}
 
 	@Override
-	public SoapXmlSerializerBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public SoapXmlSerializerBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/soap/annotation/SoapXmlConfigApply.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/soap/annotation/SoapXmlConfigApply.java
index 478d020..f13d4af 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/soap/annotation/SoapXmlConfigApply.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/soap/annotation/SoapXmlConfigApply.java
@@ -14,7 +14,7 @@ package org.apache.juneau.soap.annotation;
 
 import static org.apache.juneau.soap.SoapXmlSerializer.*;
 import org.apache.juneau.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Applies {@link SoapXmlConfig} annotations to a {@link PropertyStoreBuilder}.
@@ -27,7 +27,7 @@ public class SoapXmlConfigApply extends ConfigApply<SoapXmlConfig> {
 	 * @param c The annotation class.
 	 * @param r The resolver for resolving values in annotations.
 	 */
-	public SoapXmlConfigApply(Class<SoapXmlConfig> c, StringResolver r) {
+	public SoapXmlConfigApply(Class<SoapXmlConfig> c, VarResolverSession r) {
 		super(c, r);
 	}
 
diff --git a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/DefaultingVar.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/DefaultingVar.java
similarity index 100%
rename from juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/DefaultingVar.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/DefaultingVar.java
diff --git a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/MapVar.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/MapVar.java
similarity index 100%
rename from juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/MapVar.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/MapVar.java
diff --git a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/MultipartResolvingVar.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/MultipartResolvingVar.java
similarity index 100%
rename from juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/MultipartResolvingVar.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/MultipartResolvingVar.java
diff --git a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/MultipartVar.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/MultipartVar.java
similarity index 100%
rename from juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/MultipartVar.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/MultipartVar.java
diff --git a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/ResolvingObjectMap.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/ResolvingObjectMap.java
similarity index 100%
rename from juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/ResolvingObjectMap.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/ResolvingObjectMap.java
diff --git a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/SimpleVar.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/SimpleVar.java
similarity index 100%
rename from juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/SimpleVar.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/SimpleVar.java
diff --git a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/StreamedVar.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/StreamedVar.java
similarity index 100%
rename from juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/StreamedVar.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/StreamedVar.java
diff --git a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/Var.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/Var.java
similarity index 91%
rename from juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/Var.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/Var.java
index e46dabf..229f5dc 100644
--- a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/Var.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/Var.java
@@ -128,6 +128,19 @@ public abstract class Var {
 	}
 
 	/**
+	 * Returns <jk>true</jk> if this variable can be resolved in the specified session.
+	 *
+	 * <p>
+	 * For example, some variable cannot resolve unless specific context or session objects are available.
+	 *
+	 * @param session The current session.
+	 * @return <jk>true</jk> if this variable can be resolved in the specified session.
+	 */
+	protected boolean canResolve(VarResolverSession session) {
+		return true;
+	}
+
+	/**
 	 * The method called from {@link VarResolver}.
 	 *
 	 * <p>
diff --git a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/VarResolver.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/VarResolver.java
similarity index 95%
rename from juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/VarResolver.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/VarResolver.java
index b291618..c3fd5f2 100644
--- a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/VarResolver.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/VarResolver.java
@@ -16,7 +16,6 @@ import java.io.*;
 import java.util.*;
 
 import org.apache.juneau.svl.vars.*;
-import org.apache.juneau.utils.*;
 
 /**
  * Utility class for resolving variables of the form <js>"$X{key}"</js> in strings.
@@ -58,7 +57,7 @@ import org.apache.juneau.utils.*;
  * 	<li class='link'>{@doc juneau-svl.VarResolvers}
  * </ul>
  */
-public class VarResolver implements StringResolver {
+public class VarResolver {
 
 	/**
 	 * Default string variable resolver with support for system properties and environment variables:
@@ -160,7 +159,6 @@ public class VarResolver implements StringResolver {
 	 * @param s The input string.
 	 * @return The string with variables resolved, or the same string if it doesn't contain any variables to resolve.
 	 */
-	@Override /* StringResolver */
 	public String resolve(String s) {
 		return createSession(null).resolve(s);
 	}
diff --git a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/VarResolverBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/VarResolverBuilder.java
similarity index 100%
rename from juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/VarResolverBuilder.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/VarResolverBuilder.java
diff --git a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/VarResolverContext.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/VarResolverContext.java
similarity index 100%
rename from juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/VarResolverContext.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/VarResolverContext.java
diff --git a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/VarResolverException.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/VarResolverException.java
similarity index 100%
rename from juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/VarResolverException.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/VarResolverException.java
diff --git a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/VarResolverSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/VarResolverSession.java
similarity index 98%
rename from juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/VarResolverSession.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/VarResolverSession.java
index 29fd086..0a716bf 100644
--- a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/VarResolverSession.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/VarResolverSession.java
@@ -19,7 +19,6 @@ import java.lang.reflect.*;
 import java.util.*;
 
 import org.apache.juneau.internal.*;
-import org.apache.juneau.utils.*;
 
 /**
  * A var resolver session that combines a {@link VarResolver} with one or more session objects.
@@ -42,7 +41,7 @@ import org.apache.juneau.utils.*;
  * 	<li class='link'>{@doc juneau-svl.VarResolvers}
  * </ul>
  */
-public class VarResolverSession implements StringResolver {
+public class VarResolverSession {
 
 	private final VarResolverContext context;
 	private final Map<String,Object> sessionObjects;
@@ -85,7 +84,6 @@ public class VarResolverSession implements StringResolver {
 	 * 	The new string with all variables resolved, or the same string if no variables were found.
 	 * 	<br>Returns <jk>null</jk> if the input was <jk>null</jk>.
 	 */
-	@Override /* StringResolver */
 	public String resolve(String s) {
 
 		if (s == null || s.isEmpty())
@@ -422,6 +420,7 @@ public class VarResolverSession implements StringResolver {
 	 * @return The {@link Var} instance, or <jk>null</jk> if no <code>Var</code> is associated with the specified name.
 	 */
 	protected Var getVar(String name) {
-		return this.context.getVarMap().get(name);
+		Var v = this.context.getVarMap().get(name);
+		return v != null && v.canResolve(this) ? v : null;
 	}
 }
diff --git a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/package-info.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/package-info.java
similarity index 100%
rename from juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/package-info.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/package-info.java
diff --git a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/ArgsVar.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/vars/ArgsVar.java
similarity index 100%
rename from juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/ArgsVar.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/vars/ArgsVar.java
diff --git a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/CoalesceVar.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/vars/CoalesceVar.java
similarity index 100%
rename from juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/CoalesceVar.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/vars/CoalesceVar.java
diff --git a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/EnvVariablesVar.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/vars/EnvVariablesVar.java
similarity index 100%
rename from juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/EnvVariablesVar.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/vars/EnvVariablesVar.java
diff --git a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/IfVar.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/vars/IfVar.java
similarity index 100%
rename from juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/IfVar.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/vars/IfVar.java
diff --git a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/LenVar.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/vars/LenVar.java
similarity index 100%
rename from juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/LenVar.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/vars/LenVar.java
diff --git a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/LowerCaseVar.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/vars/LowerCaseVar.java
similarity index 100%
rename from juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/LowerCaseVar.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/vars/LowerCaseVar.java
diff --git a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/ManifestFileVar.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/vars/ManifestFileVar.java
similarity index 100%
rename from juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/ManifestFileVar.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/vars/ManifestFileVar.java
diff --git a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/NotEmptyVar.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/vars/NotEmptyVar.java
similarity index 100%
rename from juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/NotEmptyVar.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/vars/NotEmptyVar.java
diff --git a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/PatternExtractVar.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/vars/PatternExtractVar.java
similarity index 100%
rename from juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/PatternExtractVar.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/vars/PatternExtractVar.java
diff --git a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/PatternMatchVar.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/vars/PatternMatchVar.java
similarity index 100%
rename from juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/PatternMatchVar.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/vars/PatternMatchVar.java
diff --git a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/PatternReplaceVar.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/vars/PatternReplaceVar.java
similarity index 100%
rename from juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/PatternReplaceVar.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/vars/PatternReplaceVar.java
diff --git a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/SubstringVar.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/vars/SubstringVar.java
similarity index 100%
rename from juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/SubstringVar.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/vars/SubstringVar.java
diff --git a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/SwitchVar.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/vars/SwitchVar.java
similarity index 100%
rename from juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/SwitchVar.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/vars/SwitchVar.java
diff --git a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/SystemPropertiesVar.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/vars/SystemPropertiesVar.java
similarity index 100%
rename from juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/SystemPropertiesVar.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/vars/SystemPropertiesVar.java
diff --git a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/UpperCaseVar.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/vars/UpperCaseVar.java
similarity index 100%
rename from juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/UpperCaseVar.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/vars/UpperCaseVar.java
diff --git a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/package-info.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/vars/package-info.java
similarity index 100%
rename from juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/vars/package-info.java
rename to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/vars/package-info.java
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserBuilder.java
index eb6881c..9ec7de3 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserBuilder.java
@@ -20,8 +20,8 @@ import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.reflect.*;
+import org.apache.juneau.svl.*;
 import org.apache.juneau.urlencoding.*;
-import org.apache.juneau.utils.*;
 
 /**
  * Builder class for building instances of UON parsers.
@@ -646,7 +646,7 @@ public class UonParserBuilder extends ReaderParserBuilder {
 	}
 
 	@Override
-	public UonParserBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public UonParserBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java
index 5707e43..1f979b2 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java
@@ -20,7 +20,7 @@ import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.reflect.*;
 import org.apache.juneau.serializer.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Builder class for building instances of UON serializers.
@@ -776,7 +776,7 @@ public class UonSerializerBuilder extends WriterSerializerBuilder {
 	}
 
 	@Override
-	public UonSerializerBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public UonSerializerBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/annotation/UonConfigApply.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/annotation/UonConfigApply.java
index 66efad2..a9c8250 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/annotation/UonConfigApply.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/annotation/UonConfigApply.java
@@ -15,7 +15,7 @@ package org.apache.juneau.uon.annotation;
 import static org.apache.juneau.uon.UonSerializer.*;
 import static org.apache.juneau.uon.UonParser.*;
 import org.apache.juneau.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Applies {@link UonConfig} annotations to a {@link PropertyStoreBuilder}.
@@ -28,7 +28,7 @@ public class UonConfigApply extends ConfigApply<UonConfig> {
 	 * @param c The annotation class.
 	 * @param r The resolver for resolving values in annotations.
 	 */
-	public UonConfigApply(Class<UonConfig> c, StringResolver r) {
+	public UonConfigApply(Class<UonConfig> c, VarResolverSession r) {
 		super(c, r);
 	}
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserBuilder.java
index cdc4840..22f0d22 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserBuilder.java
@@ -20,8 +20,8 @@ import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.reflect.*;
+import org.apache.juneau.svl.*;
 import org.apache.juneau.uon.*;
-import org.apache.juneau.utils.*;
 
 /**
  * Builder class for building instances of URL-Encoding parsers.
@@ -589,7 +589,7 @@ public class UrlEncodingParserBuilder extends UonParserBuilder {
 	}
 
 	@Override
-	public UrlEncodingParserBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public UrlEncodingParserBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerBuilder.java
index 89d29be..e71a3dc 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerBuilder.java
@@ -20,8 +20,8 @@ import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.reflect.*;
 import org.apache.juneau.serializer.*;
+import org.apache.juneau.svl.*;
 import org.apache.juneau.uon.*;
-import org.apache.juneau.utils.*;
 
 /**
  * Builder class for building instances of URL-Encoding serializers.
@@ -745,7 +745,7 @@ public class UrlEncodingSerializerBuilder extends UonSerializerBuilder {
 	}
 
 	@Override
-	public UrlEncodingSerializerBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public UrlEncodingSerializerBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/annotation/UrlEncodingConfigApply.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/annotation/UrlEncodingConfigApply.java
index 335b6d5..8c9f935 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/annotation/UrlEncodingConfigApply.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/annotation/UrlEncodingConfigApply.java
@@ -13,8 +13,8 @@
 package org.apache.juneau.urlencoding.annotation;
 
 import org.apache.juneau.*;
+import org.apache.juneau.svl.*;
 import org.apache.juneau.urlencoding.*;
-import org.apache.juneau.utils.*;
 
 /**
  * Applies {@link UrlEncodingConfig} annotations to a {@link PropertyStoreBuilder}.
@@ -27,7 +27,7 @@ public class UrlEncodingConfigApply extends ConfigApply<UrlEncodingConfig> {
 	 * @param c The annotation class.
 	 * @param r The resolver for resolving values in annotations.
 	 */
-	public UrlEncodingConfigApply(Class<UrlEncodingConfig> c, StringResolver r) {
+	public UrlEncodingConfigApply(Class<UrlEncodingConfig> c, VarResolverSession r) {
 		super(c, r);
 	}
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/StringResolver.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/StringResolver.java
deleted file mode 100644
index ee055f2..0000000
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/StringResolver.java
+++ /dev/null
@@ -1,37 +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.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.utils;
-
-/**
- * Interface for resolving variables within strings.
- */
-public interface StringResolver {
-
-	/**
-	 * NO-OP resolver.
-	 */
-	public static final StringResolver NOOP = new StringResolver() {
-		@Override
-		public String resolve(String input) {
-			return input;
-		}
-	};
-
-	/**
-	 * Resolve any variables in the specified input string.
-	 *
-	 * @param input The string containing variables to resolve.
-	 * @return A string with variables resolved.
-	 */
-	String resolve(String input);
-}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParserBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParserBuilder.java
index e5773b1..c297348 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParserBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParserBuilder.java
@@ -23,7 +23,7 @@ import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.reflect.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Builder class for building XML parsers.
@@ -753,9 +753,9 @@ public class XmlParserBuilder extends ReaderParserBuilder {
 		super.apply(copyFrom);
 		return this;
 	}
-	
+
 	@Override
-	public XmlParserBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public XmlParserBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializerBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializerBuilder.java
index e003697..9a71fc5 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializerBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializerBuilder.java
@@ -20,7 +20,7 @@ import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.reflect.*;
 import org.apache.juneau.serializer.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 
 /**
  * Builder class for building instances of XML serializers.
@@ -891,7 +891,7 @@ public class XmlSerializerBuilder extends WriterSerializerBuilder {
 	}
 
 	@Override
-	public XmlSerializerBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public XmlSerializerBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/annotation/XmlConfigApply.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/annotation/XmlConfigApply.java
index 19705f0..60c05e0 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/annotation/XmlConfigApply.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/annotation/XmlConfigApply.java
@@ -15,7 +15,7 @@ package org.apache.juneau.xml.annotation;
 import static org.apache.juneau.xml.XmlSerializer.*;
 import static org.apache.juneau.xml.XmlParser.*;
 import org.apache.juneau.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 import org.apache.juneau.xml.*;
 
 /**
@@ -29,7 +29,7 @@ public class XmlConfigApply extends ConfigApply<XmlConfig> {
 	 * @param c The annotation class.
 	 * @param r The resolver for resolving values in annotations.
 	 */
-	public XmlConfigApply(Class<XmlConfig> c, StringResolver r) {
+	public XmlConfigApply(Class<XmlConfig> c, VarResolverSession r) {
 		super(c, r);
 	}
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xmlschema/XmlSchemaSerializerBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xmlschema/XmlSchemaSerializerBuilder.java
index 02a3692..e91cb2e 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xmlschema/XmlSchemaSerializerBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xmlschema/XmlSchemaSerializerBuilder.java
@@ -18,7 +18,7 @@ import org.apache.juneau.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.reflect.*;
 import org.apache.juneau.serializer.*;
-import org.apache.juneau.utils.*;
+import org.apache.juneau.svl.*;
 import org.apache.juneau.xml.*;
 
 /**
@@ -723,7 +723,7 @@ public class XmlSchemaSerializerBuilder extends XmlSerializerBuilder {
 	}
 
 	@Override
-	public XmlSchemaSerializerBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public XmlSchemaSerializerBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClientBuilder.java b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClientBuilder.java
index 0141959..b1917c9 100644
--- a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClientBuilder.java
+++ b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClientBuilder.java
@@ -60,9 +60,9 @@ import org.apache.juneau.parser.*;
 import org.apache.juneau.plaintext.*;
 import org.apache.juneau.reflect.*;
 import org.apache.juneau.serializer.*;
+import org.apache.juneau.svl.*;
 import org.apache.juneau.uon.*;
 import org.apache.juneau.urlencoding.*;
-import org.apache.juneau.utils.*;
 import org.apache.juneau.xml.*;
 
 /**
@@ -2691,7 +2691,7 @@ public class RestClientBuilder extends BeanContextBuilder {
 	}
 
 	@Override
-	public RestClientBuilder applyAnnotations(AnnotationsMap m, StringResolver sr) {
+	public RestClientBuilder applyAnnotations(AnnotationsMap m, VarResolverSession sr) {
 		super.applyAnnotations(m, sr);
 		return this;
 	}
diff --git a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestRequestEntity.java b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestRequestEntity.java
index b89a609..c618c27 100644
--- a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestRequestEntity.java
+++ b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestRequestEntity.java
@@ -62,7 +62,7 @@ public final class RestRequestEntity extends BasicHttpEntity {
 					// If no serializer specified, just close the stream.
 					os.close();
 				} else {
-					SerializerSessionArgs sArgs = new SerializerSessionArgs(null, null, null, null, null, schema, false, null, null);
+					SerializerSessionArgs sArgs = new SerializerSessionArgs(null, null, null, null, null, schema, false, null, null, null);
 					SerializerSession session = serializer.createSession(sArgs);
 					try (Closeable c = session.isWriterSerializer() ? new OutputStreamWriter(os, UTF8) : os) {
 						session.serialize(output, c);
diff --git a/juneau-rest/juneau-rest-server-jaxrs/src/main/java/org/apache/juneau/rest/jaxrs/BaseProvider.java b/juneau-rest/juneau-rest-server-jaxrs/src/main/java/org/apache/juneau/rest/jaxrs/BaseProvider.java
index 87182da..51654fe 100644
--- a/juneau-rest/juneau-rest-server-jaxrs/src/main/java/org/apache/juneau/rest/jaxrs/BaseProvider.java
+++ b/juneau-rest/juneau-rest-server-jaxrs/src/main/java/org/apache/juneau/rest/jaxrs/BaseProvider.java
@@ -121,7 +121,7 @@ public class BaseProvider implements MessageBodyReader<Object>, MessageBodyWrite
 			Locale locale = getLocale(headers);
 			TimeZone timeZone = getTimeZone(headers);
 
-			SerializerSession session = s.createSession(new SerializerSessionArgs(mp, null, locale, timeZone, sm.getMediaType(), null, null, null, null));
+			SerializerSession session = s.createSession(new SerializerSessionArgs(mp, null, locale, timeZone, sm.getMediaType(), null, null, null, null, null));
 
 			// Leave this open in case an error occurs.
 			Closeable c = s.isWriterSerializer() ? new OutputStreamWriter(os, UTF8) : os;
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestJavaMethod.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestJavaMethod.java
index a024d03..9395acf 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestJavaMethod.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestJavaMethod.java
@@ -51,7 +51,6 @@ import org.apache.juneau.rest.util.UrlPathPattern;
 import org.apache.juneau.rest.widget.*;
 import org.apache.juneau.serializer.*;
 import org.apache.juneau.svl.*;
-import org.apache.juneau.utils.*;
 
 /**
  * Represents a single Java servlet/resource method annotated with {@link RestMethod @RestMethod}.
@@ -253,7 +252,7 @@ public class RestJavaMethod implements Comparable<RestJavaMethod>  {
 				this.requiredMatchers = requiredMatchers.toArray(new RestMatcher[requiredMatchers.size()]);
 				this.optionalMatchers = optionalMatchers.toArray(new RestMatcher[optionalMatchers.size()]);
 
-				StringResolver sr = vr.createSession();
+				VarResolverSession sr = vr.createSession();
 
 				PropertyStoreBuilder psb = PropertyStore.create().add(properties).set(BEAN_beanFilters, mBeanFilters).set(BEAN_pojoSwaps, mPojoSwaps);
 				for (Property p1 : m.properties())
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
index bfec9f6..4d1742d 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
@@ -1614,7 +1614,7 @@ public final class RestRequest extends HttpServletRequestWrapper {
 	 */
 	public SerializerSessionArgs getSerializerSessionArgs() {
 		if (serializerSessionArgs == null)
-			serializerSessionArgs = new SerializerSessionArgs(getProperties(), getJavaMethod(), getLocale(), getHeaders().getTimeZone(), null, null, isDebug() ? true : null, getUriContext(), isPlainText() ? true : null);
+			serializerSessionArgs = new SerializerSessionArgs(getProperties(), getJavaMethod(), getLocale(), getHeaders().getTimeZone(), null, null, isDebug() ? true : null, getUriContext(), isPlainText() ? true : null, getVarResolverSession());
 		return serializerSessionArgs;
 	}
 
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerGenerator.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerGenerator.java
index f7978fd..d74cd2b 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerGenerator.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerGenerator.java
@@ -803,7 +803,7 @@ final class SwaggerGenerator {
 			if (mt != MediaType.HTML) {
 				Serializer s2 = sm.getSerializers().getSerializer(mt);
 				if (s2 != null) {
-					SerializerSessionArgs args = new SerializerSessionArgs(null, req.getJavaMethod(), req.getLocale(), null, mt, null, req.isDebug() ? true : null, req.getUriContext(), true);
+					SerializerSessionArgs args = new SerializerSessionArgs(null, req.getJavaMethod(), req.getLocale(), null, mt, null, req.isDebug() ? true : null, req.getUriContext(), true, req.getVarResolverSession());
 					try {
 						String eVal = s2.createSession(args).serializeToString(example);
 						examples.put(s2.getPrimaryMediaType().toString(), eVal);
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/reshandlers/DefaultHandler.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/reshandlers/DefaultHandler.java
index 77f683c..f85e79c 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/reshandlers/DefaultHandler.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/reshandlers/DefaultHandler.java
@@ -144,7 +144,7 @@ public class DefaultHandler implements ResponseHandler {
 					res.setContentType("text/plain");
 				p.append("mediaType", mediaType).append("characterEncoding", res.getCharacterEncoding());
 
-				SerializerSession session = s.createSession(new SerializerSessionArgs(p, req.getJavaMethod(), req.getLocale(), req.getHeaders().getTimeZone(), mediaType, schema, req.isDebug() ? true : null, req.getUriContext(), req.isPlainText() ? true : null));
+				SerializerSession session = s.createSession(new SerializerSessionArgs(p, req.getJavaMethod(), req.getLocale(), req.getHeaders().getTimeZone(), mediaType, schema, req.isDebug() ? true : null, req.getUriContext(), req.isPlainText() ? true : null, req.getVarResolverSession()));
 
 				for (Map.Entry<String,String> h : session.getResponseHeaders().entrySet())
 					res.setHeader(h.getKey(), h.getValue());
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/widget/MenuItemWidget.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/widget/MenuItemWidget.java
index 23d6a60..105e395 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/widget/MenuItemWidget.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/widget/MenuItemWidget.java
@@ -153,7 +153,7 @@ public abstract class MenuItemWidget extends Widget {
 		} else if (o instanceof CharSequence) {
 			sb.append((CharSequence)o);
 		} else {
-			SerializerSessionArgs args = new SerializerSessionArgs(req.getProperties(), null, req.getLocale(), null, null, null, req.isDebug() ? true : null, req.getUriContext(), req.isPlainText() ? true : null);
+			SerializerSessionArgs args = new SerializerSessionArgs(req.getProperties(), null, req.getLocale(), null, null, null, req.isDebug() ? true : null, req.getUriContext(), req.isPlainText() ? true : null, req.getVarResolverSession());
 			WriterSerializerSession session = HtmlSerializer.DEFAULT.createSession(args);
 			session.indent = 2;
 			session.serialize(o, sb);