http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerBuilder.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerBuilder.java 
b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerBuilder.java
index fe9858b..79d6a29 100644
--- 
a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerBuilder.java
+++ 
b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerBuilder.java
@@ -378,97 +378,111 @@ public class SerializerBuilder extends CoreObjectBuilder 
{
        }
 
        /**
-        * <b>Configuration property:</b>  URI base for relative URIs.
+        * <b>Configuration property:</b>  URI context bean.
         * <p>
         * <ul>
-        *      <li><b>Name:</b> <js>"Serializer.relativeUriBase"</js>
-        *      <li><b>Data type:</b> <code>String</code>
-        *      <li><b>Default:</b> <js>""</js>
+        *      <li><b>Name:</b> <js>"Serializer.uriContext"</js>
+        *      <li><b>Data type:</b> {@link UriContext}
+        *      <li><b>Default:</b> {@link UriContext#DEFAULT}
         *      <li><b>Session-overridable:</b> <jk>true</jk>
         * </ul>
         * <p>
-        * Prepended to relative URIs during serialization (along with the 
{@link SerializerContext#SERIALIZER_absolutePathUriBase} if specified.
-        * (i.e. URIs not containing a schema and not starting with 
<js>'/'</js>).
-        * (e.g. <js>"foo/bar"</js>)
-        *
-        * <h5 class='section'>Example:</h5>
-        * <table class='styled'>
-        *      
<tr><th>SERIALIZER_relativeUriBase</th><th>URI</th><th>Serialized URI</th></tr>
-        *      <tr>
-        *              <td><code>http://foo:9080/bar/baz</code></td>
-        *              <td><code>mywebapp</code></td>
-        *              <td><code>http://foo:9080/bar/baz/mywebapp</code></td>
-        *      </tr>
-        *      <tr>
-        *              <td><code>http://foo:9080/bar/baz</code></td>
-        *              <td><code>/mywebapp</code></td>
-        *              <td><code>/mywebapp</code></td>
-        *      </tr>
-        *      <tr>
-        *              <td><code>http://foo:9080/bar/baz</code></td>
-        *              <td><code>http://mywebapp</code></td>
-        *              <td><code>http://mywebapp</code></td>
-        *      </tr>
-        * </table>
+        * Bean used for resolution of URIs to absolute or root-relative form.
+        * <p>
+        * <h6 class='figure'>Example:</h6>
+        * <p class='bcode'>
+        *      
<js>"{authority:'http://localhost:10000',contextRoot:'/myContext',servletPath:'/myServlet',pathInfo:'/foo'}"</js>
+        * </p>
         * <p>
         * <h5 class='section'>Notes:</h5>
         * <ul>
-        *      <li>This is equivalent to calling 
<code>property(<jsf>SERIALIZER_relativeUriBase</jsf>, value)</code>.
+        *      <li>This is equivalent to calling 
<code>property(<jsf>SERIALIZER_uriContext</jsf>, value)</code>.
         * </ul>
         *
         * @param value The new value for this property.
         * @return This object (for method chaining).
-        * @see SerializerContext#SERIALIZER_relativeUriBase
+        * @see SerializerContext#SERIALIZER_uriContext
         */
-       public SerializerBuilder relativeUriBase(String value) {
-               return property(SERIALIZER_relativeUriBase, value);
+       public SerializerBuilder uriContext(UriContext value) {
+               return property(SERIALIZER_uriContext, value);
        }
 
        /**
-        * <b>Configuration property:</b>  URI base for relative URIs with 
absolute paths.
+        * <b>Configuration property:</b>  URI resolution.
         * <p>
         * <ul>
-        *      <li><b>Name:</b> <js>"Serializer.absolutePathUriBase"</js>
-        *      <li><b>Data type:</b> <code>String</code>
-        *      <li><b>Default:</b> <js>""</js>
+        *      <li><b>Name:</b> <js>"Serializer.uriResolution"</js>
+        *      <li><b>Data type:</b> {@link UriResolution}
+        *      <li><b>Default:</b> {@link UriResolution#ROOT_RELATIVE}
         *      <li><b>Session-overridable:</b> <jk>true</jk>
         * </ul>
         * <p>
-        * Prepended to relative absolute-path URIs during serialization.
-        * (i.e. URIs starting with <js>'/'</js>).
-        * (e.g. <js>"/foo/bar"</js>)
+        * Defines the resolution level for URIs when serializing any of the 
following:
+        * <ul>
+        *      <li>{@link java.net.URI}
+        *      <li>{@link java.net.URL}
+        *      <li>Properties annotated with {@link 
org.apache.juneau.annotation.URI @URI}
+        * </ul>
+        * <p>
+        * Possible values are:
+        * <ul>
+        *      <li>{@link UriResolution#ABSOLUTE}
+        *              - Resolve to an absolute URL (e.g. 
<js>"http://host:port/context-root/servlet-path/path-info";</js>).
+        *      <li>{@link UriResolution#ROOT_RELATIVE}
+        *              - Resolve to a root-relative URL (e.g. 
<js>"/context-root/servlet-path/path-info"</js>).
+        *      <li>{@link UriResolution#NONE}
+        *              - Don't do any URL resolution.
+        * </ul>
+        * <p>
+        * <h5 class='section'>Notes:</h5>
+        * <ul>
+        *      <li>This is equivalent to calling 
<code>property(<jsf>SERIALIZER_uriResolution</jsf>, value)</code>.
+        * </ul>
         *
-        * <h5 class='section'>Examples:</h5>
-        * <table class='styled'>
-        *      
<tr><th>SERIALIZER_absolutePathUriBase</th><th>URI</th><th>Serialized 
URI</th></tr>
-        *      <tr>
-        *              <td><code>http://foo:9080/bar/baz</code></td>
-        *              <td><code>mywebapp</code></td>
-        *              <td><code>mywebapp</code></td>
-        *      </tr>
-        *      <tr>
-        *              <td><code>http://foo:9080/bar/baz</code></td>
-        *              <td><code>/mywebapp</code></td>
-        *              <td><code>http://foo:9080/bar/baz/mywebapp</code></td>
-        *      </tr>
-        *      <tr>
-        *              <td><code>http://foo:9080/bar/baz</code></td>
-        *              <td><code>http://mywebapp</code></td>
-        *              <td><code>http://mywebapp</code></td>
-        *      </tr>
-        * </table>
+        * @param value The new value for this property.
+        * @return This object (for method chaining).
+        * @see SerializerContext#SERIALIZER_uriResolution
+        */
+       public SerializerBuilder uriResolution(UriResolution value) {
+               return property(SERIALIZER_uriResolution, value);
+       }
+
+       /**
+        * <b>Configuration property:</b>  URI relativity.
+        * <p>
+        * <ul>
+        *      <li><b>Name:</b> <js>"Serializer.uriRelativity"</js>
+        *      <li><b>Data type:</b> {@link UriRelativity}
+        *      <li><b>Default:</b> {@link UriRelativity#RESOURCE}
+        *      <li><b>Session-overridable:</b> <jk>true</jk>
+        * </ul>
+        * <p>
+        * Defines what relative URIs are relative to when serializing any of 
the following:
+        * <ul>
+        *      <li>{@link java.net.URI}
+        *      <li>{@link java.net.URL}
+        *      <li>Properties annotated with {@link 
org.apache.juneau.annotation.URI @URI}
+        * </ul>
+        * <p>
+        * Possible values are:
+        * <ul>
+        *      <li>{@link UriRelativity#RESOURCE}
+        *              - Relative URIs should be considered relative to the 
servlet URI.
+        *      <li>{@link UriRelativity#PATH_INFO}
+        *              - Relative URIs should be considered relative to the 
request URI.
+        * </ul>
         * <p>
         * <h5 class='section'>Notes:</h5>
         * <ul>
-        *      <li>This is equivalent to calling 
<code>property(<jsf>SERIALIZER_absolutePathUriBase</jsf>, value)</code>.
+        *      <li>This is equivalent to calling 
<code>property(<jsf>SERIALIZER_uriRelativity</jsf>, value)</code>.
         * </ul>
         *
         * @param value The new value for this property.
         * @return This object (for method chaining).
-        * @see SerializerContext#SERIALIZER_absolutePathUriBase
+        * @see SerializerContext#SERIALIZER_uriRelativity
         */
-       public SerializerBuilder absolutePathUriBase(String value) {
-               return property(SERIALIZER_absolutePathUriBase, value);
+       public SerializerBuilder uriRelativity(UriRelativity value) {
+               return property(SERIALIZER_uriRelativity, value);
        }
 
        /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerContext.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerContext.java 
b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerContext.java
index fd890f9..372e8e0 100644
--- 
a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerContext.java
+++ 
b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerContext.java
@@ -14,7 +14,6 @@ package org.apache.juneau.serializer;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Configurable properties common to all serializers.
@@ -215,96 +214,79 @@ public class SerializerContext extends BeanContext {
        public static final String SERIALIZER_trimStrings = 
"Serializer.trimStrings";
 
        /**
-        * <b>Configuration property:</b>  URI base for relative URIs.
+        * <b>Configuration property:</b>  URI context bean.
         * <p>
         * <ul>
-        *      <li><b>Name:</b> <js>"Serializer.relativeUriBase"</js>
-        *      <li><b>Data type:</b> <code>String</code>
-        *      <li><b>Default:</b> <js>""</js>
+        *      <li><b>Name:</b> <js>"Serializer.uriContext"</js>
+        *      <li><b>Data type:</b> {@link UriContext}
+        *      <li><b>Default:</b> {@link UriContext#DEFAULT}
         *      <li><b>Session-overridable:</b> <jk>true</jk>
         * </ul>
         * <p>
-        * Prepended to relative URIs during serialization (along with the 
{@link #SERIALIZER_absolutePathUriBase} if specified.
-        * (i.e. URIs not containing a schema and not starting with 
<js>'/'</js>).
-        * (e.g. <js>"foo/bar"</js>)
-        *
-        * <h5 class='section'>Example:</h5>
-        * <table class='styled'>
-        *      
<tr><th>SERIALIZER_relativeUriBase</th><th>URI</th><th>Serialized URI</th></tr>
-        *      <tr>
-        *              <td><code>http://foo:9080/bar/baz</code></td>
-        *              <td><code>mywebapp</code></td>
-        *              <td><code>http://foo:9080/bar/baz/mywebapp</code></td>
-        *      </tr>
-        *      <tr>
-        *              <td><code>http://foo:9080/bar/baz</code></td>
-        *              <td><code>/mywebapp</code></td>
-        *              <td><code>/mywebapp</code></td>
-        *      </tr>
-        *      <tr>
-        *              <td><code>http://foo:9080/bar/baz</code></td>
-        *              <td><code>http://mywebapp</code></td>
-        *              <td><code>http://mywebapp</code></td>
-        *      </tr>
-        * </table>
+        * Bean used for resolution of URIs to absolute or root-relative form.
+        * <p>
+        * <h6 class='figure'>Example:</h6>
+        * <p class='bcode'>
+        *      
<js>"{authority:'http://localhost:10000',contextRoot:'/myContext',servletPath:'/myServlet',pathInfo:'/foo'}"</js>
+        * </p>
         */
-       public static final String SERIALIZER_relativeUriBase = 
"Serializer.relativeUriBase";
+       public static final String SERIALIZER_uriContext = 
"Serializer.uriContext";
 
        /**
-        * <b>Configuration property:</b>  URI base for relative URIs with 
absolute paths.
+        * <b>Configuration property:</b>  URI resolution.
         * <p>
         * <ul>
-        *      <li><b>Name:</b> <js>"Serializer.absolutePathUriBase"</js>
-        *      <li><b>Data type:</b> <code>String</code>
-        *      <li><b>Default:</b> <js>""</js>
+        *      <li><b>Name:</b> <js>"Serializer.uriResolution"</js>
+        *      <li><b>Data type:</b> {@link UriResolution}
+        *      <li><b>Default:</b> {@link UriResolution#ROOT_RELATIVE}
         *      <li><b>Session-overridable:</b> <jk>true</jk>
         * </ul>
         * <p>
-        * Prepended to relative absolute-path URIs during serialization.
-        * (i.e. URIs starting with <js>'/'</js>).
-        * (e.g. <js>"/foo/bar"</js>)
-        *
-        * <h5 class='section'>Examples:</h5>
-        * <table class='styled'>
-        *      
<tr><th>SERIALIZER_absolutePathUriBase</th><th>URI</th><th>Serialized 
URI</th></tr>
-        *      <tr>
-        *              <td><code>http://foo:9080/bar/baz</code></td>
-        *              <td><code>mywebapp</code></td>
-        *              <td><code>mywebapp</code></td>
-        *      </tr>
-        *      <tr>
-        *              <td><code>http://foo:9080/bar/baz</code></td>
-        *              <td><code>/mywebapp</code></td>
-        *              <td><code>http://foo:9080/bar/baz/mywebapp</code></td>
-        *      </tr>
-        *      <tr>
-        *              <td><code>http://foo:9080/bar/baz</code></td>
-        *              <td><code>http://mywebapp</code></td>
-        *              <td><code>http://mywebapp</code></td>
-        *      </tr>
-        * </table>
+        * Defines the resolution level for URIs when serializing any of the 
following:
+        * <ul>
+        *      <li>{@link java.net.URI}
+        *      <li>{@link java.net.URL}
+        *      <li>Properties annotated with {@link 
org.apache.juneau.annotation.URI @URI}
+        * </ul>
+        * <p>
+        * Possible values are:
+        * <ul>
+        *      <li>{@link UriResolution#ABSOLUTE}
+        *              - Resolve to an absolute URL (e.g. 
<js>"http://host:port/context-root/servlet-path/path-info";</js>).
+        *      <li>{@link UriResolution#ROOT_RELATIVE}
+        *              - Resolve to a root-relative URL (e.g. 
<js>"/context-root/servlet-path/path-info"</js>).
+        *      <li>{@link UriResolution#NONE}
+        *              - Don't do any URL resolution.
+        * </ul>
         */
-       public static final String SERIALIZER_absolutePathUriBase = 
"Serializer.absolutePathUriBase";
+       public static final String SERIALIZER_uriResolution = 
"Serializer.uriResolution";
 
        /**
-        * <b>Configuration property:</b>  URI context bean.
+        * <b>Configuration property:</b>  URI relativity.
         * <p>
         * <ul>
-        *      <li><b>Name:</b> <js>"Serializer.uriContext"</js>
-        *      <li><b>Data type:</b> {@link UriContext}
-        *      <li><b>Default:</b> {@link UriContext#DEFAULT}
+        *      <li><b>Name:</b> <js>"Serializer.uriRelativity"</js>
+        *      <li><b>Data type:</b> {@link UriRelativity}
+        *      <li><b>Default:</b> {@link UriRelativity#RESOURCE}
         *      <li><b>Session-overridable:</b> <jk>true</jk>
         * </ul>
         * <p>
-        * Bean used for resolution of URIs to absolute or root-relative form.
+        * Defines what relative URIs are relative to when serializing any of 
the following:
+        * <ul>
+        *      <li>{@link java.net.URI}
+        *      <li>{@link java.net.URL}
+        *      <li>Properties annotated with {@link 
org.apache.juneau.annotation.URI @URI}
+        * </ul>
         * <p>
-        * For example, to define a URI context that causes relative URIs to be 
converted to root-relative form and
-        * assumes relative URIs are relative to the servlet path:
-        * <p class='bcode'>
-        *      
<js>"{resolution:'ROOT_RELATIVE',relativity:'RESOURCE',contextRoot:'/myContext',servletPath:'/myServlet'}"</js>
-        * </p>
+        * Possible values are:
+        * <ul>
+        *      <li>{@link UriRelativity#RESOURCE}
+        *              - Relative URIs should be considered relative to the 
servlet URI.
+        *      <li>{@link UriRelativity#PATH_INFO}
+        *              - Relative URIs should be considered relative to the 
request URI.
+        * </ul>
         */
-       public static final String SERIALIZER_uriContext = 
"Serializer.uriContext";
+       public static final String SERIALIZER_uriRelativity = 
"Serializer.uriRelativity";
 
        /**
         * <b>Configuration property:</b>  Sort arrays and collections 
alphabetically.
@@ -368,8 +350,9 @@ public class SerializerContext extends BeanContext {
                sortMaps,
                abridged;
        final char quoteChar;
-       final String relativeUriBase, absolutePathUriBase;
        final UriContext uriContext;
+       final UriResolution uriResolution;
+       final UriRelativity uriRelativity;
 
        /**
         * Constructor.
@@ -392,27 +375,9 @@ public class SerializerContext extends BeanContext {
                sortMaps = ps.getProperty(SERIALIZER_sortMaps, boolean.class, 
false);
                abridged = ps.getProperty(SERIALIZER_abridged, boolean.class, 
false);
                quoteChar = ps.getProperty(SERIALIZER_quoteChar, String.class, 
"\"").charAt(0);
-               relativeUriBase = 
resolveRelativeUriBase(ps.getProperty(SERIALIZER_relativeUriBase, String.class, 
""));
-               absolutePathUriBase = 
resolveAbsolutePathUriBase(ps.getProperty(SERIALIZER_absolutePathUriBase, 
String.class, ""));
                uriContext = ps.getProperty(SERIALIZER_uriContext, 
UriContext.class, UriContext.DEFAULT);
-       }
-
-       private static String resolveRelativeUriBase(String s) {
-               if (StringUtils.isEmpty(s))
-                       return null;
-               if (s.equals("/"))
-                       return s;
-               else if (StringUtils.endsWith(s, '/'))
-                       s = s.substring(0, s.length()-1);
-               return s;
-       }
-
-       private static String resolveAbsolutePathUriBase(String s) {
-               if (StringUtils.isEmpty(s))
-                       return null;
-               if (StringUtils.endsWith(s, '/'))
-                       s = s.substring(0, s.length()-1);
-               return s;
+               uriResolution = ps.getProperty(SERIALIZER_uriResolution, 
UriResolution.class, UriResolution.ROOT_RELATIVE);
+               uriRelativity = ps.getProperty(SERIALIZER_uriRelativity, 
UriRelativity.class, UriRelativity.RESOURCE);
        }
 
        @Override /* Context */
@@ -433,9 +398,9 @@ public class SerializerContext extends BeanContext {
                                .append("sortMaps", sortMaps)
                                .append("parserKnowsRootTypes", abridged)
                                .append("quoteChar", quoteChar)
-                               .append("relativeUriBase", relativeUriBase)
-                               .append("absolutePathUriBase", 
absolutePathUriBase)
                                .append("uriContext", uriContext)
+                               .append("uriResolution", uriResolution)
+                               .append("uriRelativity", uriRelativity)
                        );
        }
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroupBuilder.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroupBuilder.java
 
b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroupBuilder.java
index f97ed7a..bbe7577 100644
--- 
a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroupBuilder.java
+++ 
b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroupBuilder.java
@@ -347,25 +347,36 @@ public class SerializerGroupBuilder {
        }
 
        /**
-        * Sets the {@link SerializerContext#SERIALIZER_relativeUriBase} 
property on all serializers in this group.
+        * Sets the {@link SerializerContext#SERIALIZER_uriContext} property on 
all serializers in this group.
         *
         * @param value The new value for this property.
         * @return This object (for method chaining).
-        * @see SerializerContext#SERIALIZER_relativeUriBase
+        * @see SerializerContext#SERIALIZER_uriContext
         */
-       public SerializerGroupBuilder relativeUriBase(String value) {
-               return property(SERIALIZER_relativeUriBase, value);
+       public SerializerGroupBuilder uriContext(UriContext value) {
+               return property(SERIALIZER_uriContext, value);
        }
 
        /**
-        * Sets the {@link SerializerContext#SERIALIZER_absolutePathUriBase} 
property on all serializers in this group.
+        * Sets the {@link SerializerContext#SERIALIZER_uriResolution} property 
on all serializers in this group.
         *
         * @param value The new value for this property.
         * @return This object (for method chaining).
-        * @see SerializerContext#SERIALIZER_absolutePathUriBase
+        * @see SerializerContext#SERIALIZER_uriResolution
         */
-       public SerializerGroupBuilder absolutePathUriBase(String value) {
-               return property(SERIALIZER_absolutePathUriBase, value);
+       public SerializerGroupBuilder uriResolution(UriResolution value) {
+               return property(SERIALIZER_uriResolution, value);
+       }
+
+       /**
+        * Sets the {@link SerializerContext#SERIALIZER_uriRelativity} property 
on all serializers in this group.
+        *
+        * @param value The new value for this property.
+        * @return This object (for method chaining).
+        * @see SerializerContext#SERIALIZER_uriRelativity
+        */
+       public SerializerGroupBuilder uriRelativity(UriRelativity value) {
+               return property(SERIALIZER_uriRelativity, value);
        }
 
        /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java 
b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java
index d89203b..9a96a30 100644
--- 
a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java
+++ 
b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java
@@ -53,8 +53,7 @@ public class SerializerSession extends BeanSession {
                sortMaps,
                abridged;
        private final char quoteChar;
-       private final String relativeUriBase, absolutePathUriBase;
-       private final UriContext uriContext;
+       private final UriResolver uriResolver;
 
        /** The current indentation depth into the model. */
        public int indent;
@@ -102,7 +101,8 @@ public class SerializerSession extends BeanSession {
                super(ctx, op, locale, timeZone, mediaType);
                this.javaMethod = javaMethod;
                this.output = output;
-               this.uriContext = (uriContext != null ? uriContext : 
ctx.uriContext);
+               UriResolution uriResolution;
+               UriRelativity uriRelativity;
                if (op == null || op.isEmpty()) {
                        maxDepth = ctx.maxDepth;
                        initialDepth = ctx.initialDepth;
@@ -115,11 +115,11 @@ public class SerializerSession extends BeanSession {
                        trimEmptyMaps = ctx.trimEmptyMaps;
                        trimStrings = ctx.trimStrings;
                        quoteChar = ctx.quoteChar;
-                       relativeUriBase = ctx.relativeUriBase;
-                       absolutePathUriBase = ctx.absolutePathUriBase;
                        sortCollections = ctx.sortCollections;
                        sortMaps = ctx.sortMaps;
                        abridged = ctx.abridged;
+                       uriResolution = ctx.uriResolution;
+                       uriRelativity = ctx.uriRelativity;
                } else {
                        maxDepth = op.getInt(SERIALIZER_maxDepth, ctx.maxDepth);
                        initialDepth = op.getInt(SERIALIZER_initialDepth, 
ctx.initialDepth);
@@ -132,13 +132,15 @@ public class SerializerSession extends BeanSession {
                        trimEmptyMaps = op.getBoolean(SERIALIZER_trimEmptyMaps, 
ctx.trimEmptyMaps);
                        trimStrings = op.getBoolean(SERIALIZER_trimStrings, 
ctx.trimStrings);
                        quoteChar = op.getString(SERIALIZER_quoteChar, 
""+ctx.quoteChar).charAt(0);
-                       relativeUriBase = 
op.getString(SERIALIZER_relativeUriBase, ctx.relativeUriBase);
-                       absolutePathUriBase = 
op.getString(SERIALIZER_absolutePathUriBase, ctx.absolutePathUriBase);
                        sortCollections = 
op.getBoolean(SERIALIZER_sortCollections, ctx.sortMaps);
                        sortMaps = op.getBoolean(SERIALIZER_sortMaps, 
ctx.sortMaps);
                        abridged = op.getBoolean(SERIALIZER_abridged, 
ctx.abridged);
+                       uriResolution = op.get(UriResolution.class, 
SERIALIZER_uriResolution, UriResolution.ROOT_RELATIVE);
+                       uriRelativity = op.get(UriRelativity.class, 
SERIALIZER_uriRelativity, UriRelativity.RESOURCE);
                }
 
+               uriResolver = new UriResolver(uriResolution, uriRelativity, 
uriContext == null ? ctx.uriContext : uriContext);
+
                this.indent = initialDepth;
                if (detectRecursions || isDebug()) {
                        set = new IdentityHashMap<Object,Object>();
@@ -244,12 +246,12 @@ public class SerializerSession extends BeanSession {
        }
 
        /**
-        * Returns the URI context passed in to this constructor.
+        * Returns the URI resolver.
         *
-        * @return The URI context passed in to this constructor.
+        * @return The URI resolver.
         */
-       public final UriContext getUriContext() {
-               return uriContext;
+       public final UriResolver getUriResolver() {
+               return uriResolver;
        }
 
        /**
@@ -370,24 +372,6 @@ public class SerializerSession extends BeanSession {
        }
 
        /**
-        * Returns the {@link SerializerContext#SERIALIZER_relativeUriBase} 
setting value for this session.
-        *
-        * @return The {@link SerializerContext#SERIALIZER_relativeUriBase} 
setting value for this session.
-        */
-       public final String getRelativeUriBase() {
-               return relativeUriBase;
-       }
-
-       /**
-        * Returns the {@link SerializerContext#SERIALIZER_absolutePathUriBase} 
setting value for this session.
-        *
-        * @return The {@link SerializerContext#SERIALIZER_absolutePathUriBase} 
setting value for this session.
-        */
-       public final String getAbsolutePathUriBase() {
-               return absolutePathUriBase;
-       }
-
-       /**
         * Push the specified object onto the stack.
         *
         * @param attrName The attribute name.
@@ -578,30 +562,67 @@ public class SerializerSession extends BeanSession {
        }
 
        /**
-        * Converts a String to an absolute URI based on the {@link 
SerializerContext#SERIALIZER_absolutePathUriBase} and
-        *      {@link SerializerContext#SERIALIZER_relativeUriBase} settings 
on this context.
+        * Converts a String to an absolute URI based on the {@link UriContext} 
on this session.
         *
         * @param uri The input URI.
+        *      Can be any of the following:
+        *      <ul>
+        *              <li>{@link java.net.URI}
+        *              <li>{@link java.net.URL}
+        *              <li>{@link CharSequence}
+        *      </ul>
+        *      URI can be any of the following forms:
+        *      <ul>
+        *              <li><js>"foo://foo"</js> - Absolute URI.
+        *              <li><js>"/foo"</js> - Root-relative URI.
+        *              <li><js>"/"</js> - Root URI.
+        *              <li><js>"context:/foo"</js> - Context-root-relative URI.
+        *              <li><js>"context:/"</js> - Context-root URI.
+        *              <li><js>"servlet:/foo"</js> - Servlet-path-relative URI.
+        *              <li><js>"servlet:/"</js> - Servlet-path URI.
+        *              <li><js>"request:/foo"</js> - Request-path-relative URI.
+        *              <li><js>"request:/"</js> - Request-path URI.
+        *              <li><js>"foo"</js> - Path-info-relative URI.
+        *              <li><js>""</js> - Path-info URI.
+        *      </ul>
         * @return The resolved URI.
         */
-       public String resolveUri(String uri) {
-               if (uri.indexOf("://") != -1 || (absolutePathUriBase == null && 
relativeUriBase == null))
-                       return uri;
-               StringBuilder sb = getStringBuilder();
-               if (StringUtils.startsWith(uri, '/')) {
-                       if (absolutePathUriBase != null)
-                               sb.append(absolutePathUriBase);
-               } else {
-                       if (relativeUriBase != null) {
-                               sb.append(relativeUriBase);
-                               if (! uri.equals("/"))
-                                       sb.append("/");
-                       }
-               }
-               sb.append(uri);
-               String s = sb.toString();
-               returnStringBuilder(sb);
-               return s;
+       public String resolveUri(Object uri) {
+               return uriResolver.resolve(uri);
+       }
+
+       /**
+        * Opposite of {@link #resolveUri(Object)}.
+        * <p>
+        * Converts the URI to a value relative to the specified 
<code>relativeTo</code> parameter.
+        * <p>
+        * Both parameters can be any of the following:
+        * <ul>
+        *      <li>{@link java.net.URI}
+        *      <li>{@link java.net.URL}
+        *      <li>{@link CharSequence}
+        * </ul>
+        * Both URIs can be any of the following forms:
+        * <ul>
+        *      <li><js>"foo://foo"</js> - Absolute URI.
+        *      <li><js>"/foo"</js> - Root-relative URI.
+        *      <li><js>"/"</js> - Root URI.
+        *      <li><js>"context:/foo"</js> - Context-root-relative URI.
+        *      <li><js>"context:/"</js> - Context-root URI.
+        *      <li><js>"servlet:/foo"</js> - Servlet-path-relative URI.
+        *      <li><js>"servlet:/"</js> - Servlet-path URI.
+        *      <li><js>"request:/foo"</js> - Request-path-relative URI.
+        *      <li><js>"request:/"</js> - Request-path URI.
+        *      <li><js>"foo"</js> - Path-info-relative URI.
+        *      <li><js>""</js> - Path-info URI.
+        * </ul>
+        *
+        * @param relativeTo The URI to relativize against.
+        * @param uri The URI to relativize.
+        * @return The relativized URI.
+        */
+       public String relativizeUri(Object relativeTo, Object uri) {
+               return uriResolver.relativize(relativeTo, uri);
        }
 
        /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerWriter.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerWriter.java 
b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerWriter.java
index 413aa63..3250d1a 100644
--- 
a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerWriter.java
+++ 
b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerWriter.java
@@ -16,7 +16,6 @@ import java.io.*;
 import java.net.*;
 
 import org.apache.juneau.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Simple wrapper around a standard {@link Writer} with additional methods.
@@ -43,14 +42,8 @@ public class SerializerWriter extends Writer {
        /** The quote character being used by this writer. */
        protected final char quoteChar;
 
-       /** The base (e.g. <js>https://localhost:9443/contextPath";</js>) for 
relative URIs (e.g. <js>"my/path"</js>). */
-       protected final String relativeUriBase;
-
-       /** The base (e.g. <js>https://localhost:9443";</js>) for relative URIs 
with absolute paths (e.g. <js>"/contextPath/my/path"</js>). */
-       protected final String absolutePathUriBase;
-
-       /** The URI context of the request. (i.e. the REST request URL broken 
down into authority/context/servlet/pathInfo parts. */
-       protected final UriContext uriContext;
+       /** The URI resolver of the request. */
+       protected final UriResolver uriResolver;
 
        /**
         * @param out The writer being wrapped.
@@ -58,19 +51,14 @@ public class SerializerWriter extends Writer {
         *      {@link #s()} will write a space character.
         * @param trimStrings If <jk>true</jk>, strings should be trimmed 
before they're serialized.
         * @param quoteChar The character to write when {@link #q()} is called.
-        * @param relativeUriBase The base (e.g. 
<js>https://localhost:9443/contextPath";</js>) for relative URIs (e.g. 
<js>"my/path"</js>).
-        * @param absolutePathUriBase The base (e.g. 
<js>https://localhost:9443";</js>) for relative URIs with absolute paths (e.g. 
<js>"/contextPath/my/path"</js>).
-        * @param uriContext The URI context.
-        *      Identifies the current request URI used for resolution of URIs 
to absolute or root-relative form.
+        * @param uriResolver The URI resolver for resolving URIs to absolute 
or root-relative form.
         */
-       public SerializerWriter(Writer out, boolean useWhitespace, boolean 
trimStrings, char quoteChar, String relativeUriBase, String 
absolutePathUriBase, UriContext uriContext) {
+       public SerializerWriter(Writer out, boolean useWhitespace, boolean 
trimStrings, char quoteChar, UriResolver uriResolver) {
                this.out = out;
                this.useWhitespace = useWhitespace;
                this.trimStrings = trimStrings;
                this.quoteChar = quoteChar;
-               this.relativeUriBase = relativeUriBase;
-               this.absolutePathUriBase = absolutePathUriBase;
-               this.uriContext = uriContext != null ? uriContext : new 
UriContext();
+               this.uriResolver = uriResolver;
        }
 
        /**
@@ -160,32 +148,17 @@ public class SerializerWriter extends Writer {
         * Object is converted to a <code>String</code> using 
<code>toString()</code>, so this will work on {@link URL} or {@link URI} 
objects,
         * or any other type that returns a URI via it's 
<code>toString()</code> method.
         * <p>
-        * If the URI is relative (i.e. without a schema and not prepended with 
<js>'/'</js>) the URI
-        * will be prepended with {@link #absolutePathUriBase} and {@link 
#relativeUriBase}.
-        * <p>
-        * If the URI is context-absolute (i.e. without a schema, but prepended 
with <js>'/'</js>)
-        * the URI will be prepended with {@link #absolutePathUriBase}.
-        *
+        * The URI is resolved based on the {@link 
SerializerContext#SERIALIZER_uriRelativity} and
+        * {@link SerializerContext#SERIALIZER_uriResolution} settings and the 
{@link UriContext} that's part of the 
+        * session.
+        * 
         * @param uri The URI to serialize.
         * @return This object (for method chaining).
         * @throws IOException If a problem occurred trying to write to the 
writer.
         */
        public SerializerWriter appendUri(Object uri) throws IOException {
-               String s = uri.toString();
-               if (s.indexOf("://") == -1) {
-                       if (StringUtils.startsWith(s, '/')) {
-                               if (absolutePathUriBase != null)
-                                       append(absolutePathUriBase);
-                       } else {
-                               if (relativeUriBase != null) {
-                                       append(relativeUriBase);
-                                       if (! relativeUriBase.equals("/"))
-                                               append("/");
-
-                               }
-                       }
-               }
-               return append(s);
+               uriResolver.append(this, uri);
+               return this;
        }
 
        /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializerBuilder.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializerBuilder.java
 
b/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializerBuilder.java
index 7436ddc..015e662 100644
--- 
a/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializerBuilder.java
+++ 
b/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializerBuilder.java
@@ -188,14 +188,20 @@ public class SoapXmlSerializerBuilder extends 
XmlSerializerBuilder {
        }
 
        @Override /* SerializerBuilder */
-       public SoapXmlSerializerBuilder relativeUriBase(String value) {
-               super.relativeUriBase(value);
+       public SoapXmlSerializerBuilder uriContext(UriContext value) {
+               super.uriContext(value);
                return this;
        }
 
        @Override /* SerializerBuilder */
-       public SoapXmlSerializerBuilder absolutePathUriBase(String value) {
-               super.absolutePathUriBase(value);
+       public SoapXmlSerializerBuilder uriResolution(UriResolution value) {
+               super.uriResolution(value);
+               return this;
+       }
+
+       @Override /* SerializerBuilder */
+       public SoapXmlSerializerBuilder uriRelativity(UriRelativity value) {
+               super.uriRelativity(value);
                return this;
        }
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java 
b/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java
index 2106637..3d0ee3d 100644
--- a/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java
@@ -169,14 +169,20 @@ public class UonSerializerBuilder extends 
SerializerBuilder {
        }
 
        @Override /* SerializerBuilder */
-       public UonSerializerBuilder relativeUriBase(String value) {
-               super.relativeUriBase(value);
+       public UonSerializerBuilder uriContext(UriContext value) {
+               super.uriContext(value);
                return this;
        }
 
        @Override /* SerializerBuilder */
-       public UonSerializerBuilder absolutePathUriBase(String value) {
-               super.absolutePathUriBase(value);
+       public UonSerializerBuilder uriResolution(UriResolution value) {
+               super.uriResolution(value);
+               return this;
+       }
+
+       @Override /* SerializerBuilder */
+       public UonSerializerBuilder uriRelativity(UriRelativity value) {
+               super.uriRelativity(value);
                return this;
        }
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerSession.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerSession.java 
b/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerSession.java
index 0f9b5a1..e9f9659 100644
--- a/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerSession.java
@@ -87,6 +87,6 @@ public class UonSerializerSession extends SerializerSession {
                Object output = getOutput();
                if (output instanceof UonWriter)
                        return (UonWriter)output;
-               return new UonWriter(this, super.getWriter(), 
isUseWhitespace(), isEncodeChars(), isTrimStrings(), getRelativeUriBase(), 
getAbsolutePathUriBase(), getUriContext());
+               return new UonWriter(this, super.getWriter(), 
isUseWhitespace(), isEncodeChars(), isTrimStrings(), getUriResolver());
        }
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/uon/UonWriter.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/uon/UonWriter.java 
b/juneau-core/src/main/java/org/apache/juneau/uon/UonWriter.java
index 85f9cd0..2844e62 100644
--- a/juneau-core/src/main/java/org/apache/juneau/uon/UonWriter.java
+++ b/juneau-core/src/main/java/org/apache/juneau/uon/UonWriter.java
@@ -53,13 +53,10 @@ public final class UonWriter extends SerializerWriter {
         * @param useWhitespace If <jk>true</jk>, tabs will be used in output.
         * @param encodeChars If <jk>true</jk>, special characters should be 
encoded.
         * @param trimStrings If <jk>true</jk>, strings should be trimmed 
before they're serialized.
-        * @param relativeUriBase The base (e.g. 
<js>https://localhost:9443/contextPath";</js>) for relative URIs (e.g. 
<js>"my/path"</js>).
-        * @param absolutePathUriBase The base (e.g. 
<js>https://localhost:9443";</js>) for relative URIs with absolute paths (e.g. 
<js>"/contextPath/my/path"</js>).
-        * @param uriContext The URI context.
-        *      Identifies the current request URI used for resolution of URIs 
to absolute or root-relative form.
+        * @param uriResolver The URI resolver for resolving URIs to absolute 
or root-relative form.
         */
-       protected UonWriter(UonSerializerSession session, Writer out, boolean 
useWhitespace, boolean encodeChars, boolean trimStrings, String 
relativeUriBase, String absolutePathUriBase, UriContext uriContext) {
-               super(out, useWhitespace, trimStrings, '\'', relativeUriBase, 
absolutePathUriBase, uriContext);
+       protected UonWriter(UonSerializerSession session, Writer out, boolean 
useWhitespace, boolean encodeChars, boolean trimStrings, UriResolver 
uriResolver) {
+               super(out, useWhitespace, trimStrings, '\'', uriResolver);
                this.session = session;
                this.encodeChars = encodeChars;
        }
@@ -167,20 +164,7 @@ public final class UonWriter extends SerializerWriter {
         */
        @Override
        public SerializerWriter appendUri(Object uri) throws IOException {
-               String s = uri.toString();
-               if (s.indexOf("://") == -1) {
-                       if (StringUtils.startsWith(s, '/')) {
-                               if (absolutePathUriBase != null)
-                                       append(absolutePathUriBase);
-                       } else {
-                               if (relativeUriBase != null) {
-                                       append(relativeUriBase);
-                                       if (! relativeUriBase.equals("/"))
-                                               append("/");
-                               }
-                       }
-               }
-               return appendObject(s, false, false);
+               return appendObject(uriResolver.resolve(uri), false, false);
        }
 
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerBuilder.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerBuilder.java
 
b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerBuilder.java
index e795a48..7c79631 100644
--- 
a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerBuilder.java
+++ 
b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerBuilder.java
@@ -231,14 +231,20 @@ public class UrlEncodingSerializerBuilder extends 
UonSerializerBuilder {
        }
 
        @Override /* SerializerBuilder */
-       public UrlEncodingSerializerBuilder relativeUriBase(String value) {
-               super.relativeUriBase(value);
+       public UrlEncodingSerializerBuilder uriContext(UriContext value) {
+               super.uriContext(value);
                return this;
        }
 
        @Override /* SerializerBuilder */
-       public UrlEncodingSerializerBuilder absolutePathUriBase(String value) {
-               super.absolutePathUriBase(value);
+       public UrlEncodingSerializerBuilder uriResolution(UriResolution value) {
+               super.uriResolution(value);
+               return this;
+       }
+
+       @Override /* SerializerBuilder */
+       public UrlEncodingSerializerBuilder uriRelativity(UriRelativity value) {
+               super.uriRelativity(value);
                return this;
        }
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializer.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializer.java 
b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializer.java
index 0e42c27..9a499d2 100644
--- a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializer.java
@@ -266,7 +266,7 @@ public class XmlSchemaSerializer extends XmlSerializer {
                        this.defaultNs = defaultNs;
                        this.targetNs = targetNs;
                        this.session = session;
-                       w = new XmlWriter(sw, session.isUseWhitespace(), 
session.isTrimStrings(), session.getQuoteChar(), null, null, null, true, null);
+                       w = new XmlWriter(sw, session.isUseWhitespace(), 
session.isTrimStrings(), session.getQuoteChar(), null, true, null);
                        int i = session.getIndent();
                        w.oTag(i, "schema");
                        w.attr("xmlns", xs.getUri());
@@ -418,7 +418,7 @@ public class XmlSchemaSerializer extends XmlSerializer {
                                                                        
Namespace cNs = first(xmlMeta.getNamespace(), 
ct2.getExtendedMeta(XmlClassMeta.class).getNamespace(), 
cm.getExtendedMeta(XmlClassMeta.class).getNamespace(), defaultNs);
                                                                        if 
(xmlMeta.getNamespace() == null) {
                                                                                
w.oTag(i+2, "element")
-                                                                               
        .attr("name", XmlUtils.encodeElementName(childName), true)
+                                                                               
        .attr("name", XmlUtils.encodeElementName(childName), false)
                                                                                
        .attr("type", getXmlType(cNs, ct2))
                                                                                
        .attr("minOccurs", 0);
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializerBuilder.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializerBuilder.java
 
b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializerBuilder.java
index 4af4739..9e24414 100644
--- 
a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializerBuilder.java
+++ 
b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializerBuilder.java
@@ -168,14 +168,20 @@ public class XmlSchemaSerializerBuilder extends 
XmlSerializerBuilder {
        }
 
        @Override /* SerializerBuilder */
-       public XmlSchemaSerializerBuilder relativeUriBase(String value) {
-               super.relativeUriBase(value);
+       public XmlSchemaSerializerBuilder uriContext(UriContext value) {
+               super.uriContext(value);
                return this;
        }
 
        @Override /* SerializerBuilder */
-       public XmlSchemaSerializerBuilder absolutePathUriBase(String value) {
-               super.absolutePathUriBase(value);
+       public XmlSchemaSerializerBuilder uriResolution(UriResolution value) {
+               super.uriResolution(value);
+               return this;
+       }
+
+       @Override /* SerializerBuilder */
+       public XmlSchemaSerializerBuilder uriRelativity(UriRelativity value) {
+               super.uriRelativity(value);
                return this;
        }
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializer.java 
b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializer.java
index cd46134..af5ce51 100644
--- a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializer.java
@@ -520,7 +520,7 @@ public class XmlSerializer extends WriterSerializer {
                // Render the tag contents.
                if (o != null) {
                        if (sType.isUri() || (pMeta != null && pMeta.isUri())) {
-                               out.appendUri(o);
+                               out.textUri(o);
                        } else if (sType.isCharSequence() || sType.isChar()) {
                                if (format == XMLTEXT)
                                        out.append(o);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializerBuilder.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializerBuilder.java 
b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializerBuilder.java
index dfdef5a..2e812b9 100644
--- a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializerBuilder.java
@@ -315,14 +315,20 @@ public class XmlSerializerBuilder extends 
SerializerBuilder {
        }
 
        @Override /* SerializerBuilder */
-       public XmlSerializerBuilder relativeUriBase(String value) {
-               super.relativeUriBase(value);
+       public XmlSerializerBuilder uriContext(UriContext value) {
+               super.uriContext(value);
                return this;
        }
 
        @Override /* SerializerBuilder */
-       public XmlSerializerBuilder absolutePathUriBase(String value) {
-               super.absolutePathUriBase(value);
+       public XmlSerializerBuilder uriResolution(UriResolution value) {
+               super.uriResolution(value);
+               return this;
+       }
+
+       @Override /* SerializerBuilder */
+       public XmlSerializerBuilder uriRelativity(UriRelativity value) {
+               super.uriRelativity(value);
                return this;
        }
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializerSession.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializerSession.java 
b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializerSession.java
index ef08f48..bd99974 100644
--- a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializerSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializerSession.java
@@ -200,6 +200,6 @@ public class XmlSerializerSession extends SerializerSession 
{
                Object output = getOutput();
                if (output instanceof XmlWriter)
                        return (XmlWriter)output;
-               return new XmlWriter(super.getWriter(), isUseWhitespace(), 
isTrimStrings(), getQuoteChar(), getRelativeUriBase(), 
getAbsolutePathUriBase(), getUriContext(), isEnableNamespaces(), 
getDefaultNamespace());
+               return new XmlWriter(super.getWriter(), isUseWhitespace(), 
isTrimStrings(), getQuoteChar(), getUriResolver(), isEnableNamespaces(), 
getDefaultNamespace());
        }
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/xml/XmlUtils.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/xml/XmlUtils.java 
b/juneau-core/src/main/java/org/apache/juneau/xml/XmlUtils.java
index 0567d73..483e06d 100644
--- a/juneau-core/src/main/java/org/apache/juneau/xml/XmlUtils.java
+++ b/juneau-core/src/main/java/org/apache/juneau/xml/XmlUtils.java
@@ -13,6 +13,7 @@
 package org.apache.juneau.xml;
 
 import java.io.*;
+import java.net.*;
 import java.util.*;
 
 import javax.xml.stream.*;
@@ -27,16 +28,110 @@ import org.apache.juneau.xml.annotation.*;
 public final class XmlUtils {
 
        
//--------------------------------------------------------------------------------
-       // Encode URI part
+       // XML element names
        
//--------------------------------------------------------------------------------
 
        /**
-        * Encodes invalid XML text characters to <code>_x####_</code> 
sequences.
+        * Encodes any invalid XML element name characters to 
<code>_x####_</code> sequences.
+        *
+        * @param w The writer to send the output to.
+        * @param o The object being encoded.
+        * @return The same writer passed in.
+        * @throws IOException Throw by the writer.
+        */
+       public static final Writer encodeElementName(Writer w, Object o) throws 
IOException {
+
+               if (o == null)
+                       return w.append("_x0000_");
+
+               String s = o.toString();
+
+               if (needsElementNameEncoding(s))
+                       return encodeElementNameInner(w, s);
+
+               w.append(s);
+               return w;
+       }
+
+       /**
+        * Encodes any invalid XML element name characters to 
<code>_x####_</code> sequences.
+        *
+        * @param o The object being encoded.
+        * @return The encoded element name string.
+        */
+       public static final String encodeElementName(Object o) {
+               if (o == null)
+                       return "_x0000_";
+
+               String s = o.toString();
+               if (s.isEmpty())
+                       return "_xE000_";
+               try {
+                       if (needsElementNameEncoding(s))
+                               return encodeElementNameInner(new 
StringBuilderWriter(s.length() * 2), s).toString();
+               } catch (IOException e) {
+                       throw new RuntimeException(e); // Never happens
+               }
+
+               return s;
+       }
+
+       private static final Writer encodeElementNameInner(Writer w, String s) 
throws IOException {
+               for (int i = 0; i < s.length(); i++) {
+                       char c = s.charAt(i);
+                       if ((c >= 'A' && c <= 'Z')
+                                       || (c == '_' && ! isEscapeSequence(s,i))
+                                       || (c >= 'a' && c <= 'z')
+                                       || (i != 0 && (
+                                                       c == '-'
+                                                       || c == '.'
+                                                       || (c >= '0' && c <= 
'9')
+                                                       || c == '\u00b7'
+                                                       || (c >= '\u0300' && c 
<= '\u036f')
+                                                       || (c >= '\u203f' && c 
<= '\u2040')
+                                               ))
+                                       || (c >= '\u00c0' && c <= '\u00d6')
+                                       || (c >= '\u00d8' && c <= '\u00f6')
+                                       || (c >= '\u00f8' && c <= '\u02ff')
+                                       || (c >= '\u0370' && c <= '\u037d')
+                                       || (c >= '\u037f' && c <= '\u1fff')
+                                       || (c >= '\u200c' && c <= '\u200d')
+                                       || (c >= '\u2070' && c <= '\u218f')
+                                       || (c >= '\u2c00' && c <= '\u2fef')
+                                       || (c >= '\u3001' && c <= '\ud7ff')
+                                       || (c >= '\uf900' && c <= '\ufdcf')
+                                       || (c >= '\ufdf0' && c <= '\ufffd')) {
+                               w.append(c);
+                       }  else {
+                               appendPaddedHexChar(w, c);
+                       }
+               }
+               return w;
+       }
+
+       private static final boolean needsElementNameEncoding(String s) {
+               // Note that this doesn't need to be perfect, just fast.
+               for (int i = 0; i < s.length(); i++) {
+                       char c = s.charAt(i);
+                       if (! (c >= '0' && c <= '9' || c >= 'a' && c <= 'z' || 
c >= 'A' && c <= 'Z'))
+                               return true;
+                       if (i == 0 && (c >= '0' && c <= '9'))
+                               return true;
+               }
+               return false;
+       }
+
+       
//--------------------------------------------------------------------------------
+       // XML element text
+       
//--------------------------------------------------------------------------------
+
+       /**
+        * Escapes invalid XML text characters to <code>_x####_</code> 
sequences.
         *
         * @param o The object being encoded.
         * @return The encoded string.
         */
-       public static final String encodeInvalidCharsForText(Object o) {
+       public static final String escapeText(Object o) {
 
                if (o == null)
                        return "_x0000_";
@@ -66,10 +161,12 @@ public final class XmlUtils {
        }
 
        /**
+        * Encodes the specified element text and sends the results to the 
specified writer.
+        * <p>
         * Encodes any invalid XML text characters to <code>_x####_</code> 
sequences and sends the response
         *      to the specified writer.
-        * Encodes <js>'&amp;'</js>, <js>'&lt;'</js>, and <js>'&gt;'</js> as 
XML entities.<br>
-        * Encodes invalid XML text characters to <code>_x####_</code> 
sequences.
+        * <br>Encodes <js>'&amp;'</js>, <js>'&lt;'</js>, and <js>'&gt;'</js> 
as XML entities.<br>
+        * <br>Encodes invalid XML text characters to <code>_x####_</code> 
sequences.
         *
         * @param w The writer to send the output to.
         * @param o The object being encoded.
@@ -97,18 +194,12 @@ public final class XmlUtils {
                                char c = s.charAt(i);
                                if ((i == 0 || i == len-1) && 
Character.isWhitespace(c) && ! preserveWhitespace)
                                        appendPaddedHexChar(w, c);
-                               else if (c == '&')
-                                       w.append("&amp;");
-                               else if (c == '<')
-                                       w.append("&lt;");
-                               else if (c == '>')
-                                       w.append("&gt;");
+                               else if (REPLACE_TEXT.contains(c))
+                                       w.append(REPLACE_TEXT.get(c));
                                else if (c == '_' && isEscapeSequence(s,i))
                                        appendPaddedHexChar(w, c);
                                else if (isValidXmlCharacter(c))
                                        w.append(c);
-                               else if (c == 0x09 || c == 0x0A || c == 0x0D)
-                                       
w.append("&#x000").append(Integer.toHexString(c)).append(";");
                                else
                                        appendPaddedHexChar(w, c);
                        }
@@ -119,7 +210,6 @@ public final class XmlUtils {
                return w;
        }
 
-
        private static final boolean needsTextEncoding(String s) {
                // See if we need to convert the string.
                // Conversion is somewhat expensive, so make sure we need to do 
so before hand.
@@ -128,116 +218,115 @@ public final class XmlUtils {
                        char c = s.charAt(i);
                        if ((i == 0 || i == len-1) && Character.isWhitespace(c))
                                return true;
-                       if (c == '&' || c == '<' || c == '>' || c == '\n' || ! 
isValidXmlCharacter(c) || (c == '_' && isEscapeSequence(s,i)))
+                       if (REPLACE_TEXT.contains(c) || ! 
isValidXmlCharacter(c) || (c == '_' && isEscapeSequence(s,i)))
                                return true;
                }
                return false;
        }
 
+       private static AsciiMap REPLACE_TEXT = new AsciiMap()
+               .append('&', "&amp;")
+               .append('<', "&lt;")
+               .append('>', "&gt;")
+               .append((char)0x09, "&#x0009;")
+               .append((char)0x0A, "&#x000a;")
+               .append((char)0x0D, "&#x000d;");
+
 
        
//--------------------------------------------------------------------------------
-       // Decode XML text
+       // XML attribute names
        
//--------------------------------------------------------------------------------
 
        /**
-        * Translates any _x####_ sequences (introduced by the various encode 
methods) back into their original characters.
+        * Serializes and encodes the specified object as valid XML attribute 
name.
         *
-        * @param s The string being decoded.
-        * @param sb The string builder to use as a scratch pad.
-        * @return The decoded string.
+        * @param w The writer to send the output to.
+        * @param o The object being serialized.
+        * @return This object (for method chaining).
+        * @throws IOException If a problem occurred.
         */
-       public static final String decode(String s, StringBuilder sb) {
-               if (s == null) return null;
-               if (s.length() == 0)
-                       return s;
-               if (s.indexOf('_') == -1)
-                       return s;
-
-               if (sb == null)
-                       sb = new StringBuilder(s.length());
-               for (int i = 0; i < s.length(); i++) {
-                       char c = s.charAt(i);
-                       if (c == '_' && isEscapeSequence(s,i)) {
+       public static final Writer encodeAttrName(Writer w, Object o) throws 
IOException {
 
-                               int x = Integer.parseInt(s.substring(i+2, i+6), 
16);
+               if (o == null)
+                       return w.append("_x0000_");
 
-                               // If we find _x0000_, then that means a null.
-                               // If we find _xE000_, then that means an empty 
string.
-                               if (x == 0)
-                                       return null;
-                               else if (x != 0xE000)
-                                       sb.append((char)x);
+               String s = o.toString();
 
-                               i+=6;
-                       } else {
-                               sb.append(c);
+               if (needsAttrNameEncoding(s)) {
+                       for (int i = 0; i < s.length(); i++) {
+                               char c = s.charAt(i);
+                               if (i == 0) {
+                                       if (c >= 'a' && c <= 'z' || c >= 'A' && 
c <= 'Z' || c == ':')
+                                               w.append(c);
+                                       else if (c == '_' && ! 
isEscapeSequence(s,i))
+                                               w.append(c);
+                                       else
+                                               appendPaddedHexChar(w, c);
+                               } else {
+                                       if ((c >= '0' && c <= '9' || c >= 'a' 
&& c <= 'z' || c >= 'A' && c <= 'Z' || c == ':'))
+                                               w.append(c);
+                                       else if (c == '_' && ! 
isEscapeSequence(s,i))
+                                               w.append(c);
+                                       else
+                                               appendPaddedHexChar(w, c);
+                               }
                        }
+               } else {
+                       w.append(s);
                }
-               return sb.toString();
-       }
-
 
-       /**
-        * Given a list of Strings and other Objects, combines Strings that are 
next to each other in the list.
-        *
-        * @param l The list of text nodes to collapse.
-        * @return The same list.
-        */
-       public static LinkedList<Object> collapseTextNodes(LinkedList<Object> 
l) {
+               return w;
+       }
 
-               String prev = null;
-               for (ListIterator<Object> i = l.listIterator(); i.hasNext();) {
-                       Object o = i.next();
-                       if (o instanceof String) {
-                               if (prev == null)
-                                       prev = o.toString();
-                               else {
-                                       prev += o;
-                                       i.remove();
-                                       i.previous();
-                                       i.remove();
-                                       i.add(prev);
-                               }
-                       } else {
-                               prev = null;
-                       }
+       private static final boolean needsAttrNameEncoding(String s) {
+               // Note that this doesn't need to be perfect, just fast.
+               for (int i = 0; i < s.length(); i++) {
+                       char c = s.charAt(i);
+                       if (! (c >= '0' && c <= '9' || c >= 'a' && c <= 'z' || 
c >= 'A' && c <= 'Z'))
+                               return true;
+                       if (i == 0 && ! (c >= 'a' && c <= 'z' || c >= 'A' && c 
<= 'Z'))
+                               return true;
                }
-               return l;
+               return false;
        }
 
-
        
//--------------------------------------------------------------------------------
-       // Encode XML attributes
+       // XML attribute values
        
//--------------------------------------------------------------------------------
 
        /**
-        * Serializes and encodes the specified object as valid XML attribute 
name.
+        * Encodes the specified attribute value and sends the results to the 
specified writer.
+        * <p>
+        * Encodes any invalid XML text characters to <code>_x####_</code> 
sequences and sends the response
+        *      to the specified writer.
+        * <br>Encodes <js>'&amp;'</js>, <js>'&lt;'</js>, <js>'&gt;'</js>, 
<js>'"'</js>, and <js>'\''</js> as XML entities.<br>
+        * <br?Encodes invalid XML text characters to <code>_x####_</code> 
sequences.
         *
         * @param w The writer to send the output to.
-        * @param o The object being serialized.
-        * @return This object (for method chaining).
-        * @throws IOException If a problem occurred.
+        * @param o The object being encoded.
+        * @param trim Trim the text before serializing it.
+        * If <jk>true</jk>, leading and trailing whitespace characters will be 
encoded.
+        * @return The same writer passed in.
+        * @throws IOException Thrown from the writer.
         */
-       public static final Writer encodeAttr(Writer w, Object o) throws 
IOException {
-
+       public static final Writer encodeAttrValue(Writer w, Object o, boolean 
trim) throws IOException {
                if (o == null)
                        return w.append("_x0000_");
 
                String s = o.toString();
+               if (s.isEmpty())
+                       return w;
+               if (trim)
+                       s = s.trim();
 
-               if (needsAttributeEncoding(s)) {
-                       for (int i = 0; i < s.length(); i++) {
+               if (needsAttrValueEncoding(s)) {
+                       final int len = s.length();
+                       for (int i = 0; i < len; i++) {
                                char c = s.charAt(i);
-                               if (c == '&')
-                                       w.append("&amp;");
-                               else if (c == '<')
-                                       w.append("&lt;");
-                               else if (c == '>')
-                                       w.append("&gt;");
-                               else if (c == '\'')
-                                       w.append("&apos;");
-                               else if (c == '"')
-                                       w.append("&quot;");
+                               if ((i == 0 || i == len-1) && 
Character.isWhitespace(c))
+                                       appendPaddedHexChar(w, c);
+                               else if (REPLACE_ATTR_VAL.contains(c))
+                                       w.append(REPLACE_ATTR_VAL.get(c));
                                else if (c == '_' && isEscapeSequence(s,i))
                                        appendPaddedHexChar(w, c);
                                else if (isValidXmlCharacter(c))
@@ -252,114 +341,101 @@ public final class XmlUtils {
                return w;
        }
 
-
-       private static boolean needsAttributeEncoding(String s) {
+       private static final boolean needsAttrValueEncoding(String s) {
                // See if we need to convert the string.
                // Conversion is somewhat expensive, so make sure we need to do 
so before hand.
-               for (int i = 0; i < s.length(); i++) {
+               final int len = s.length();
+               for (int i = 0; i < len; i++) {
                        char c = s.charAt(i);
-                       if (c == '&' || c == '<' || c == '>' || c == '\n' || c 
== '\'' || c == '"' || ! isValidXmlCharacter(c))
+                       if ((i == 0 || i == len-1) && Character.isWhitespace(c))
+                               return true;
+                       if (REPLACE_ATTR_VAL.contains(c) || ! 
isValidXmlCharacter(c) || (c == '_' && isEscapeSequence(s,i)))
                                return true;
                }
                return false;
        }
 
+       private static AsciiMap REPLACE_ATTR_VAL = new AsciiMap()
+               .append('&', "&amp;")
+               .append('<', "&lt;")
+               .append('>', "&gt;")
+               .append('"', "&quot;")
+               .append('\'', "&apos;")
+               .append((char)0x09, "&#x0009;")
+               .append((char)0x0A, "&#x000a;")
+               .append((char)0x0D, "&#x000d;");
+
 
        
//--------------------------------------------------------------------------------
-       // Encode XML element names
+       // Decode XML text
        
//--------------------------------------------------------------------------------
 
        /**
-        * Encodes any invalid XML element name characters to 
<code>_x####_</code> sequences.
+        * Translates any _x####_ sequences (introduced by the various encode 
methods) back into their original characters.
         *
-        * @param w The writer to send the output to.
-        * @param o The object being encoded.
-        * @return The same writer passed in.
-        * @throws IOException Throw by the writer.
+        * @param s The string being decoded.
+        * @param sb The string builder to use as a scratch pad.
+        * @return The decoded string.
         */
-       public static final Writer encodeElementName(Writer w, Object o) throws 
IOException {
+       public static final String decode(String s, StringBuilder sb) {
+               if (s == null) return null;
+               if (s.length() == 0)
+                       return s;
+               if (s.indexOf('_') == -1)
+                       return s;
 
-               if (o == null)
-                       return w.append("_x0000_");
+               if (sb == null)
+                       sb = new StringBuilder(s.length());
+               for (int i = 0; i < s.length(); i++) {
+                       char c = s.charAt(i);
+                       if (c == '_' && isEscapeSequence(s,i)) {
 
-               String s = o.toString();
+                               int x = Integer.parseInt(s.substring(i+2, i+6), 
16);
 
-               if (needsElementNameEncoding(s))
-                       return encodeElementNameInner(w, s);
+                               // If we find _x0000_, then that means a null.
+                               // If we find _xE000_, then that means an empty 
string.
+                               if (x == 0)
+                                       return null;
+                               else if (x != 0xE000)
+                                       sb.append((char)x);
 
-               w.append(s);
-               return w;
+                               i+=6;
+                       } else {
+                               sb.append(c);
+                       }
+               }
+               return sb.toString();
        }
 
+
        /**
-        * Encodes any invalid XML element name characters to 
<code>_x####_</code> sequences.
+        * Given a list of Strings and other Objects, combines Strings that are 
next to each other in the list.
         *
-        * @param o The object being encoded.
-        * @return The encoded element name string.
+        * @param l The list of text nodes to collapse.
+        * @return The same list.
         */
-       public static final String encodeElementName(Object o) {
-               if (o == null)
-                       return "_x0000_";
-
-               String s = o.toString();
-               if (s.isEmpty())
-                       return "_xE000_";
-               try {
-                       if (needsElementNameEncoding(s))
-                               return encodeElementNameInner(new 
StringBuilderWriter(s.length() * 2), s).toString();
-               } catch (IOException e) {
-                       throw new RuntimeException(e); // Never happens
-               }
-
-               return s;
-       }
+       public static LinkedList<Object> collapseTextNodes(LinkedList<Object> 
l) {
 
-       private static final Writer encodeElementNameInner(Writer w, String s) 
throws IOException {
-               for (int i = 0; i < s.length(); i++) {
-                       char c = s.charAt(i);
-                       if ((c >= 'A' && c <= 'Z')
-                                       || (c == '_' && ! isEscapeSequence(s,i))
-                                       || (c >= 'a' && c <= 'z')
-                                       || (i != 0 && (
-                                                       c == '-'
-                                                       || c == '.'
-                                                       || (c >= '0' && c <= 
'9')
-                                                       || c == '\u00b7'
-                                                       || (c >= '\u0300' && c 
<= '\u036f')
-                                                       || (c >= '\u203f' && c 
<= '\u2040')
-                                               ))
-                                       || (c >= '\u00c0' && c <= '\u00d6')
-                                       || (c >= '\u00d8' && c <= '\u00f6')
-                                       || (c >= '\u00f8' && c <= '\u02ff')
-                                       || (c >= '\u0370' && c <= '\u037d')
-                                       || (c >= '\u037f' && c <= '\u1fff')
-                                       || (c >= '\u200c' && c <= '\u200d')
-                                       || (c >= '\u2070' && c <= '\u218f')
-                                       || (c >= '\u2c00' && c <= '\u2fef')
-                                       || (c >= '\u3001' && c <= '\ud7ff')
-                                       || (c >= '\uf900' && c <= '\ufdcf')
-                                       || (c >= '\ufdf0' && c <= '\ufffd')) {
-                               w.append(c);
-                       }  else {
-                               appendPaddedHexChar(w, c);
+               String prev = null;
+               for (ListIterator<Object> i = l.listIterator(); i.hasNext();) {
+                       Object o = i.next();
+                       if (o instanceof String) {
+                               if (prev == null)
+                                       prev = o.toString();
+                               else {
+                                       prev += o;
+                                       i.remove();
+                                       i.previous();
+                                       i.remove();
+                                       i.add(prev);
+                               }
+                       } else {
+                               prev = null;
                        }
                }
-               return w;
-       }
-
-       private static final boolean needsElementNameEncoding(String s) {
-               // Note that this doesn't need to be perfect, just fast.
-               for (int i = 0; i < s.length(); i++) {
-                       char c = s.charAt(i);
-                       if (! (c >= '0' && c <= '9' || c >= 'a' && c <= 'z' || 
c >= 'A' && c <= 'Z'))
-                               return true;
-                       if (i == 0 && (c >= '0' && c <= '9'))
-                               return true;
-               }
-               return false;
+               return l;
        }
 
-
        
//--------------------------------------------------------------------------------
        // Other methods
        
//--------------------------------------------------------------------------------
@@ -501,4 +577,32 @@ public final class XmlUtils {
                        return "ENTITY_DECLARATION";
                return "UNKNOWN";
        }
+
+       /**
+        * Shortcut for calling 
<code>URLEncoder.<jsm>encode</jsm>(o.toString(), <js>"UTF-8"</js>)</code>.
+        *
+        * @param o The object to encode.
+        * @return The URL encoded string, or <jk>null</jk> if the object was 
null.
+        */
+       public static String urlEncode(Object o) {
+               try {
+                       if (o != null)
+                               return URLEncoder.encode(o.toString(), "UTF-8");
+               } catch (UnsupportedEncodingException e) {}
+               return null;
+       }
+
+       /**
+        * Shortcut for calling 
<code>URLEncoder.<jsm>decode</jsm>(o.toString(), <js>"UTF-8"</js>)</code>.
+        *
+        * @param s The string to decode.
+        * @return The decoded string, or <jk>null</jk> if the string was null.
+        */
+       public static String urlDecode(String s) {
+               try {
+                       if (s != null)
+                               return URLDecoder.decode(s, "UTF-8");
+               } catch (UnsupportedEncodingException e) {}
+               return null;
+       }
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/xml/XmlWriter.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/xml/XmlWriter.java 
b/juneau-core/src/main/java/org/apache/juneau/xml/XmlWriter.java
index 6b8caeb..d1ed78e 100644
--- a/juneau-core/src/main/java/org/apache/juneau/xml/XmlWriter.java
+++ b/juneau-core/src/main/java/org/apache/juneau/xml/XmlWriter.java
@@ -38,15 +38,12 @@ public class XmlWriter extends SerializerWriter {
         * @param useWhitespace If <jk>true</jk> XML elements will be indented.
         * @param trimStrings If <jk>true</jk>, strings should be trimmed 
before they're serialized.
         * @param quoteChar The quote character to use for attributes.  Should 
be <js>'\''</js> or <js>'"'</js>.
-        * @param relativeUriBase The base (e.g. 
<js>https://localhost:9443/contextPath";</js>) for relative URIs (e.g. 
<js>"my/path"</js>).
-        * @param absolutePathUriBase The base (e.g. 
<js>https://localhost:9443";</js>) for relative URIs with absolute paths (e.g. 
<js>"/contextPath/my/path"</js>).
-        * @param uriContext The URI context.
-        *      Identifies the current request URI used for resolution of URIs 
to absolute or root-relative form.
+        * @param uriResolver The URI resolver for resolving URIs to absolute 
or root-relative form.
         * @param enableNs Flag to indicate if XML namespaces are enabled.
         * @param defaultNamespace The default namespace if XML namespaces are 
enabled.
         */
-       public XmlWriter(Writer out, boolean useWhitespace, boolean 
trimStrings, char quoteChar, String relativeUriBase, String 
absolutePathUriBase, UriContext uriContext, boolean enableNs, Namespace 
defaultNamespace) {
-               super(out, useWhitespace, trimStrings, quoteChar, 
relativeUriBase, absolutePathUriBase, uriContext);
+       public XmlWriter(Writer out, boolean useWhitespace, boolean 
trimStrings, char quoteChar, UriResolver uriResolver, boolean enableNs, 
Namespace defaultNamespace) {
+               super(out, useWhitespace, trimStrings, quoteChar, uriResolver);
                this.enableNs = enableNs;
                this.defaultNsPrefix = defaultNamespace == null ? null : 
defaultNamespace.name;
        }
@@ -404,17 +401,12 @@ public class XmlWriter extends SerializerWriter {
         * @param ns The namespace.  Can be <jk>null</jk>.
         * @param name The attribute name.
         * @param value The attribute value.
-        * @param needsEncoding If <jk>true</jk>, attribute name will be 
encoded.
+        * @param valNeedsEncoding If <jk>true</jk>, attribute name will be 
encoded.
         * @return This object (for method chaining).
         * @throws IOException If a problem occurred.
         */
-       public XmlWriter attr(String ns, String name, Object value, boolean 
needsEncoding) throws IOException {
-               oAttr(ns, name).q();
-               if (needsEncoding)
-                       encodeAttr(value);
-               else
-                       append(value);
-               return q();
+       public XmlWriter attr(String ns, String name, Object value, boolean 
valNeedsEncoding) throws IOException {
+               return oAttr(ns, name).q().attrValue(value, 
valNeedsEncoding).q();
        }
 
        /**
@@ -422,12 +414,12 @@ public class XmlWriter extends SerializerWriter {
         *
         * @param name The attribute name.
         * @param value The attribute value.
-        * @param needsEncoding If <jk>true</jk>, attribute name will be 
encoded.
+        * @param valNeedsEncoding If <jk>true</jk>, attribute name will be 
encoded.
         * @return This object (for method chaining).
         * @throws IOException If a problem occurred.
         */
-       public XmlWriter attr(String name, Object value, boolean needsEncoding) 
throws IOException {
-               return attr(null, name, value, needsEncoding);
+       public XmlWriter attr(String name, Object value, boolean 
valNeedsEncoding) throws IOException {
+               return attr(null, name, value, valNeedsEncoding);
        }
 
        /**
@@ -440,11 +432,11 @@ public class XmlWriter extends SerializerWriter {
         * @throws IOException If a problem occurred.
         */
        public XmlWriter attr(String ns, String name, Object value) throws 
IOException {
-               return oAttr(ns, name).q().append(value).q();
+               return oAttr(ns, name).q().attrValue(value, false).q();
        }
 
        /**
-        * Same as {@link #attr(String, Object, boolean)}, except pass in a 
{@link Namespace} object for the namespace.
+        * Same as {@link #attr(String, String, Object)}, except pass in a 
{@link Namespace} object for the namespace.
         *
         * @param ns The namespace.  Can be <jk>null</jk>.
         * @param name The attribute name.
@@ -453,7 +445,7 @@ public class XmlWriter extends SerializerWriter {
         * @throws IOException If a problem occurred.
         */
        public XmlWriter attr(Namespace ns, String name, Object value) throws 
IOException {
-               return oAttr(ns == null ? null : ns.name, 
name).q().append(value).q();
+               return oAttr(ns == null ? null : ns.name, 
name).q().attrValue(value, false).q();
        }
 
        /**
@@ -507,8 +499,7 @@ public class XmlWriter extends SerializerWriter {
         * @throws IOException If a problem occurred.
         */
        public XmlWriter attrUri(Namespace ns, String name, Object value) 
throws IOException {
-               oAttr(ns, name).q().appendUri(value).q();
-               return this;
+               return attr(ns, name, uriResolver.resolve(value));
        }
 
        /**
@@ -521,8 +512,7 @@ public class XmlWriter extends SerializerWriter {
         * @throws IOException If a problem occurred.
         */
        public XmlWriter attrUri(String ns, String name, Object value) throws 
IOException {
-               oAttr(ns, name).q().appendUri(value).q();
-               return this;
+               return attr(ns, name, uriResolver.resolve(value), true);
        }
 
        /**
@@ -551,14 +541,22 @@ public class XmlWriter extends SerializerWriter {
        }
 
        /**
-        * Serializes and encodes the specified object as valid XML attribute 
name.
+        * Same as {@link #text(Object)} but treats the value as a URL to 
resolved then serialized.
         *
         * @param o The object being serialized.
         * @return This object (for method chaining).
-        * @throws IOException If a problem occurred.
+        * @throws IOException
         */
-       public XmlWriter encodeAttr(Object o) throws IOException {
-               XmlUtils.encodeAttr(out, o);
+       public XmlWriter textUri(Object o) throws IOException {
+               text(uriResolver.resolve(o), false);
+               return this;
+       }
+
+       private XmlWriter attrValue(Object o, boolean needsEncoding) throws 
IOException {
+               if (needsEncoding)
+                       XmlUtils.encodeAttrValue(out, o, this.trimStrings);
+               else
+                       append(o.toString());
                return this;
        }
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/javadoc/overview.html
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/javadoc/overview.html 
b/juneau-core/src/main/javadoc/overview.html
index fe24402..64714b6 100644
--- a/juneau-core/src/main/javadoc/overview.html
+++ b/juneau-core/src/main/javadoc/overview.html
@@ -2187,14 +2187,30 @@
        <p class='bcode'>
        <ja>@RestResource</ja>(
                path=<js>"/systemProperties"</js>,
+               
+               <jc>// Title and description that show up on HTML rendition 
page.
+               // Also used in Swagger doc.</jc>
                title=<js>"System properties resource"</js>,
                description=<js>"REST interface for performing CRUD operations 
on system properties."</js>,
-               
pageLinks=<js>"{up:'$R{requestParentURI}',options:'?method=OPTIONS'}"</js>,
+               
+               <jc>// Links on the HTML rendition page.
+               // "request:/..." URIs are relative to the request URI.
+               // "servlet:/..." URIs are relative to the servlet URI.</jc>
+               
pageLinks=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js>,
+               
+               <jc>// Properties that get applied to all serializers and 
parsers.</jc>
                properties={
+                       <jc>// Use single quotes.</jc>
                        
<ja>@Property</ja>(name=<jsf>SERIALIZER_quoteChar</jsf>, value=<js>"'"</js>)
                },
+               
+               <jc>// Our stylesheet for the HTML rendition.</jc>
                stylesheet=<js>"styles/devops.css"</js>,
+               
+               <jc>// Support GZIP encoding on Accept-Encoding header.</jc>
                encoders=GzipEncoder.<jk>class</jk>,
+
+               <jc>// Swagger info.</jc>
                contact=<js>"{name:'John Smith',email:'[email protected]'}"</js>,
                license=<js>"{name:'Apache 
2.0',url:'http://www.apache.org/licenses/LICENSE-2.0.html'}"</js>,
                version=<js>"2.0"</js>,
@@ -3076,7 +3092,7 @@
        <ja>@RestResource</ja>( 
                messages=<js>"nls/HelloWorldResource"</js>, 
                path=<js>"/helloWorld"</js>, 
-               
pageLinks=<js>"{up:'$R{requestParentURI}',options:'?method=OPTIONS'}"</js>
+               
pageLinks=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js>
        ) 
        <jk>public class</jk> HelloWorldResource <jk>extends</jk> Resource { 
                <jk>private static final long</jk> <jsf>serialVersionUID</jsf> 
= 1L; 
@@ -3151,7 +3167,7 @@
        <ja>@RestResource</ja>( 
                path=<js>"/methodExample"</js>, 
                messages=<js>"nls/MethodExampleResource"</js>, 
-               
pageLinks=<js>"{up:'$R{requestParentURI}',options:'?method=OPTIONS'}"</js>
+               
pageLinks=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js>
        ) 
        <jk>public class</jk> MethodExampleResource <jk>extends</jk> Resource { 
                <jk>private static final long</jk> <jsf>serialVersionUID</jsf> 
= 1L; 
@@ -3620,7 +3636,7 @@
        <ja>@RestResource</ja>(
                path=<js>"/echo"</js>,
                messages=<js>"nls/RequestEchoResource"</js>,
-               
pageLinks=<js>"{up:'$R{requestParentURI}',options:'?method=OPTIONS'}"</js>,
+               
pageLinks=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js>,
                properties={
                        <ja>@Property</ja>(name=<jsf>SERIALIZER_maxDepth</jsf>, 
value=<js>"10"</js>),
                        
<ja>@Property</ja>(name=<jsf>SERIALIZER_detectRecursions</jsf>, 
value=<js>"true"</js>)
@@ -4075,18 +4091,42 @@
        <ja>@RestResource</ja>( 
                path=<js>"/addressBook"</js>, 
                messages=<js>"nls/AddressBookResource"</js>, 
-               
pageLinks=<js>"{up:'$R{requestParentURI}',options:'?method=OPTIONS'}"</js>, 
-               properties={ 
-                       
<ja>@Property</ja>(name=<jsf>REST_allowMethodParam</jsf>, value=<js>"*"</js>), 
-                       <ja>@Property</ja>(name=<jsf>HTML_uriAnchorText</jsf>, 
value=<jsf>TO_STRING</jsf>), 
-                       
<ja>@Property</ja>(name=<jsf>SERIALIZER_quoteChar</jsf>, value=<js>"'"</js>), 
-                       <ja>@Property</ja>(name=<jsf>RDF_rdfxml_tab</jsf>, 
value=<js>"5"</js>), 
-                       <ja>@Property</ja>(name=<jsf>RDF_addRootProperty</jsf>, 
value=<js>"true"</js>), 
-                       <jc>// Resolve all relative URIs so that they're 
relative to this servlet!</jc> 
-                       
<ja>@Property</ja>(name=<jsf>SERIALIZER_relativeUriBase</jsf>, 
value=<js>"$R{servletURI}"</js>), 
-               }, 
+
+               <jc>// Links on the HTML rendition page.
+               // "request:/..." URIs are relative to the request URI.
+               // "servlet:/..." URIs are relative to the servlet URI.
+               // "$C{...}" variables are pulled from the config file.</jc>
+               pageLinks=<js>"{up:'request:/..', 
options:'servlet:/?method=OPTIONS', 
source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/addressbook/AddressBookResource.java'}"</js>,
+
+               <jc>// Properties that get applied to all serializers and 
parsers.</jc>
+               properties={
+                       
+                       <jc>// Allow INIT as a method parameter.</jc>
+                       
<ja>@Property</ja>(name=<jsf>REST_allowMethodParam</jsf>, value=<js>"*"</js>),
+       
+                       <jc>// Use single quotes.</jc>
+                       
<ja>@Property</ja>(name=<jsf>SERIALIZER_quoteChar</jsf>, value=<js>"'"</js>),
+                       
+                       <jc>// Make RDF/XML readable.</jc>
+                       <ja>@Property</ja>(name=<jsf>RDF_rdfxml_tab</jsf>, 
value=<js>"5"</js>),
+                       
+                       <jc>// Make RDF parsable by adding a root node.</jc>
+                       <ja>@Property</ja>(name=<jsf>RDF_addRootProperty</jsf>, 
value=<js>"true"</js>),
+                       
+                       <jc>// Make URIs absolute so that we can easily 
reference them on the client side.</jc>
+                       
<ja>@Property</ja>(name=<jsf>SERIALIZER_uriResolution</jsf>, 
value=<js>"ABSOLUTE"</js>)
+               
+                       <jc>// Make the anchor text on URLs be just the path 
relative to the servlet.</jc>
+                       <ja>@Property</ja>(name=<jsf>HTML_uriAnchorText</jsf>, 
value=<js>"SERVLET_RELATIVE"</js>)
+               },
+               
+               <jc>// Our stylesheet for the HTML rendition.</jc>
                stylesheet=<js>"styles/devops.css"</js>,
+               
+               <jc>// Support GZIP encoding on Accept-Encoding header.</jc>
                encoders=GzipEncoder.<jk>class</jk>,
+               
+               <jc>// Swagger info.</jc>
                contact=<js>"{name:'John Smith',email:'[email protected]'}"</js>,
                license=<js>"{name:'Apache 
2.0',url:'http://www.apache.org/licenses/LICENSE-2.0.html'}"</js>,
                version=<js>"2.0"</js>,
@@ -4105,7 +4145,7 @@
                
                        <jk>try</jk> { 
                                <jc>// Create the address book</jc> 
-                               <jf>addressBook</jf> = <jk>new</jk> 
AddressBook(java.net.URI.create(<js>""</js>)); 
+                               <jf>addressBook</jf> = <jk>new</jk> 
AddressBook(java.net.URI.create(<js>"servlet:/"</js>)); 
                                
                                <jc>// Add some people to our address book by 
default</jc> 
                                <jf>addressBook</jf>.createPerson( 
@@ -4724,7 +4764,7 @@
                messages=<js>"nls/SampleRemoteableServlet"</js>, 
                title=<js>"Remoteable Service Proxy API"</js>, 
                description=<js>"Sample class showing how to use remoteable 
proxies. The list below are exposed services that can be retrieved using 
RestClient.getProxyInterface(Class)."</js>, 
-               
pageLinks=<js>"{up:'$R{requestParentURI}',options:'?method=OPTIONS'}"</js>, 
+               
pageLinks=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js>, 
                properties={ 
                        <jc>// Allow us to use method=POST from a browser.</jc> 
                        
<ja>@Property</ja>(name=<jsf>REST_allowMethodParam</jsf>, value=<js>"*"</js>) 
@@ -4827,7 +4867,7 @@
        <ja>@RestResource</ja>( 
                path=<js>"/tempDir"</js>, 
                messages=<js>"nls/TempDirResource"</js>, 
-               
pageLinks=<js>"{up:'$R{requestParentURI}',options:'?method=OPTIONS',upload:'upload'}"</js>,
+               pageLinks=<js>"{up:'request:/..', 
options:'servlet:/?method=OPTIONS', upload:'servlet:/upload'}"</js>,
                properties={ 
                        
<ja>@Property</ja>(name=<js>"DirectoryResource.rootDir"</js>, 
value=<js>"$S{java.io.tmpdir}"</js>), 
                        
<ja>@Property</ja>(name=<js>"DirectoryResource.allowViews"</js>, 
value=<js>"true"</js>), 
@@ -4945,7 +4985,7 @@
        <ja>@RestResource</ja>( 
                path=<js>"/atom"</js>, 
                messages=<js>"nls/AtomFeedResource"</js>, 
-               
pageLinks=<js>"{up:'$R{requestParentURI}',options:'?method=OPTIONS'}"</js>,
+               
pageLinks=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js>,
                properties={ 
                        
<ja>@Property</ja>(name=<jsf>SERIALIZER_quoteChar</jsf>, value=<js>"'"</js>), 
                        <ja>@Property</ja>(name=<jsf>RDF_rdfxml_tab</jsf>, 
value=<js>"5"</js>), 
@@ -5053,7 +5093,7 @@
        <ja>@RestResource</ja>( 
                path=<js>"/docker"</js>, 
                title=<js>"Sample Docker resource"</js>, 
-               
pageLinks=<js>"{up:'$R{requestParentURI}',options:'?method=OPTIONS'}"</js> 
+               
pageLinks=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js> 
        ) 
        <jk>public class</jk> DockerRegistryResource <jk>extends</jk> Resource 
{ 
                <jk>private static final long</jk> <jsf>serialVersionUID</jsf> 
= 1L; 
@@ -5134,7 +5174,7 @@
                messages=<js>"nls/TumblrParserResource"</js>, 
                title=<js>"Tumblr parser service"</js>, 
                description=<js>"Specify a URL to a Tumblr blog and parse the 
results."</js>, 
-               
pageLinks=<js>"{up:'$R{requestParentURI}',options:'?method=OPTIONS'}"</js> 
+               
pageLinks=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js> 
        ) 
        <jk>public class</jk> TumblrParserResource <jk>extends</jk> Resource { 
                <jk>private static final long</jk> <jsf>serialVersionUID</jsf> 
= 1L; 
@@ -5355,7 +5395,7 @@
                path=<js>"/jsonSchema"</js>, 
                messages=<js>"nls/JsonSchemaResource"</js>, 
                title=<js>"Sample JSON-Schema document"</js>, 
-               
pageLinks=<js>"{up:'$R{requestParentURI}',options:'?method=OPTIONS'}"</js> 
+               
pageLinks=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js> 
        ) 
        <jk>public class</jk> JsonSchemaResource <jk>extends</jk> ResourceJena 
{ 
                <jk>private static final long</jk> <jsf>serialVersionUID</jsf> 
= 1L; 
@@ -5436,7 +5476,7 @@
                messages=<js>"nls/SqlQueryResource"</js>, 
                title=<js>"SQL query service"</js>, 
                description=<js>"Executes queries against the local derby 
'$C{SqlQueryResource/connectionUrl}' database"</js>, 
-               
pageLinks=<js>"{up:'$R{requestParentURI}',options:'?method=OPTIONS'}"</js> 
+               
pageLinks=<js>"{up:'request:/..',options:'servlet:/?method=OPTIONS'}"</js> 
        ) 
        <jk>public class</jk> SqlQueryResource <jk>extends</jk> Resource { 
                <jk>private static final long</jk> <jsf>serialVersionUID</jsf> 
= 1L; 
@@ -5623,7 +5663,7 @@
                path=<js>"/config"</js>, 
                title=<js>"Configuration"</js>, 
                description=<js>"Contents of configuration file."</js>, 
-               
pageLinks=<js>"{up:'$R{requestParentURI}',options:'?method=OPTIONS',edit:'edit'}"</js>
+               pageLinks=<js>"{up:'request:/..', 
options:'servlet:/?method=OPTIONS', edit:'servlet:/edit'}"</js>
        ) 
        <jk>public class</jk> ConfigResource <jk>extends</jk> Resource { 
                <jk>private static final long</jk> <jsf>serialVersionUID</jsf> 
= 1L; 
@@ -6150,6 +6190,39 @@
                                        <li>{@link 
org.apache.juneau.remoteable.Header#serializer} 
                                        <li>{@link 
org.apache.juneau.remoteable.HeaderIfNE#serializer} 
                                </ul>
+                       <li>Across-the-board improvements to the URI-resolution 
support (i.e. how URIs get serialized).
+                               <ul>
+                                       <li>New support for resolving URIs with 
the following newly-recognized protocols:
+                                               <ul>
+                                                       
<li><js>"context:/..."</js> - Relative to context-root of the application.
+                                                       
<li><js>"servlet:/..."</js> - Relative to the servlet URI.
+                                                       
<li><js>"request:/..."</js> - Relative to the request URI.
+                                               </ul>
+                                               For example, currently we 
define HTML page links using variables and servlet-relative URIs...
+                                               <p class='bcode'>
+       pageLinks=<js>"{up:'$R{requestParentURI}', options:'?method=OPTIONS', 
upload:'upload'}"</js>
+                                               </p>
+                                               With these new protocols, we 
can define them like so:
+                                               <p class='bcode'>
+       pageLinks=<js>"{top:'context:/', up:'request:/..' 
,options:'servlet:/?method=OPTIONS', upload:'servlet:/upload'}"</js>
+                                               </p>
+                                               The old method of using 
variables and servlet-relative URIs will still be supported, but using 
+                                               these new protocols should 
(hopefully) be easier to understand.
+                                               <br>
+                                               These protocols work on all 
serialized URL and URI objects, as well as classes and properties 
+                                               annotated with {@link 
org.apache.juneau.annotation.URI @URI}.
+                                       <li>New classes:
+                                               <ul>
+                                                       <li>{@link 
org.apache.juneau.UriContext}
+                                                       <li>{@link 
org.apache.juneau.UriRelativity}
+                                                       <li>{@link 
org.apache.juneau.UriResolution}
+                                                       <li>{@link 
org.apache.juneau.UriResolver}
+                                               </ul>
+                                       <li>New configuration properties:
+                                               <li>{@link 
org.apache.juneau.serializer.SerializerContext#SERIALIZER_uriContext}
+                                               <li>{@link 
org.apache.juneau.serializer.SerializerContext#SERIALIZER_uriRelativity}
+                                               <li>{@link 
org.apache.juneau.serializer.SerializerContext#SERIALIZER_uriResolution}
+                               </ul>
                </ul>
 
                <h6 class='topic'>org.apache.juneau.rest</h6>
@@ -7839,8 +7912,8 @@
                <ul class='spaced-list'>
                        <li>New properties in {@link 
org.apache.juneau.serializer.SerializerContext}:
                                <ol>
-                                       <li>{@link 
org.apache.juneau.serializer.SerializerContext#SERIALIZER_relativeUriBase}
-                                       <li>{@link 
org.apache.juneau.serializer.SerializerContext#SERIALIZER_absolutePathUriBase}
+                                       
<li><code><del>SerializerContext.SERIALIZER_relativeUriBase</del></code>
+                                       
<li><code><del>SerializerContext.SERIALIZER_absolutePathUriBase</del></code>
                                </ol>
                                These replace the 
<code>SERIALIZER_uriAuthority</code> and <code>SERIALIZER_uriContext</code> 
properties.
                        </li>

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-examples-rest/src/main/java/org/apache/juneau/examples/addressbook/Person.java
----------------------------------------------------------------------
diff --git 
a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/addressbook/Person.java
 
b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/addressbook/Person.java
index 1d8c73c..e95806a 100755
--- 
a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/addressbook/Person.java
+++ 
b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/addressbook/Person.java
@@ -32,7 +32,7 @@ public class Person {
 
        // Bean properties
        @Rdf(beanUri=true) public URI uri;
-       public URI addressBookUri;
+       private URI addressBookUri;
        public int id;
        public String name;
        @BeanProperty(swap=CalendarSwap.DateMedium.class) public Calendar 
birthDate;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/AtomFeedResource.java
----------------------------------------------------------------------
diff --git 
a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/AtomFeedResource.java
 
b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/AtomFeedResource.java
index ff453ae..49fc847 100644
--- 
a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/AtomFeedResource.java
+++ 
b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/AtomFeedResource.java
@@ -31,7 +31,7 @@ import org.apache.juneau.rest.annotation.*;
        path="/atom",
        title="Sample ATOM feed resource",
        description="Sample resource that shows how to render ATOM feeds",
-       
pageLinks="{up:'$R{requestParentURI}',options:'?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/AtomFeedResource.java'}",
+       
pageLinks="{up:'request:/..',options:'servlet:/?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/AtomFeedResource.java'}",
        properties={
                @Property(name=SERIALIZER_quoteChar, value="'"),
                @Property(name=RDF_rdfxml_tab, value="5"),

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/DirectoryResource.java
----------------------------------------------------------------------
diff --git 
a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/DirectoryResource.java
 
b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/DirectoryResource.java
index 9c3919f..753fcf7 100644
--- 
a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/DirectoryResource.java
+++ 
b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/DirectoryResource.java
@@ -35,7 +35,7 @@ import org.apache.juneau.utils.*;
  */
 @RestResource(
        messages="nls/DirectoryResource",
-       
pageLinks="{up:'$R{requestParentURI}',options:'?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/DirectoryResource.java'}",
+       
pageLinks="{up:'request:/..',options:'servlet:/?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/DirectoryResource.java'}",
        properties={
                @Property(name=HTML_uriAnchorText, value=PROPERTY_NAME),
                @Property(name=REST_allowMethodParam, value="*"),

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/DockerRegistryResource.java
----------------------------------------------------------------------
diff --git 
a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/DockerRegistryResource.java
 
b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/DockerRegistryResource.java
index 61192f0..1b021f0 100644
--- 
a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/DockerRegistryResource.java
+++ 
b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/DockerRegistryResource.java
@@ -27,7 +27,7 @@ import org.apache.juneau.rest.labels.*;
 @RestResource(
        path="/docker",
        title="Sample Docker resource",
-       
pageLinks="{up:'$R{requestParentURI}',options:'?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/DockerRegistryResource.java'}"
+       
pageLinks="{up:'request:/..',options:'servlet:/?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/DockerRegistryResource.java'}"
 )
 public class DockerRegistryResource extends Resource {
        private static final long serialVersionUID = 1L;

Reply via email to