This is an automated email from the ASF dual-hosted git repository.

jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git


The following commit(s) were added to refs/heads/master by this push:
     new ed77ddd49e juneau-marshall improvements
ed77ddd49e is described below

commit ed77ddd49e3be23f9e19d02a9c817e3acac82601
Author: James Bognar <[email protected]>
AuthorDate: Thu Dec 18 16:23:18 2025 -0500

    juneau-marshall improvements
---
 .../org/apache/juneau/jena/RdfParserSession.java   |   6 -
 .../apache/juneau/jena/RdfSerializerSession.java   |   6 -
 .../main/java/org/apache/juneau/BeanContext.java   | 352 ++++++++-------------
 .../main/java/org/apache/juneau/BeanSession.java   | 134 +++-----
 .../org/apache/juneau/BeanTraverseContext.java     |  30 +-
 .../org/apache/juneau/BeanTraverseSession.java     |   7 +-
 .../src/main/java/org/apache/juneau/Context.java   |   2 +-
 .../java/org/apache/juneau/ContextSession.java     |  49 +--
 .../org/apache/juneau/csv/CsvParserSession.java    |   6 -
 .../apache/juneau/csv/CsvSerializerSession.java    |   6 -
 .../juneau/html/HtmlDocSerializerSession.java      |   6 -
 .../org/apache/juneau/html/HtmlParserSession.java  |   6 -
 .../html/HtmlSchemaDocSerializerSession.java       |   6 -
 .../juneau/html/HtmlSchemaSerializerSession.java   |   6 -
 .../apache/juneau/html/HtmlSerializerSession.java  |   6 -
 .../html/HtmlStrippedDocSerializerSession.java     |   6 -
 .../org/apache/juneau/json/JsonParserSession.java  |   6 -
 .../juneau/json/JsonSchemaSerializerSession.java   |   6 -
 .../apache/juneau/json/JsonSerializerSession.java  |   6 -
 .../jsonschema/JsonSchemaGeneratorSession.java     |   6 -
 .../juneau/msgpack/MsgPackParserSession.java       |   6 -
 .../juneau/msgpack/MsgPackSerializerSession.java   |   6 -
 .../apache/juneau/oapi/OpenApiParserSession.java   |   6 -
 .../juneau/oapi/OpenApiSerializerSession.java      |   6 -
 .../juneau/parser/InputStreamParserSession.java    |   6 -
 .../org/apache/juneau/parser/ParserSession.java    |   5 -
 .../org/apache/juneau/parser/ReaderParser.java     |   4 +-
 .../apache/juneau/parser/ReaderParserSession.java  |  10 +-
 .../juneau/plaintext/PlainTextParserSession.java   |   6 -
 .../plaintext/PlainTextSerializerSession.java      |   6 -
 .../serializer/OutputStreamSerializerSession.java  |   6 -
 .../org/apache/juneau/serializer/Serializer.java   |  12 +-
 .../juneau/serializer/SerializerSession.java       |   8 +-
 .../apache/juneau/serializer/WriterSerializer.java |   8 +-
 .../juneau/serializer/WriterSerializerSession.java |  10 +-
 .../juneau/soap/SoapXmlSerializerSession.java      |   6 -
 .../org/apache/juneau/uon/UonParserSession.java    |   6 -
 .../apache/juneau/uon/UonSerializerSession.java    |   6 -
 .../urlencoding/UrlEncodingParserSession.java      |   6 -
 .../urlencoding/UrlEncodingSerializerSession.java  |   6 -
 .../apache/juneau/xml/XmlDocSerializerSession.java |   6 -
 .../org/apache/juneau/xml/XmlParserSession.java    |   6 -
 .../java/org/apache/juneau/xml/XmlSerializer.java  |  23 +-
 .../apache/juneau/xml/XmlSerializerSession.java    |  16 +-
 .../java/org/apache/juneau/BeanSession_Test.java   |  23 ++
 .../org/apache/juneau/ContextSession_Test.java     | 130 ++++++++
 .../test/java/org/apache/juneau/rest/Nls_Test.java |   3 +-
 .../Rest_DefaultRequestAttributes_Test.java        |   6 +-
 .../juneau/rest/annotation/Rest_RVars_Test.java    |   4 +-
 49 files changed, 431 insertions(+), 579 deletions(-)

diff --git 
a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfParserSession.java
 
b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfParserSession.java
index 7043eacaa1..954483874d 100644
--- 
a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfParserSession.java
+++ 
b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfParserSession.java
@@ -106,12 +106,6 @@ public class RdfParserSession extends ReaderParserSession {
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
-
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
                        super.mediaType(value);
diff --git 
a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerSession.java
 
b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerSession.java
index 81e1046657..065ff330b7 100644
--- 
a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerSession.java
+++ 
b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerSession.java
@@ -109,12 +109,6 @@ public class RdfSerializerSession extends 
WriterSerializerSession {
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
-
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
                        super.mediaType(value);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java
index 9c604844d4..bd0cc0d03a 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java
@@ -29,8 +29,6 @@ import java.io.*;
 import java.lang.annotation.*;
 import java.lang.reflect.*;
 import java.util.*;
-import java.util.concurrent.*;
-import java.util.concurrent.atomic.*;
 import java.util.stream.*;
 
 import org.apache.juneau.annotation.*;
@@ -174,6 +172,12 @@ public class BeanContext extends Context {
 
                private static final Cache<HashKey,BeanContext> CACHE = 
Cache.of(HashKey.class, BeanContext.class).build();
 
+               private static int integer(boolean...values) {
+                       var n = 0;
+                       for (var b : values)
+                               n = (n << 1) | (b ? 1 : 0);
+                       return n;
+               }
                private Visibility beanClassVisibility;
                private Visibility beanConstructorVisibility;
                private Visibility beanMethodVisibility;
@@ -203,6 +207,7 @@ public class BeanContext extends Context {
                private List<ClassInfo> beanDictionary;
                private List<Object> swaps;
                private Set<ClassInfo> notBeanClasses;
+
                private Set<String> notBeanPackages;
 
                /**
@@ -453,6 +458,20 @@ public class BeanContext extends Context {
                        return beanDictionary;
                }
 
+               /**
+                * Convenience method for {@link #beanDictionary(ClassInfo...)} 
that accepts {@link Class} objects.
+                *
+                * @param values
+                *      The values to add to this setting.
+                *      <br>Cannot contain <jk>null</jk> values.
+                * @return This object.
+                * @see #beanDictionary(ClassInfo...)
+                */
+               public Builder beanDictionary(Class<?>...values) {
+                       assertArgNoNulls("values", values);
+                       return 
beanDictionary(Stream.of(values).map(ReflectionUtils::info).toArray(ClassInfo[]::new));
+               }
+
                /**
                 * Bean dictionary.
                 *
@@ -564,20 +583,6 @@ public class BeanContext extends Context {
                        return this;
                }
 
-               /**
-                * Convenience method for {@link #beanDictionary(ClassInfo...)} 
that accepts {@link Class} objects.
-                *
-                * @param values
-                *      The values to add to this setting.
-                *      <br>Cannot contain <jk>null</jk> values.
-                * @return This object.
-                * @see #beanDictionary(ClassInfo...)
-                */
-               public Builder beanDictionary(Class<?>...values) {
-                       assertArgNoNulls("values", values);
-                       return 
beanDictionary(Stream.of(values).map(ReflectionUtils::info).toArray(ClassInfo[]::new));
-               }
-
                /**
                 * Minimum bean field visibility.
                 *
@@ -2655,6 +2660,20 @@ public class BeanContext extends Context {
                        return notBeanClasses;
                }
 
+               /**
+                * Convenience method for {@link #notBeanClasses(ClassInfo...)} 
that accepts {@link Class} objects.
+                *
+                * @param values
+                *      The values to add to this setting.
+                *      <br>Cannot contain <jk>null</jk> values.
+                * @return This object.
+                * @see #notBeanClasses(ClassInfo...)
+                */
+               public Builder notBeanClasses(Class<?>...values) {
+                       assertArgNoNulls("values", values);
+                       return 
notBeanClasses(Stream.of(values).map(ReflectionUtils::info).toArray(ClassInfo[]::new));
+               }
+
                /**
                 * Bean class exclusions.
                 *
@@ -2725,20 +2744,6 @@ public class BeanContext extends Context {
                        return this;
                }
 
-               /**
-                * Convenience method for {@link #notBeanClasses(ClassInfo...)} 
that accepts {@link Class} objects.
-                *
-                * @param values
-                *      The values to add to this setting.
-                *      <br>Cannot contain <jk>null</jk> values.
-                * @return This object.
-                * @see #notBeanClasses(ClassInfo...)
-                */
-               public Builder notBeanClasses(Class<?>...values) {
-                       assertArgNoNulls("values", values);
-                       return 
notBeanClasses(Stream.of(values).map(ReflectionUtils::info).toArray(ClassInfo[]::new));
-               }
-
                /**
                 * Returns the list of not-bean Java package names.
                 *
@@ -3503,13 +3508,6 @@ public class BeanContext extends Context {
                        useJavaBeanIntrospector = value;
                        return this;
                }
-
-               private static int integer(boolean...values) {
-                       var n = 0;
-                       for (var b : values)
-                               n = (n << 1) | (b ? 1 : 0);
-                       return n;
-               }
        }
 
        /*
@@ -3563,7 +3561,27 @@ public class BeanContext extends Context {
                return new Builder();
        }
 
-       private final AtomicReference<WriterSerializer> beanToStringSerializer 
= new AtomicReference<>();
+       /**
+        * Checks if the specified class should be cached.
+        *
+        * <p>
+        * Generated classes (proxies, lambda expressions, etc.) shouldn't be 
cacheable to prevent
+        * needlessly filling up the cache.
+        *
+        * @param c The class to check.
+        * @return <jk>true</jk> if the class should be cached.
+        */
+       private static boolean isCacheable(Class<?> c) {
+               var n = c.getName();
+               var x = n.charAt(n.length() - 1);  // All generated classes 
appear to end with digits.
+               if (x >= '0' && x <= '9') {
+                       if (n.indexOf("$$") != -1 || n.startsWith("sun") || 
n.startsWith("com.sun") || n.indexOf("$Proxy") != -1)
+                               return false;
+               }
+               return true;
+       }
+
+       private final OptionalSupplier<WriterSerializer> beanToStringSerializer;
        private final BeanRegistry beanRegistry;
        private final BeanSession defaultSession;
        private final boolean beanMapPutReturnsOldValue;
@@ -3584,7 +3602,6 @@ public class BeanContext extends Context {
        private final boolean useInterfaceProxies;
        private final boolean useJavaBeanIntrospector;
        private final Class<? extends PropertyNamer> propertyNamer;
-       private final ClassMeta<Class> cmClass;  // Reusable ClassMeta that 
represents general Classes.
        private final ClassMeta<Object> cmObject;  // Reusable ClassMeta that 
represents general Objects.
        private final ClassMeta<String> cmString;  // Reusable ClassMeta that 
represents general Strings.
        private final HashKey hashKey;
@@ -3593,7 +3610,7 @@ public class BeanContext extends Context {
        private final List<Object> swaps;
        private final List<String> notBeanPackages;
        private final Locale locale;
-       private final Map<Class,ClassMeta> cmCache;
+       private final Cache<Class,ClassMeta> cmCache;
        private final MediaType mediaType;
        private final List<ObjectSwap<?,?>> objectSwaps;
        private final PropertyNamer propertyNamerBean;
@@ -3633,14 +3650,14 @@ public class BeanContext extends Context {
                ignoreUnknownBeanProperties = 
builder.ignoreUnknownBeanProperties;
                ignoreUnknownEnumValues = builder.ignoreUnknownEnumValues;
                ignoreUnknownNullBeanProperties = ! 
builder.disableIgnoreUnknownNullBeanProperties;
-               locale = nn(builder.locale) ? builder.locale : 
Locale.getDefault();
+               locale = opt(builder.locale).orElse(Locale.getDefault());
                mediaType = builder.mediaType;
                notBeanPackages = u(new ArrayList<>(builder.notBeanPackages));
                propertyNamer = nn(builder.propertyNamer) ? 
builder.propertyNamer : BasicPropertyNamer.class;
                sortProperties = builder.sortProperties;
                swaps = u(copyOf(builder.swaps));
                timeZone = builder.timeZone;
-               typePropertyName = nn(builder.typePropertyName) ? 
builder.typePropertyName : "_type";
+               typePropertyName = 
opt(builder.typePropertyName).orElse("_type");
                useEnumNames = builder.useEnumNames;
                useInterfaceProxies = ! builder.disableInterfaceProxies;
                useJavaBeanIntrospector = builder.useJavaBeanIntrospector;
@@ -3653,11 +3670,7 @@ public class BeanContext extends Context {
                notBeanPackageNames = u(_notBeanPackageNames);
                notBeanPackagePrefixes = _notBeanPackages.stream().filter(x -> 
x.endsWith(".*")).map(x -> x.substring(0, x.length() - 2)).toList();
 
-               try {
-                       propertyNamerBean = 
propertyNamer.getDeclaredConstructor().newInstance();
-               } catch (Exception e) {
-                       throw toRex(e);
-               }
+               propertyNamerBean = 
safe(()->propertyNamer.getDeclaredConstructor().newInstance());
 
                var _objectSwaps = new LinkedList<ObjectSwap<?,?>>();
                swaps.forEach(x -> {
@@ -3675,36 +3688,13 @@ public class BeanContext extends Context {
                });
                objectSwaps = u(_objectSwaps);
 
-               cmCache = new ConcurrentHashMap<>();
-               cmCache.put(String.class, new ClassMeta(String.class, this));
-               cmCache.put(Object.class, new ClassMeta(Object.class, this));
+               cmCache = Cache.<Class,ClassMeta>create().supplier(type -> new 
ClassMeta<>(type, this)).build();
                cmString = cmCache.get(String.class);
                cmObject = cmCache.get(Object.class);
-               cmClass = cmCache.get(Class.class);
 
                beanRegistry = new BeanRegistry(this, null, list());
                defaultSession = createSession().unmodifiable().build();
-       }
-
-       /**
-        * Same as {@link #convertToType(Object, Class)}, except used for 
instantiating inner member classes that must
-        * be instantiated within another class instance.
-        *
-        * <p>
-        * This is a shortcut for the following code:  
<c>createSession().build().convertToMemberType(<jv>outer</jv>, <jv>value</jv>, 
<jv>type</jv>);</c>
-        *
-        * @param <T> The class type to convert the value to.
-        * @param outer
-        *      If class is a member class, this is the instance of the 
containing class.
-        *      Should be <jk>null</jk> if not a member class.
-        * @param value The value to convert.
-        * @param type The class type to convert the value to.
-        * @throws InvalidDataConversionException If the specified value cannot 
be converted to the specified type.
-        * @return The converted value.
-        * @see BeanSession#convertToMemberType(Object, Object, Class)
-        */
-       public final <T> T convertToMemberType(Object outer, Object value, 
Class<T> type) throws InvalidDataConversionException {
-               return defaultSession.convertToMemberType(outer, value, 
getClassMeta(type));
+               beanToStringSerializer = memoize(() -> 
JsonSerializer.create().beanContext(this).sq().simpleAttrs().build());
        }
 
        /**
@@ -3724,24 +3714,6 @@ public class BeanContext extends Context {
                return defaultSession.convertToType(value, type);
        }
 
-       /**
-        * Same as {@link #convertToType(Object, Class)}, but allows for 
complex data types consisting of collections or maps.
-        *
-        * <p>
-        * This is a shortcut for the following code:  
<c>createSession().build().convertToType(<jv>value</jv>, <jv>type</jv>, 
<jv>args</jv>);</c>
-        *
-        * @param <T> The class type to convert the value to.
-        * @param value The value to be converted.
-        * @param type The target object type.
-        * @param args The target object parameter types.
-        * @return The converted type.
-        * @throws InvalidDataConversionException If the specified value cannot 
be converted to the specified type.
-        * @see BeanSession#convertToType(Object, Type, Type...)
-        */
-       public final <T> T convertToType(Object value, Type type, Type...args) 
throws InvalidDataConversionException {
-               return (T)defaultSession.convertToMemberType(null, value, 
getClassMeta(type, args));
-       }
-
        @Override /* Overridden from Context */
        public Builder copy() {
                return new Builder(this);
@@ -3815,6 +3787,7 @@ public class BeanContext extends Context {
         */
        public final Visibility getBeanMethodVisibility() { return 
beanMethodVisibility; }
 
+
        /**
         * Bean type property name.
         *
@@ -3824,6 +3797,21 @@ public class BeanContext extends Context {
         */
        public final String getBeanTypePropertyName() { return 
typePropertyName; }
 
+       /**
+        * Construct a {@code ClassMeta} wrapper around a {@link Class} object.
+        *
+        * @param <T> The class type being wrapped.
+        * @param type The class to resolve.
+        * @return
+        *      If the class is not an array, returns a cached {@link 
ClassMeta} object.
+        *      Otherwise, returns a new {@link ClassMeta} object every time.
+        */
+       public final <T> ClassMeta<T> getClassMeta(Class<T> type) {
+               // Non-cacheable classes (proxies, generated classes) should 
not be cached
+               if (! isCacheable(type))
+                       return new ClassMeta<>(type, this);
+               return cmCache.get(type);
+       }
 
        /**
         * Used to resolve <c>ClassMetas</c> of type <c>Collection</c> and 
<c>Map</c> that have
@@ -3918,41 +3906,6 @@ public class BeanContext extends Context {
         */
        public final MediaType getDefaultMediaType() { return mediaType; }
 
-       /**
-        * Hash key.
-        *
-        * @return The hash key.
-        */
-       protected final HashKey getHashKey() { return hashKey; }
-
-       /**
-        * Class metadata cache.
-        *
-        * @return The class metadata cache.
-        */
-       protected final Map<Class,ClassMeta> getCmCache() { return cmCache; }
-
-       /**
-        * Locale.
-        *
-        * @return The locale.
-        */
-       protected final Locale getLocale() { return locale; }
-
-       /**
-        * Media type.
-        *
-        * @return The media type.
-        */
-       protected final MediaType getMediaType() { return mediaType; }
-
-       /**
-        * Time zone.
-        *
-        * @return The time zone.
-        */
-       protected final TimeZone getTimeZone() { return timeZone; }
-
        /**
         * Time zone.
         *
@@ -4213,75 +4166,51 @@ public class BeanContext extends Context {
                return defaultSession.toBeanMap(object);
        }
 
-
-       /*
-        * Resolves the 'genericized' class meta at the specified position in 
the ClassMeta array.
+       /**
+        * Returns the lookup table for resolving bean types by name.
+        *
+        * @return The lookup table for resolving bean types by name.
         */
-       private ClassMeta<?> getTypedClassMeta(ClassMeta<?>[] c, int pos) {
-               var cm = c[pos++];
-               if (cm.isCollection() || cm.isOptional()) {
-                       var ce = c.length == pos ? object() : 
getTypedClassMeta(c, pos);
-                       return (ce.isObject() ? cm : new ClassMeta(cm, null, 
null, ce));
-               } else if (cm.isMap()) {
-                       var ck = c.length == pos ? object() : c[pos++];
-                       var cv = c.length == pos ? object() : 
getTypedClassMeta(c, pos);
-                       return (ck.isObject() && cv.isObject() ? cm : new 
ClassMeta(cm, ck, cv, null));
-               }
-               return cm;
-       }
+       protected final BeanRegistry getBeanRegistry() { return beanRegistry; }
 
-       private ClassMeta<?> resolveType(Type...t) {
-               for (var tt : t) {
-                       if (nn(tt)) {
-                               var cm = getClassMeta(tt);
-                               if (tt != cmObject)
-                                       return cm;
-                       }
-               }
-               return cmObject;
+       /**
+        * Returns the serializer to use for serializing beans when using the 
{@link BeanSession#convertToType(Object, Class)}
+        * and related methods.
+        *
+        * @return The serializer.  May be <jk>null</jk> if all initialization 
has occurred.
+        */
+       protected WriterSerializer getBeanToStringSerializer() {
+               return beanToStringSerializer.get();
        }
 
        /**
-        * Returns a reusable {@link ClassMeta} representation for the class 
<c>Class</c>.
-        *
-        * <p>
-        * This <c>ClassMeta</c> is often used to represent key types in maps.
+        * Class metadata cache.
         *
-        * <p>
-        * This method is identical to calling 
<code>getClassMeta(Class.<jk>class</jk>)</code> but uses a cached copy to
-        * avoid a hashmap lookup.
+        * @return The class metadata cache.
+        */
+       protected final Cache<Class,ClassMeta> getCmCache() { return cmCache; }
+
+
+       /**
+        * Hash key.
         *
-        * @return The {@link ClassMeta} object associated with the 
<c>String</c> class.
+        * @return The hash key.
         */
-       protected final ClassMeta<Class> _class() {
-               return cmClass;
-       }
+       protected final HashKey getHashKey() { return hashKey; }
 
        /**
-        * Returns the lookup table for resolving bean types by name.
+        * Locale.
         *
-        * @return The lookup table for resolving bean types by name.
+        * @return The locale.
         */
-       protected final BeanRegistry getBeanRegistry() { return beanRegistry; }
+       protected final Locale getLocale() { return locale; }
 
        /**
-        * Returns the serializer to use for serializing beans when using the 
{@link BeanSession#convertToType(Object, Class)}
-        * and related methods.
+        * Media type.
         *
-        * @return The serializer.  May be <jk>null</jk> if all initialization 
has occurred.
+        * @return The media type.
         */
-       protected WriterSerializer getBeanToStringSerializer() {
-               var result = beanToStringSerializer.get();
-               if (result == null) {
-                       if (JsonSerializer.DEFAULT == null)
-                               return null;
-                       result = 
JsonSerializer.create().beanContext(this).sq().simpleAttrs().build();
-                       if (! beanToStringSerializer.compareAndSet(null, 
result)) {
-                               result = beanToStringSerializer.get();
-                       }
-               }
-               return result;
-       }
+       protected final MediaType getMediaType() { return mediaType; }
 
        /**
         * Bean class exclusions.
@@ -4295,15 +4224,11 @@ public class BeanContext extends Context {
        protected final List<ClassInfo> getNotBeanClasses() { return 
notBeanClasses; }
 
        /**
-        * Bean package exclusions.
+        * Time zone.
         *
-        * @see BeanContext.Builder#notBeanPackages(String...)
-        * @return
-        *      The list of package name prefixes to exclude from being 
classified as beans.
-        *      <br>Never <jk>null</jk>.
-        *      <br>List is unmodifiable.
+        * @return The time zone.
         */
-       protected final List<String> getNotBeanPackagesPrefixes() { return 
notBeanPackagePrefixes; }
+       protected final TimeZone getTimeZone() { return timeZone; }
 
        /**
         * Ignore transient fields.
@@ -4485,35 +4410,6 @@ public class BeanContext extends Context {
                return null;
        }
 
-       /**
-        * Construct a {@code ClassMeta} wrapper around a {@link Class} object.
-        *
-        * @param <T> The class type being wrapped.
-        * @param type The class to resolve.
-        * @return
-        *      If the class is not an array, returns a cached {@link 
ClassMeta} object.
-        *      Otherwise, returns a new {@link ClassMeta} object every time.
-        */
-       public final <T> ClassMeta<T> getClassMeta(Class<T> type) {
-
-               // This can happen if we have transforms defined against String 
or Object.
-               if (cmCache == null)
-                       return null;
-
-               var cm = cmCache.get(type);
-               if (cm == null) {
-
-                       synchronized (this) {
-                               // Make sure someone didn't already set it 
while this thread was blocked.
-                               cm = cmCache.get(type);
-                               if (cm == null)
-                                       cm = new ClassMeta<>(type, this);
-                       }
-               }
-               return cm;
-       }
-
-
        final ClassMeta resolveClassMeta(Type o, TypeVariables typeVars) {
                if (o == null)
                        return null;
@@ -4573,4 +4469,32 @@ public class BeanContext extends Context {
 
                return rawType;
        }
+
+       /*
+        * Resolves the 'genericized' class meta at the specified position in 
the ClassMeta array.
+        */
+       private ClassMeta<?> getTypedClassMeta(ClassMeta<?>[] c, int pos) {
+               var cm = c[pos++];
+               if (cm.isCollection() || cm.isOptional()) {
+                       var ce = c.length == pos ? object() : 
getTypedClassMeta(c, pos);
+                       return (ce.isObject() ? cm : new ClassMeta(cm, null, 
null, ce));
+               } else if (cm.isMap()) {
+                       var ck = c.length == pos ? object() : c[pos++];
+                       var cv = c.length == pos ? object() : 
getTypedClassMeta(c, pos);
+                       return (ck.isObject() && cv.isObject() ? cm : new 
ClassMeta(cm, ck, cv, null));
+               }
+               return cm;
+       }
+
+
+       private ClassMeta<?> resolveType(Type...t) {
+               for (var tt : t) {
+                       if (nn(tt)) {
+                               var cm = getClassMeta(tt);
+                               if (tt != cmObject)
+                                       return cm;
+                       }
+               }
+               return cmObject;
+       }
 }
\ No newline at end of file
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanSession.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanSession.java
index 9d17da9ead..4f78668014 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanSession.java
@@ -53,6 +53,7 @@ import org.apache.juneau.swap.*;
  */
 @SuppressWarnings({ "unchecked", "rawtypes" })
 public class BeanSession extends ContextSession {
+
        /**
         * Builder class.
         */
@@ -72,7 +73,6 @@ public class BeanSession extends ContextSession {
                protected Builder(BeanContext ctx) {
                        super(assertArgNotNull("ctx", ctx));
                        this.ctx = ctx;
-                       locale = ctx.getLocale();
                        mediaType = ctx.getMediaType();
                        timeZone = ctx.getTimeZone();
                }
@@ -115,26 +115,11 @@ public class BeanSession extends ContextSession {
                 *
                 * @param value
                 *      The new value for this property.
-                *      <br>If <jk>null</jk>, then the locale defined on the 
context is used.
+                *      <br>If <jk>null</jk> defaults to {@link 
BeanContext#getLocale()}
                 * @return This object.
                 */
                public Builder locale(Locale value) {
-                       if (nn(value))
-                               locale = value;
-                       return this;
-               }
-
-               /**
-                * Same as {@link #locale(Locale)} but doesn't overwrite the 
value if it is already set.
-                *
-                * @param value
-                *      The new value for this property.
-                *      <br>If <jk>null</jk>, then the locale defined on the 
context is used.
-                * @return This object.
-                */
-               public Builder localeDefault(Locale value) {
-                       if (nn(value) && locale == null)
-                               locale = value;
+                       locale = value;
                        return this;
                }
 
@@ -154,12 +139,11 @@ public class BeanSession extends ContextSession {
                 *
                 * @param value
                 *      The new value for this property.
-                *      <br>Can be <jk>null</jk> (will not set the value, 
defaults to {@link BeanContext.Builder#mediaType(MediaType)} if set on context).
+                *      <br>If <jk>null</jk> defaults to {@link 
BeanContext#getMediaType()}.
                 * @return This object.
                 */
                public Builder mediaType(MediaType value) {
-                       if (nn(value))
-                               mediaType = value;
+                       mediaType = value;
                        return this;
                }
 
@@ -172,7 +156,7 @@ public class BeanSession extends ContextSession {
                 * @return This object.
                 */
                public Builder mediaTypeDefault(MediaType value) {
-                       if (nn(value) && mediaType == null)
+                       if (mediaType == null)
                                mediaType = value;
                        return this;
                }
@@ -205,12 +189,11 @@ public class BeanSession extends ContextSession {
                 *
                 * @param value
                 *      The new value for this property.
-                *      <br>Can be <jk>null</jk> (will not set the value, 
defaults to {@link BeanContext.Builder#timeZone(TimeZone)} if set on context).
+                *      <br>If <jk>null</jk> defaults to {@link 
BeanContext#getTimeZone()}.
                 * @return This object.
                 */
                public Builder timeZone(TimeZone value) {
-                       if (nn(value))
-                               timeZone = value;
+                       timeZone = value;
                        return this;
                }
 
@@ -223,7 +206,7 @@ public class BeanSession extends ContextSession {
                 * @return This object.
                 */
                public Builder timeZoneDefault(TimeZone value) {
-                       if (nn(value) && timeZone == null)
+                       if (timeZone == null)
                                timeZone = value;
                        return this;
                }
@@ -248,6 +231,16 @@ public class BeanSession extends ContextSession {
                return new Builder(assertArgNotNull("ctx", ctx));
        }
 
+       /**
+        * Returns the name property name.
+        *
+        * <p>
+        * Currently this always returns <js>"_name"</js>.
+        *
+        * @return The name property name.  Never <jk>null</jk>.
+        */
+       public final static String getNamePropertyName() { return "_name"; }
+
        private static int getMultiplier(String s) {
                if (s.endsWith("G"))
                        return 1024 * 1024 * 1024;
@@ -265,10 +258,10 @@ public class BeanSession extends ContextSession {
        private static final boolean isNullOrEmpty(Object o) {
                return o == null || o.toString().isEmpty() || 
o.toString().equals("null");
        }
-
        private final BeanContext ctx;
        private final Locale locale;
        private final MediaType mediaType;
+
        private final TimeZone timeZone;
 
        /**
@@ -279,34 +272,9 @@ public class BeanSession extends ContextSession {
        protected BeanSession(Builder builder) {
                super(builder);
                ctx = builder.ctx;
-               locale = builder.locale;
-               mediaType = builder.mediaType;
-               timeZone = builder.timeZone;
-       }
-
-       /**
-        * Returns a reusable {@link ClassMeta} representation for the class 
<c>Class</c>.
-        *
-        * <p>
-        * This <c>ClassMeta</c> is often used to represent key types in maps.
-        *
-        * <p>
-        * This method is identical to calling 
<code>getClassMeta(Class.<jk>class</jk>)</code> but uses a cached copy to
-        * avoid a hashmap lookup.
-        *
-        * @return The {@link ClassMeta} object associated with the 
<c>String</c> class.
-        */
-       public final ClassMeta<Class> _class() {
-               return ctx._class();
-       }
-
-       /**
-        * Returns the annotation provider for this session.
-        *
-        * @return The annotation provider for this session.
-        */
-       public AnnotationProvider getAnnotationProvider() {
-               return ctx.getAnnotationProvider();
+               locale = opt(builder.locale).orElse(ctx.getLocale());
+               mediaType = opt(builder.mediaType).orElse(builder.mediaType);
+               timeZone = opt(builder.timeZone).orElse(builder.timeZone);
        }
 
        /**
@@ -511,6 +479,15 @@ public class BeanSession extends ContextSession {
                return (T)convertToMemberType(null, value, getClassMeta(type, 
args));
        }
 
+       /**
+        * Returns the annotation provider for this session.
+        *
+        * @return The annotation provider for this session.
+        */
+       public AnnotationProvider getAnnotationProvider() {
+               return ctx.getAnnotationProvider();
+       }
+
        /**
         * Minimum bean class visibility.
         *
@@ -532,7 +509,7 @@ public class BeanSession extends ContextSession {
        /**
         * Bean dictionary.
         *
-        * @see BeanContext.Builder#beanDictionary(Class...)
+        * @see BeanContext.Builder#beanDictionary(ClassInfo...)
         * @return
         *      The list of classes that make up the bean dictionary in this 
bean context.
         *      <br>Never <jk>null</jk>.
@@ -575,7 +552,7 @@ public class BeanSession extends ContextSession {
        public final Visibility getBeanMethodVisibility() { return 
ctx.getBeanMethodVisibility(); }
 
        /**
-        * Returns the bean registry defined in this bean context defined by 
{@link BeanContext.Builder#beanDictionary(Class...)}.
+        * Returns the bean registry defined in this bean context defined by 
{@link BeanContext.Builder#beanDictionary(ClassInfo...)}.
         *
         * @return The bean registry defined in this bean context.  Never 
<jk>null</jk>.
         */
@@ -703,16 +680,6 @@ public class BeanSession extends ContextSession {
         */
        public final MediaType getMediaType() { return mediaType; }
 
-       /**
-        * Returns the name property name.
-        *
-        * <p>
-        * Currently this always returns <js>"_name"</js>.
-        *
-        * @return The name property name.  Never <jk>null</jk>.
-        */
-       public final static String getNamePropertyName() { return "_name"; }
-
        /**
         * Bean class exclusions.
         *
@@ -1628,17 +1595,6 @@ public class BeanSession extends ContextSession {
                return getClassMeta(o.getClass());
        }
 
-       /**
-        * Bean package exclusions.
-        *
-        * @see BeanContext.Builder#notBeanPackages(String...)
-        * @return
-        *      The list of package name prefixes to exclude from being 
classified as beans.
-        *      <br>Never <jk>null</jk>.
-        *      <br>List is unmodifiable.
-        */
-       protected final List<String> getNotBeanPackagesPrefixes() { return 
ctx.getNotBeanPackagesPrefixes(); }
-
        /**
         * Creates either an {@link JsonMap} or {@link LinkedHashMap} depending 
on whether the key type is
         * String or something else.
@@ -1651,6 +1607,14 @@ public class BeanSession extends ContextSession {
                return (k == null || k.isString()) ? new JsonMap(this) : map();
        }
 
+       @Override /* Overridden from ContextSession */
+       protected FluentMap<String,Object> properties() {
+               return super.properties()
+                       .a("locale", locale)
+                       .a("mediaType", mediaType)
+                       .a("timeZone", timeZone);
+       }
+
        /**
         * Converts the contents of the specified list into an array.
         *
@@ -1682,20 +1646,8 @@ public class BeanSession extends ContextSession {
                                else
                                        x2 = convertToType(x, componentType);
                        }
-                       try {
-                               Array.set(array, i.getAndIncrement(), x2);
-                       } catch (IllegalArgumentException e) {
-                               throw e;
-                       }
+                       Array.set(array, i.getAndIncrement(), x2);
                });
                return array;
        }
-
-       @Override /* Overridden from ContextSession */
-       protected FluentMap<String,Object> properties() {
-               return super.properties()
-                       .a("locale", locale)
-                       .a("mediaType", mediaType)
-                       .a("timeZone", timeZone);
-       }
 }
\ No newline at end of file
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanTraverseContext.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanTraverseContext.java
index 7fdb2c8eec..5f7e6bbc13 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanTraverseContext.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanTraverseContext.java
@@ -67,10 +67,10 @@ public abstract class BeanTraverseContext extends 
BeanContextable {
                 */
                protected Builder(BeanTraverseContext copyFrom) {
                        super(copyFrom);
-                       detectRecursions = copyFrom.detectRecursions;
-                       ignoreRecursions = copyFrom.ignoreRecursions;
-                       initialDepth = copyFrom.initialDepth;
-                       maxDepth = copyFrom.maxDepth;
+                       detectRecursions = copyFrom.getDetectRecursions();
+                       ignoreRecursions = copyFrom.getIgnoreRecursions();
+                       initialDepth = copyFrom.getInitialDepth();
+                       maxDepth = copyFrom.getMaxDepth();
                }
 
                /**
@@ -697,10 +697,10 @@ public abstract class BeanTraverseContext extends 
BeanContextable {
                }
        }
 
-       protected final boolean detectRecursions;
-       protected final boolean ignoreRecursions;
-       protected final int initialDepth;
-       protected final int maxDepth;
+       private final boolean detectRecursions;
+       private final boolean ignoreRecursions;
+       private final int initialDepth;
+       private final int maxDepth;
        private final boolean actualDetectRecursions;
 
        /**
@@ -760,6 +760,20 @@ public abstract class BeanTraverseContext extends 
BeanContextable {
         */
        public final boolean isIgnoreRecursions() { return ignoreRecursions; }
 
+       /**
+        * Detect recursions flag (raw value).
+        *
+        * @return The detect recursions flag.
+        */
+       protected final boolean getDetectRecursions() { return 
detectRecursions; }
+
+       /**
+        * Ignore recursions flag (raw value).
+        *
+        * @return The ignore recursions flag.
+        */
+       protected final boolean getIgnoreRecursions() { return 
ignoreRecursions; }
+
        @Override /* Overridden from BeanContextable */
        protected FluentMap<String,Object> properties() {
                return super.properties()
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanTraverseSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanTraverseSession.java
index 47332b5147..48a5d5e6c8 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanTraverseSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanTraverseSession.java
@@ -65,7 +65,7 @@ public class BeanTraverseSession extends BeanSession {
                protected Builder(BeanTraverseContext ctx) {
                        super(assertArgNotNull("ctx", ctx).getBeanContext());
                        this.ctx = ctx;
-                       initialDepth = ctx.initialDepth;
+                       initialDepth = ctx.getInitialDepth();
                }
 
                @Override /* Overridden from Builder */
@@ -86,11 +86,6 @@ public class BeanTraverseSession extends BeanSession {
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
 
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Context.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Context.java
index 01f550d722..92ce2168e8 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Context.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Context.java
@@ -303,7 +303,7 @@ public abstract class Context {
                 */
                public Builder annotations(Annotation...values) {
                        assertArgNoNulls("values", values);
-                       annotations.addAll(l(values));
+                       annotations(l(values));
                        return this;
                }
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextSession.java
index 1d0d1c1edc..103c361ab2 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextSession.java
@@ -19,6 +19,7 @@ package org.apache.juneau;
 import static java.util.Collections.*;
 import static org.apache.juneau.commons.utils.AssertionUtils.*;
 import static org.apache.juneau.commons.utils.CollectionUtils.*;
+import static org.apache.juneau.commons.utils.StringUtils.*;
 import static org.apache.juneau.commons.utils.ThrowableUtils.*;
 import static org.apache.juneau.commons.utils.Utils.*;
 
@@ -26,10 +27,9 @@ import java.text.*;
 import java.util.*;
 import java.util.function.*;
 
-import org.apache.juneau.collections.*;
 import org.apache.juneau.commons.collections.*;
+import org.apache.juneau.commons.function.*;
 import org.apache.juneau.commons.reflect.*;
-import org.apache.juneau.commons.utils.*;
 
 /**
  * A one-time-use non-thread-safe object that's meant to be used once and then 
thrown away.
@@ -40,6 +40,7 @@ import org.apache.juneau.commons.utils.*;
  *
  */
 public abstract class ContextSession {
+
        /**
         * Builder class.
         */
@@ -47,7 +48,7 @@ public abstract class ContextSession {
                private Boolean debug;
                private boolean unmodifiable;
                private Context ctx;
-               private JsonMap properties;
+               private ResettableSupplier<LinkedHashMap<String,Object>> 
properties;
 
                /**
                 * Constructor.
@@ -57,7 +58,7 @@ public abstract class ContextSession {
                 */
                protected Builder(Context ctx) {
                        this.ctx = assertArgNotNull("ctx", ctx);
-                       debug = ctx.isDebug();
+                       this.properties = memoizeResettable(LinkedHashMap::new);
                }
 
                /**
@@ -101,12 +102,11 @@ public abstract class ContextSession {
                 *
                 * @param value
                 *      The new value for this property.
-                *      <br>Can be <jk>null</jk>.  Value will be ignored.
+                *      <br>If <jk>null</jk>, defaults to {@link 
Context#isDebug()}.
                 * @return This object.
                 */
                public Builder debug(Boolean value) {
-                       if (nn(value))
-                               debug = value;
+                       debug = value;
                        return this;
                }
 
@@ -119,11 +119,13 @@ public abstract class ContextSession {
                 *
                 * @param value
                 *      The new value for this property.
-                *      <br>Can be <jk>null</jk>.
+                *      <br>Cannot be <jk>null</jk>.
                 * @return This object.
                 */
                public Builder properties(Map<String,Object> value) {
-                       properties = JsonMap.of(value);
+                       assertArgNotNull("value", value);
+                       properties.reset();
+                       properties.get().putAll(value);
                        return this;
                }
 
@@ -137,12 +139,12 @@ public abstract class ContextSession {
                 * @return This object.
                 */
                public Builder property(String key, Object value) {
-                       if (properties == null)
-                               properties = JsonMap.create();
+                       assertArgNotNull("key", key);
+                       var map = properties.get();
                        if (value == null) {
-                               properties.remove(assertArgNotNull("key", key));
+                               map.remove(key);
                        } else {
-                               properties.put(assertArgNotNull("key", key), 
value);
+                               map.put(key, value);
                        }
                        return this;
                }
@@ -164,7 +166,7 @@ public abstract class ContextSession {
        private final boolean debug;
        private final boolean unmodifiable;
        private final Context ctx;
-       private final JsonMap properties;
+       private final Map<String,Object> properties;
        private List<String> warnings;  // Any warnings encountered.
 
        /**
@@ -176,12 +178,14 @@ public abstract class ContextSession {
        protected ContextSession(Builder builder) {
                assertArgNotNull("builder", builder);
                ctx = builder.ctx;
-               debug = builder.debug;
+               debug = opt(builder.debug).orElse(ctx.isDebug());
                unmodifiable = builder.unmodifiable;
-               var sp = builder.properties == null ? JsonMap.EMPTY_MAP : 
builder.properties;
-               if (unmodifiable)
-                       sp = sp.unmodifiable();
-               properties = sp;
+               var sp = builder.properties.get();
+               if (unmodifiable) {
+                       properties = sp.isEmpty() ? Collections.emptyMap() : 
u(sp);
+               } else {
+                       properties = sp;
+               }
        }
 
        /**
@@ -193,11 +197,12 @@ public abstract class ContextSession {
         *      <br>Cannot contain <jk>null</jk> values.
         */
        public void addWarning(String msg, Object...args) {
+               assertArgsNotNull("msg", msg, "args", args);
                if (unmodifiable)
                        return;
                if (warnings == null)
                        warnings = new LinkedList<>();
-               warnings.add((warnings.size() + 1) + ": " + 
f(assertArgNotNull("msg", msg), assertArgNoNulls("args", args)));
+               warnings.add((warnings.size() + 1) + ": " + f(msg, args));
        }
 
        /**
@@ -205,7 +210,7 @@ public abstract class ContextSession {
         */
        public void checkForWarnings() {
                if (debug && ! getWarnings().isEmpty())
-                       throw bex("Warnings occurred in session: \n" + 
StringUtils.join(getWarnings(), "\n"));
+                       throw bex("Warnings occurred in session: \n" + 
join(getWarnings(), "\n"));
        }
 
        /**
@@ -220,7 +225,7 @@ public abstract class ContextSession {
         *
         * @return The session properties on this session.  Never <jk>null</jk>.
         */
-       public final JsonMap getSessionProperties() { return properties; }
+       public final Map<String,Object> getSessionProperties() { return 
properties; }
 
        /**
         * Returns the warnings that occurred in this session.
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvParserSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvParserSession.java
index 16a668a4b4..30669df5c5 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvParserSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvParserSession.java
@@ -84,12 +84,6 @@ public class CsvParserSession extends ReaderParserSession {
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
-
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
                        super.mediaType(value);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvSerializerSession.java
index de38490d23..25284e1b03 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvSerializerSession.java
@@ -93,12 +93,6 @@ public class CsvSerializerSession extends 
WriterSerializerSession {
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
-
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
                        super.mediaType(value);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
index 853f45ec41..91d0fca464 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
@@ -96,12 +96,6 @@ public class HtmlDocSerializerSession extends 
HtmlStrippedDocSerializerSession {
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
-
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
                        super.mediaType(value);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlParserSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlParserSession.java
index 5bfb28e430..781ee52e9d 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlParserSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlParserSession.java
@@ -108,12 +108,6 @@ public class HtmlParserSession extends XmlParserSession {
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
-
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
                        super.mediaType(value);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSchemaDocSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSchemaDocSerializerSession.java
index cf02077bd7..5eb469a5de 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSchemaDocSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSchemaDocSerializerSession.java
@@ -92,12 +92,6 @@ public class HtmlSchemaDocSerializerSession extends 
HtmlDocSerializerSession {
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
-
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
                        super.mediaType(value);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSchemaSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSchemaSerializerSession.java
index 572e6e531c..b58e310746 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSchemaSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSchemaSerializerSession.java
@@ -92,12 +92,6 @@ public class HtmlSchemaSerializerSession extends 
HtmlSerializerSession {
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
-
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
                        super.mediaType(value);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java
index aad41c836c..3d8fa6f740 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java
@@ -108,12 +108,6 @@ public class HtmlSerializerSession extends 
XmlSerializerSession {
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
-
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
                        super.mediaType(value);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlStrippedDocSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlStrippedDocSerializerSession.java
index 5178e3ec92..57a60a880a 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlStrippedDocSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlStrippedDocSerializerSession.java
@@ -91,12 +91,6 @@ public class HtmlStrippedDocSerializerSession extends 
HtmlSerializerSession {
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
-
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
                        super.mediaType(value);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParserSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParserSession.java
index 9cabf7ca1d..1f43291336 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParserSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParserSession.java
@@ -101,12 +101,6 @@ public class JsonParserSession extends ReaderParserSession 
{
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
-
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
                        super.mediaType(value);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSchemaSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSchemaSerializerSession.java
index c07a9e84aa..aceaf181fb 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSchemaSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSchemaSerializerSession.java
@@ -92,12 +92,6 @@ public class JsonSchemaSerializerSession extends 
JsonSerializerSession {
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
-
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
                        super.mediaType(value);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializerSession.java
index 0c75def03f..92d8c01a71 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializerSession.java
@@ -98,12 +98,6 @@ public class JsonSerializerSession extends 
WriterSerializerSession {
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
-
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
                        super.mediaType(value);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaGeneratorSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaGeneratorSession.java
index 2bca5f5f8d..cc60ec864a 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaGeneratorSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaGeneratorSession.java
@@ -87,12 +87,6 @@ public class JsonSchemaGeneratorSession extends 
BeanTraverseSession {
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
-
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
                        super.mediaType(value);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParserSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParserSession.java
index 5e96e49185..997d932b11 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParserSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParserSession.java
@@ -90,12 +90,6 @@ public class MsgPackParserSession extends 
InputStreamParserSession {
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
-
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
                        super.mediaType(value);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerSession.java
index 728aa548d8..c5fea95f5e 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerSession.java
@@ -92,12 +92,6 @@ public class MsgPackSerializerSession extends 
OutputStreamSerializerSession {
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
-
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
                        super.mediaType(value);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiParserSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiParserSession.java
index 2a267b0d58..1de4b70b7e 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiParserSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiParserSession.java
@@ -111,12 +111,6 @@ public class OpenApiParserSession extends UonParserSession 
{
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
-
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
                        super.mediaType(value);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiSerializerSession.java
index f62c0db9d1..26d83cf096 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiSerializerSession.java
@@ -104,12 +104,6 @@ public class OpenApiSerializerSession extends 
UonSerializerSession {
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
-
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
                        super.mediaType(value);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParserSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParserSession.java
index cca353e23d..46ff99c2ee 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParserSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParserSession.java
@@ -85,12 +85,6 @@ public class InputStreamParserSession extends ParserSession {
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
-
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
                        super.mediaType(value);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserSession.java
index 50446df535..6033b1aa6b 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserSession.java
@@ -108,11 +108,6 @@ public class ParserSession extends BeanSession {
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
 
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParser.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParser.java
index 4906fff4f4..29d6d4f02e 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParser.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParser.java
@@ -673,8 +673,8 @@ public class ReaderParser extends Parser {
                return new Builder();
        }
 
-       protected final Charset fileCharset;
-       protected final Charset streamCharset;
+       private final Charset fileCharset;
+       private final Charset streamCharset;
 
        /**
         * Constructor.
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParserSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParserSession.java
index feeefd0ff5..45f59873cb 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParserSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParserSession.java
@@ -58,8 +58,8 @@ public class ReaderParserSession extends ParserSession {
                protected Builder(ReaderParser ctx) {
                        super(assertArgNotNull("ctx", ctx));
                        this.ctx = ctx;
-                       fileCharset = ctx.fileCharset;
-                       streamCharset = ctx.streamCharset;
+                       fileCharset = ctx.getFileCharset();
+                       streamCharset = ctx.getStreamCharset();
                }
 
                @Override /* Overridden from Builder */
@@ -113,12 +113,6 @@ public class ReaderParserSession extends ParserSession {
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
-
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
                        super.mediaType(value);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextParserSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextParserSession.java
index 2c7a03e7d5..8c94d5f5ed 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextParserSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextParserSession.java
@@ -88,12 +88,6 @@ public class PlainTextParserSession extends 
ReaderParserSession {
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
-
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
                        super.mediaType(value);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerSession.java
index 11c125ab9c..cb2e843cee 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerSession.java
@@ -89,12 +89,6 @@ public class PlainTextSerializerSession extends 
WriterSerializerSession {
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
-
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
                        super.mediaType(value);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/OutputStreamSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/OutputStreamSerializerSession.java
index fde307d428..b498d95a2f 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/OutputStreamSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/OutputStreamSerializerSession.java
@@ -95,12 +95,6 @@ public class OutputStreamSerializerSession extends 
SerializerSession {
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
-
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
                        super.mediaType(value);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/Serializer.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/Serializer.java
index 66e08d51f4..b9a24d813d 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/Serializer.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/Serializer.java
@@ -155,9 +155,9 @@ public class Serializer extends BeanTraverseContext {
                        trimEmptyCollections = copyFrom.trimEmptyCollections;
                        trimEmptyMaps = copyFrom.trimEmptyMaps;
                        trimStrings = copyFrom.trimStrings;
-                       uriContext = copyFrom.uriContext;
-                       uriRelativity = copyFrom.uriRelativity;
-                       uriResolution = copyFrom.uriResolution;
+                       uriContext = copyFrom.getUriContext();
+                       uriRelativity = copyFrom.getUriRelativity();
+                       uriResolution = copyFrom.getUriResolution();
                        listener = copyFrom.listener;
                }
 
@@ -1288,9 +1288,9 @@ public class Serializer extends BeanTraverseContext {
        protected final Class<? extends SerializerListener> listener;
        protected final String accept;
        protected final String produces;
-       protected final UriContext uriContext;
-       protected final UriRelativity uriRelativity;
-       protected final UriResolution uriResolution;
+       private final UriContext uriContext;
+       private final UriRelativity uriRelativity;
+       private final UriResolution uriResolution;
        private final MediaRanges acceptRanges;
        private final List<MediaType> acceptMediaTypes;
        private final MediaType producesMediaType;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerSession.java
index beda257b4b..b62cbe2620 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerSession.java
@@ -86,7 +86,7 @@ public class SerializerSession extends BeanTraverseSession {
                        super(assertArgNotNull("ctx", ctx));
                        this.ctx = ctx;
                        mediaTypeDefault(ctx.getResponseContentType());
-                       uriContext = ctx.uriContext;
+                       uriContext = ctx.getUriContext();
                }
 
                @Override /* Overridden from Builder */
@@ -126,12 +126,6 @@ public class SerializerSession extends BeanTraverseSession 
{
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
-
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
                        super.mediaType(value);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializer.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializer.java
index 41cdb65968..a64b3c5b8f 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializer.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializer.java
@@ -93,8 +93,8 @@ public class WriterSerializer extends Serializer {
                 */
                protected Builder(WriterSerializer copyFrom) {
                        super(assertArgNotNull("copyFrom", copyFrom));
-                       fileCharset = copyFrom.fileCharset;
-                       streamCharset = copyFrom.streamCharset;
+                       fileCharset = copyFrom.getFileCharset();
+                       streamCharset = copyFrom.getStreamCharset();
                        maxIndent = copyFrom.maxIndent;
                        quoteChar = copyFrom.quoteChar;
                        quoteCharOverride = copyFrom.quoteCharOverride;
@@ -980,8 +980,8 @@ public class WriterSerializer extends Serializer {
        protected final boolean useWhitespace;
        protected final Character quoteChar;
        protected final Character quoteCharOverride;
-       protected final Charset fileCharset;
-       protected final Charset streamCharset;
+       private final Charset fileCharset;
+       private final Charset streamCharset;
        protected final int maxIndent;
 
        private final char quoteCharValue;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializerSession.java
index f189c3a604..1d06c68f79 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializerSession.java
@@ -70,8 +70,8 @@ public class WriterSerializerSession extends 
SerializerSession {
                protected Builder(WriterSerializer ctx) {
                        super(assertArgNotNull("ctx", ctx));
                        this.ctx = ctx;
-                       fileCharset = ctx.fileCharset;
-                       streamCharset = ctx.streamCharset;
+                       fileCharset = ctx.getFileCharset();
+                       streamCharset = ctx.getStreamCharset();
                        useWhitespace = ctx.useWhitespace;
                }
 
@@ -127,12 +127,6 @@ public class WriterSerializerSession extends 
SerializerSession {
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
-
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
                        super.mediaType(value);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/soap/SoapXmlSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/soap/SoapXmlSerializerSession.java
index f0318afbb2..acb37a3476 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/soap/SoapXmlSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/soap/SoapXmlSerializerSession.java
@@ -94,12 +94,6 @@ public class SoapXmlSerializerSession extends 
XmlSerializerSession {
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
-
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
                        super.mediaType(value);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserSession.java
index 55eb53cbbb..b3b3bf3379 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserSession.java
@@ -115,12 +115,6 @@ public class UonParserSession extends ReaderParserSession 
implements HttpPartPar
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
-
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
                        super.mediaType(value);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializerSession.java
index 4bb4f12423..7d00636cde 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializerSession.java
@@ -101,12 +101,6 @@ public class UonSerializerSession extends 
WriterSerializerSession implements Htt
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
-
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
                        super.mediaType(value);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserSession.java
index af3b7c4d60..43c7156314 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserSession.java
@@ -105,12 +105,6 @@ public class UrlEncodingParserSession extends 
UonParserSession {
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
-
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
                        super.mediaType(value);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerSession.java
index dd8a554d7f..9322580068 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerSession.java
@@ -97,12 +97,6 @@ public class UrlEncodingSerializerSession extends 
UonSerializerSession {
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
-
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
                        super.mediaType(value);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlDocSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlDocSerializerSession.java
index 93b41cdda6..da7e17b68a 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlDocSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlDocSerializerSession.java
@@ -91,12 +91,6 @@ public class XmlDocSerializerSession extends 
XmlSerializerSession {
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
-
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
                        super.mediaType(value);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParserSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParserSession.java
index 64d3970183..2f08413a4c 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParserSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParserSession.java
@@ -105,12 +105,6 @@ public class XmlParserSession extends ReaderParserSession {
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
-
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
                        super.mediaType(value);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializer.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializer.java
index b829ea149a..0f0f30fc0a 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializer.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializer.java
@@ -196,12 +196,13 @@ public class XmlSerializer extends WriterSerializer 
implements XmlMetaProvider {
                        super(assertArgNotNull("copyFrom", copyFrom));
                        addBeanTypesXml = copyFrom.addBeanTypesXml;
                        addNamespaceUrisToRoot = 
copyFrom.addNamespaceUrlsToRoot;
-                       defaultNamespace = copyFrom.defaultNamespace;
+                       defaultNamespace = copyFrom.getDefaultNamespace();
                        disableAutoDetectNamespaces = ! 
copyFrom.autoDetectNamespaces;
                        disableJsonTags = ! copyFrom.addJsonTags;
                        enableNamespaces = copyFrom.enableNamespaces;
-                       namespaces = copyFrom.namespaces.isEmpty() ? null : new 
ArrayList<>(copyFrom.namespaces);
-                       textNodeDelimiter = copyFrom.textNodeDelimiter;
+                       var ctxNamespaces = copyFrom.getNamespaces();
+                       namespaces = ctxNamespaces.isEmpty() ? null : new 
ArrayList<>(ctxNamespaces);
+                       textNodeDelimiter = copyFrom.getTextNodeDelimiter();
                }
 
                @Override /* Overridden from Builder */
@@ -1220,9 +1221,9 @@ public class XmlSerializer extends WriterSerializer 
implements XmlMetaProvider {
        protected final boolean addNamespaceUrlsToRoot;
        protected final boolean autoDetectNamespaces;
        protected final boolean enableNamespaces;
-       protected final Namespace defaultNamespace;
-       protected final List<Namespace> namespaces;
-       protected final String textNodeDelimiter;
+       private final Namespace defaultNamespace;
+       private final List<Namespace> namespaces;
+       private final String textNodeDelimiter;
 
        private final boolean addBeanTypes;
        private final Map<ClassMeta<?>,XmlClassMeta> xmlClassMetas = new 
ConcurrentHashMap<>();
@@ -1311,6 +1312,16 @@ public class XmlSerializer extends WriterSerializer 
implements XmlMetaProvider {
         */
        protected final List<Namespace> getNamespaces() { return namespaces; }
 
+       /**
+        * Text node delimiter.
+        *
+        * @see Builder#textNodeDelimiter(String)
+        * @return
+        *      The delimiter string to insert between consecutive text nodes.
+        *      <br>Never <jk>null</jk>.
+        */
+       protected final String getTextNodeDelimiter() { return 
textNodeDelimiter; }
+
        /**
         * Add <js>"_type"</js> properties when needed.
         *
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializerSession.java
index 19d581dda0..584f66ae1e 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializerSession.java
@@ -105,12 +105,6 @@ public class XmlSerializerSession extends 
WriterSerializerSession {
                        return this;
                }
 
-               @Override /* Overridden from Builder */
-               public Builder localeDefault(Locale value) {
-                       super.localeDefault(value);
-                       return this;
-               }
-
                @Override /* Overridden from Builder */
                public Builder mediaType(MediaType value) {
                        super.mediaType(value);
@@ -256,7 +250,7 @@ public class XmlSerializerSession extends 
WriterSerializerSession {
                defaultNamespace = 
findDefaultNamespace(ctx.getDefaultNamespace());
                var ctxNamespaces = ctx.getNamespaces();
                namespaces = ctxNamespaces == null ? new ArrayList<>() : new 
ArrayList<>(ctxNamespaces);
-               textNodeDelimiter = ctx.textNodeDelimiter;
+               textNodeDelimiter = ctx.getTextNodeDelimiter();
        }
 
        /**
@@ -966,16 +960,16 @@ public class XmlSerializerSession extends 
WriterSerializerSession {
                                rc = serializeBeanMap(out, toBeanMap(o), 
elementNamespace, isCollapsed, isMixedOrText);
                        } else if (sType.isCollection() || (nn(wType) && 
wType.isCollection())) {
                                if (isCollapsed)
-                                       this.indent--;
+                                       indent--;
                                serializeCollection(out, o, sType, eType, 
pMeta, isMixedOrText);
                                if (isCollapsed)
-                                       this.indent++;
+                                       indent++;
                        } else if (sType.isArray()) {
                                if (isCollapsed)
-                                       this.indent--;
+                                       indent--;
                                serializeCollection(out, o, sType, eType, 
pMeta, isMixedOrText);
                                if (isCollapsed)
-                                       this.indent++;
+                                       indent++;
                        } else if (sType.isReader()) {
                                pipe((Reader)o, out, 
SerializerSession::handleThrown);
                        } else if (sType.isInputStream()) {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/BeanSession_Test.java 
b/juneau-utest/src/test/java/org/apache/juneau/BeanSession_Test.java
new file mode 100644
index 0000000000..7ab35555c5
--- /dev/null
+++ b/juneau-utest/src/test/java/org/apache/juneau/BeanSession_Test.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.juneau;
+
+import org.junit.jupiter.api.*;
+
+class BeanSession_Test extends TestBase {
+       // Test class for BeanSession
+}
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/ContextSession_Test.java 
b/juneau-utest/src/test/java/org/apache/juneau/ContextSession_Test.java
new file mode 100644
index 0000000000..3c63135af4
--- /dev/null
+++ b/juneau-utest/src/test/java/org/apache/juneau/ContextSession_Test.java
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.juneau;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.junit.jupiter.api.*;
+
+class ContextSession_Test extends TestBase {
+
+       
//====================================================================================================
+       // ContextSession.Builder.property() - Lines 142-149
+       
//====================================================================================================
+
+       @Test void a01_property_addProperty() {
+               // Test line 147: adding a property with non-null value
+               var session = BeanContext.DEFAULT.createSession()
+                       .property("key1", "value1")
+                       .property("key2", 123)
+                       .build();
+               var props = session.getSessionProperties();
+               assertEquals("value1", props.get("key1"));
+               assertEquals(123, props.get("key2"));
+       }
+
+       @Test void a02_property_removeProperty() {
+               // Test line 145: removing a property by setting value to null
+               var session = BeanContext.DEFAULT.createSession()
+                       .property("key1", "value1")
+                       .property("key2", "value2")
+                       .property("key1", null)  // Remove key1
+                       .build();
+               var props = session.getSessionProperties();
+               assertFalse(props.containsKey("key1"));
+               assertEquals("value2", props.get("key2"));
+       }
+
+       @Test void a03_property_nullKey() {
+               // Test line 142: assertArgNotNull on key
+               assertThrows(IllegalArgumentException.class, () -> {
+                       BeanContext.DEFAULT.createSession()
+                               .property(null, "value");
+               });
+       }
+
+       
//====================================================================================================
+       // ContextSession constructor - Line 185
+       
//====================================================================================================
+
+       @Test void b01_unmodifiableSession_emptyProperties() {
+               // Test line 185: unmodifiable session with empty properties 
should use Collections.emptyMap()
+               // Note: The actual implementation may wrap empty maps 
differently, so we test the behavior
+               var session = BeanContext.DEFAULT.createSession()
+                       .unmodifiable()
+                       .build();
+               var props = session.getSessionProperties();
+               // Test line 185: if properties are empty, should use 
Collections.emptyMap() or equivalent
+               // The key test is that it's unmodifiable and empty
+               assertTrue(props.isEmpty());
+               assertThrows(UnsupportedOperationException.class, () -> {
+                       props.put("key", "value");
+               });
+       }
+
+       @Test void b02_unmodifiableSession_withProperties() {
+               // Test line 185: unmodifiable session with properties should 
use unmodifiable map
+               var session = BeanContext.DEFAULT.createSession()
+                       .property("key1", "value1")
+                       .property("key2", "value2")
+                       .unmodifiable()
+                       .build();
+               var props = session.getSessionProperties();
+               assertEquals("value1", props.get("key1"));
+               assertEquals("value2", props.get("key2"));
+               // Verify it's unmodifiable
+               assertThrows(UnsupportedOperationException.class, () -> {
+                       props.put("key3", "value3");
+               });
+       }
+
+       
//====================================================================================================
+       // ContextSession.addWarning() - Line 201
+       
//====================================================================================================
+
+       @Test void c01_addWarning_unmodifiableSession() {
+               // Test line 201: addWarning should return early if session is 
unmodifiable
+               var session = BeanContext.DEFAULT.createSession()
+                       .unmodifiable()
+                       .build();
+               // Should not throw exception, just return early
+               session.addWarning("Test warning");
+               assertTrue(session.getWarnings().isEmpty());
+       }
+
+       @Test void c02_addWarning_modifiableSession() {
+               // Test that addWarning works on modifiable sessions
+               var session = BeanContext.DEFAULT.createSession()
+                       .build();
+               session.addWarning("Test warning");
+               var warnings = session.getWarnings();
+               assertFalse(warnings.isEmpty());
+               assertTrue(warnings.get(0).contains("Test warning"));
+       }
+
+       
//====================================================================================================
+       // ContextSession.getContext() - Line 220
+       
//====================================================================================================
+
+       @Test void d01_getContext() {
+               // Test line 220: getContext() returns the context that created 
the session
+               var context = BeanContext.DEFAULT;
+               var session = context.createSession().build();
+               assertSame(context, session.getContext());
+       }
+}
+
diff --git a/juneau-utest/src/test/java/org/apache/juneau/rest/Nls_Test.java 
b/juneau-utest/src/test/java/org/apache/juneau/rest/Nls_Test.java
index ef773d2978..d5e686f60a 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/rest/Nls_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/rest/Nls_Test.java
@@ -18,6 +18,7 @@ package org.apache.juneau.rest;
 
 import org.apache.juneau.*;
 import org.apache.juneau.bean.swagger.Swagger;
+import org.apache.juneau.commons.utils.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.mock.*;
 import org.apache.juneau.serializer.*;
@@ -53,7 +54,7 @@ class Nls_Test extends TestBase {
                }
 
                public static String out(SerializerSession s) {
-                       return 
s.getSessionProperties().getString("TestProperty",null);
+                       return 
Utils.s(s.getSessionProperties().get("TestProperty"));
                }
        }
 
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_DefaultRequestAttributes_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_DefaultRequestAttributes_Test.java
index cb7f2651c5..f03ea9eb8a 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_DefaultRequestAttributes_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_DefaultRequestAttributes_Test.java
@@ -84,7 +84,7 @@ class Rest_DefaultRequestAttributes_Test extends TestBase {
 
                private static Object in(ReaderParserSession session) {
                        var sp = session.getSessionProperties();
-                       return 
"p1="+sp.get("p1",null)+",p2="+sp.get("p2",null)+",p3="+sp.get("p3",null)+",p4="+sp.get("p4",null)+",p5="+sp.get("p5",null);
+                       return 
"p1="+sp.get("p1")+",p2="+sp.get("p2")+",p3="+sp.get("p3")+",p4="+sp.get("p4")+",p5="+sp.get("p5");
 
                }
        }
@@ -154,12 +154,12 @@ class Rest_DefaultRequestAttributes_Test extends TestBase 
{
                }
                public static String out(SerializerSession s) {
                        var sp = s.getSessionProperties();
-                       return 
"p1="+sp.get("p1",null)+",p2="+sp.get("p2",null)+",p3="+sp.get("p3",null)+",p4="+sp.get("p4",null)+",p5="+sp.get("p5",null);
+                       return 
"p1="+sp.get("p1")+",p2="+sp.get("p2")+",p3="+sp.get("p3")+",p4="+sp.get("p4")+",p5="+sp.get("p5");
                }
                public static Map<String,String> headers(SerializerSession s) {
                        var sp = s.getSessionProperties();
                        if (sp.containsKey("Override-Content-Type"))
-                               return 
m("Content-Type",sp.getString("Override-Content-Type",null));
+                               return 
m("Content-Type",sp.get("Override-Content-Type").toString());
                        return emptyMap();
                }
        }
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_RVars_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_RVars_Test.java
index cb1ae3dbd6..535c452dda 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_RVars_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_RVars_Test.java
@@ -68,8 +68,8 @@ class Rest_RVars_Test extends TestBase {
                        public static String out(SerializerSession s) {
                                var sp = s.getSessionProperties();
                                return 
format("A1=%s,A2=%s,B1=%s,B2=%s,C=%s,R1a=%s,R1b=%s,R2=%s,R3=%s,R4=%s,R5=%s,R6=%s",
-                                       sp.get("A1",null), sp.get("A2",null), 
sp.get("B1",null), sp.get("B2",null), sp.get("C",null),
-                                       sp.get("R1a",null), sp.get("R1b",null), 
sp.get("R2",null), sp.get("R3",null), sp.get("R4",null), sp.get("R5",null), 
sp.get("R6",null));
+                                       sp.get("A1"), sp.get("A2"), 
sp.get("B1"), sp.get("B2"), sp.get("C"),
+                                       sp.get("R1a"), sp.get("R1b"), 
sp.get("R2"), sp.get("R3"), sp.get("R4"), sp.get("R5"), sp.get("R6"));
                        }
                }
        }

Reply via email to