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 02e831c  Context API refactoring.
02e831c is described below

commit 02e831c9560f1db0f5ebf88c5b359e49352d6b74
Author: JamesBognar <[email protected]>
AuthorDate: Thu Sep 9 13:35:04 2021 -0400

    Context API refactoring.
---
 .../org/apache/juneau/BasicRuntimeException.java   |  10 ++
 .../java/org/apache/juneau/ContextProperties.java  |   4 +-
 .../org/apache/juneau/ExecutableException.java     |   2 +-
 .../main/java/org/apache/juneau/cp/BeanStore.java  | 137 ++++++++++++++++++---
 .../org/apache/juneau/cp/BeanStoreBuilder.java     | 101 ---------------
 .../apache/juneau/httppart/BaseHttpPartParser.java |  33 ++++-
 .../juneau/httppart/BaseHttpPartSerializer.java    |  33 ++++-
 .../apache/juneau/httppart/SimplePartParser.java   |  53 +++++++-
 .../juneau/httppart/SimplePartSerializer.java      |  53 +++++++-
 .../juneau/httppart/bean/RequestBeanMeta.java      |   6 +-
 .../httppart/bean/RequestBeanPropertyMeta.java     |   6 +-
 .../java/org/apache/juneau/internal/Function2.java |  18 ++-
 .../java/org/apache/juneau/internal/Function3.java |  15 ++-
 .../java/org/apache/juneau/internal/Function4.java |  20 ++-
 .../org/apache/juneau/mstat/MethodExecStore.java   |   4 +-
 .../java/org/apache/juneau/mstat/ThrownStore.java  |   2 +-
 .../main/java/org/apache/juneau/parser/Parser.java |   6 +-
 .../org/apache/juneau/svl/VarResolverBuilder.java  |   4 +-
 .../rest/test/client/ThirdPartyProxyTest.java      |  29 +++++
 .../org/apache/juneau/rest/client/RestClient.java  |   2 +-
 .../rest/client/remote/RemoteOperationArg.java     |  23 +---
 .../java/org/apache/juneau/rest/RestContext.java   |   8 +-
 .../apache/juneau/http/remote/ListSerializer.java  |  39 ------
 .../remote/Remote_FormDataAnnotation_Test.java     |  20 +--
 .../http/remote/Remote_HeaderAnnotation_Test.java  |  20 +--
 .../http/remote/Remote_PathAnnotation_Test.java    |  20 +--
 .../http/remote/Remote_QueryAnnotation_Test.java   |  20 +--
 .../http/remote/Remote_RequestAnnotation_Test.java |   2 +-
 .../org/apache/juneau/http/remote/XSerializer.java |  39 ------
 .../client/RestClient_Config_RestClient_Test.java  |  43 +++----
 .../rest/client/RestClient_FormData_Test.java      |  19 +--
 .../rest/client/RestClient_Headers_Test.java       |  14 +--
 .../juneau/rest/client/RestClient_Query_Test.java  |  20 +--
 .../apache/juneau/testutils/MockReaderParser.java  |  48 +++++++-
 .../juneau/testutils/MockReaderParserFunction.java |   3 +-
 ...tion.java => MockReaderParserPartFunction.java} |   5 +-
 .../juneau/testutils/MockStreamParserFunction.java |   3 +-
 .../juneau/testutils/MockWriterSerializer.java     |  62 +++++++++-
 .../testutils/MockWriterSerializerFunction.java    |   5 +-
 ....java => MockWriterSerializerPartFunction.java} |  14 +--
 .../apache/juneau/testutils/XPartSerializer.java   |  37 ------
 41 files changed, 573 insertions(+), 429 deletions(-)

diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BasicRuntimeException.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BasicRuntimeException.java
index 21a2239..8b0756e 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BasicRuntimeException.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BasicRuntimeException.java
@@ -112,6 +112,16 @@ public abstract class BasicRuntimeException extends 
RuntimeException {
        }
 
        /**
+        * Returns the caused-by exception if there is one.
+        *
+        * @return The caused-by exception if there is one, or this exception 
if there isn't.
+        */
+       public Throwable unwrap() {
+               Throwable t = getCause();
+               return t == null ? this : t;
+       }
+
+       /**
         * Throws an {@link UnsupportedOperationException} if the unmodifiable 
flag is set on this bean.
         */
        protected final void assertModifiable() {
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextProperties.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextProperties.java
index 143580a..6522d3f 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextProperties.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextProperties.java
@@ -914,15 +914,13 @@ public final class ContextProperties {
        // Utility methods
        
//-------------------------------------------------------------------------------------------------------------------
 
-       static BeanStore DEFAULT_BEAN_STORE = BeanStore.create().build();
-
        static <T> T instantiate(BeanStore beanStore, Class<T> c, Object value) 
{
                if (ClassInfo.of(c).isParentOf(value.getClass()))
                        return (T)value;
                try {
                        if 
(ClassInfo.of(value.getClass()).isChildOf(Class.class)) {
                                if (beanStore == null)
-                                       beanStore = DEFAULT_BEAN_STORE;
+                                       beanStore = BeanStore.INSTANCE;
                                return beanStore.createBean((Class<T>)value);
                        }
                } catch (ExecutableException e) {
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ExecutableException.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ExecutableException.java
index 764c382..bc0728c 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ExecutableException.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ExecutableException.java
@@ -17,7 +17,7 @@ import java.text.MessageFormat;
 /**
  * General exception that occurs when trying to execute a constructor, method, 
or field using reflection.
  */
-public class ExecutableException extends BasicException {
+public class ExecutableException extends BasicRuntimeException {
 
        private static final long serialVersionUID = 1L;
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BeanStore.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BeanStore.java
index 42153d0..54e176d 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BeanStore.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BeanStore.java
@@ -12,9 +12,11 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.cp;
 
+import static org.apache.juneau.internal.ClassUtils.*;
 import static org.apache.juneau.internal.ExceptionUtils.*;
 import static org.apache.juneau.internal.StringUtils.*;
 import static org.apache.juneau.reflect.ReflectFlags.*;
+import static java.util.Optional.*;
 
 import java.lang.annotation.*;
 import java.util.*;
@@ -41,17 +43,23 @@ public class BeanStore {
         */
        public static final class Null extends BeanStore {}
 
+       /**
+        * Static read-only reusable instance.
+        */
+       public static final BeanStore INSTANCE = create().readOnly().build();
+
        private final Map<String,Supplier<?>> beanMap = new 
ConcurrentHashMap<>();
        private final Optional<BeanStore> parent;
        private final Optional<Object> outer;
+       private final boolean readOnly;
 
        /**
         * Static creator.
         *
-        * @return A new {@link BeanStoreBuilder} object.
+        * @return A new {@link Builder} object.
         */
-       public static BeanStoreBuilder create() {
-               return new BeanStoreBuilder();
+       public static Builder create() {
+               return new Builder();
        }
 
        /**
@@ -75,12 +83,10 @@ public class BeanStore {
                return create().parent(parent).outer(outer).build();
        }
 
-       /**
-        * Default constructor.
-        */
-       public BeanStore() {
-               this.parent = Optional.empty();
-               this.outer = Optional.empty();
+       BeanStore() {
+               this.parent = empty();
+               this.outer = empty();
+               this.readOnly = false;
        }
 
        /**
@@ -88,9 +94,95 @@ public class BeanStore {
         *
         * @param builder The builder containing the settings for this bean.
         */
-       public BeanStore(BeanStoreBuilder builder) {
-               this.parent = Optional.ofNullable(builder.parent);
-               this.outer = Optional.ofNullable(builder.outer);
+       public BeanStore(Builder builder) {
+               this.parent = ofNullable(builder.parent);
+               this.outer = ofNullable(builder.outer);
+               this.readOnly = builder.readOnly;
+       }
+
+       /**
+        * The builder for this object.
+        */
+       public static class Builder {
+
+               Class<? extends BeanStore> implClass = BeanStore.class;
+               Object outer;
+               BeanStore parent;
+               boolean readOnly;
+
+               /**
+                * Create a new {@link BeanStore} using this builder.
+                *
+                * @return A new {@link BeanStore}
+                */
+               public BeanStore build() {
+                       try {
+                               if (implClass == BeanStore.class)
+                                       return new BeanStore(this);
+                               Class<? extends BeanStore> ic = 
isConcrete(implClass) ? implClass : BeanStore.class;
+                               return new BeanStore().addBeans(Builder.class, 
this).createBean(ic);
+                       } catch (ExecutableException e) {
+                               throw runtimeException(e);
+                       }
+               }
+
+               /**
+                * Specifies a subclass of {@link BeanStore} to create when the 
{@link #build()} method is called.
+                *
+                * @param value The new value for this setting.
+                * @return  This object (for method chaining).
+                */
+               @FluentSetter
+               public Builder implClass(Class<? extends BeanStore> value) {
+                       implClass = value;
+                       return this;
+               }
+
+               /**
+                * Specifies the parent bean store.
+                *
+                * <p>
+                * Bean searches are performed recursively up this parent chain.
+                *
+                * @param value The new value for this setting.
+                * @return  This object (for method chaining).
+                */
+               @FluentSetter
+               public Builder parent(BeanStore value) {
+                       parent = value;
+                       return this;
+               }
+
+               /**
+                * Specifies that the bean store is read-only.
+                *
+                * <p>
+                * This means methods such as {@link BeanStore#addBean(Class, 
Object)} cannot be used.
+                *
+                * @return  This object (for method chaining).
+                */
+               @FluentSetter
+               public Builder readOnly() {
+                       readOnly = true;
+                       return this;
+               }
+
+               /**
+                * Specifies the outer bean context.
+                *
+                * <p>
+                * Used when calling {@link BeanStore#createBean(Class)} on a 
non-static inner class.
+                * This should be the instance of the outer object such as the 
servlet object when constructing inner classes
+                * of the servlet class.
+                *
+                * @param value The new value for this setting.
+                * @return  This object (for method chaining).
+                */
+               @FluentSetter
+               public Builder outer(Object value) {
+                       outer = value;
+                       return this;
+               }
        }
 
        /**
@@ -131,6 +223,7 @@ public class BeanStore {
         * @return This object (for method chaining).
         */
        public <T> BeanStore addBean(Class<T> c, T t) {
+               assertCanWrite();
                return addBean(c.getName(), t);
        }
 
@@ -143,6 +236,7 @@ public class BeanStore {
         * @return This object (for method chaining).
         */
        public <T> BeanStore addBean(String name, T t) {
+               assertCanWrite();
                if (t == null)
                        beanMap.remove(name);
                else
@@ -160,6 +254,7 @@ public class BeanStore {
         */
        @SuppressWarnings("unchecked")
        public <T> BeanStore addBeans(Class<T> c, T t) {
+               assertCanWrite();
                if (t == null)
                        beanMap.remove(c.getName());
                else {
@@ -182,6 +277,7 @@ public class BeanStore {
         * @return This object (for method chaining).
         */
        public <T> BeanStore addSupplier(Class<T> c, Supplier<T> t) {
+               assertCanWrite();
                return addSupplier(c.getName(), t);
        }
 
@@ -194,6 +290,7 @@ public class BeanStore {
         * @return This object (for method chaining).
         */
        public <T> BeanStore addSupplier(String name, Supplier<T> t) {
+               assertCanWrite();
                if (t == null)
                        beanMap.remove(name);
                else
@@ -229,12 +326,15 @@ public class BeanStore {
         * Creates a bean of the specified type.
         *
         * @param <T> The bean type to create.
-        * @param c The bean type to create.
-        * @return A newly-created bean.
+        * @param c The bean type to create.  Can be <jk>null</jk>.
+        * @return A newly-created bean, or <jk>null</jk> if the type was 
<jk>null</jk>.
         * @throws ExecutableException If bean could not be created.
         */
        public <T> T createBean(Class<T> c) throws ExecutableException {
 
+               if (c == null)
+                       return null;
+
                Optional<T> o = getBean(c);
                if (o.isPresent())
                        return o.get();
@@ -320,8 +420,8 @@ public class BeanStore {
         * @return A newly-created bean.
         * @throws ExecutableException If bean could not be created.
         */
-       public <T> T createBean(Class<T> c, Class<? extends T> type) throws 
ExecutableException {
-               if (! c.isAssignableFrom(type))
+       public <T> T createBean(Class<T> c, Class<? extends T> type) {
+               if (type != null && ! c.isAssignableFrom(type))
                        throw new ExecutableException("Could not instantiate 
class of type {0} because it was not a subtype of the class: {1}.", 
c.getName(), type);
                return createBean(type);
        }
@@ -459,6 +559,11 @@ public class BeanStore {
                        .a("parent", parent.orElse(null));
        }
 
+       private void assertCanWrite() {
+               if (readOnly)
+                       throw runtimeException("Method cannot be used because 
BeanStore is read-only.");
+       }
+
        @Override /* Object */
        public String toString() {
                return toMap().toString();
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BeanStoreBuilder.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BeanStoreBuilder.java
deleted file mode 100644
index 6a2ad90..0000000
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BeanStoreBuilder.java
+++ /dev/null
@@ -1,101 +0,0 @@
-// 
***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright 
ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not 
use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                
                                              *
-// *                                                                           
                                              *
-// *  http://www.apache.org/licenses/LICENSE-2.0                               
                                              *
-// *                                                                           
                                              *
-// * Unless required by applicable law or agreed to in writing, software 
distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the 
License.                                              *
-// 
***************************************************************************************************************************
-package org.apache.juneau.cp;
-
-import static org.apache.juneau.internal.ClassUtils.*;
-import static org.apache.juneau.internal.ExceptionUtils.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.internal.*;
-
-/**
- * Builder for {@link BeanStore} objects.
- */
-@FluentSetters
-public class BeanStoreBuilder {
-
-       private Class<? extends BeanStore> implClass;
-       Object outer;
-       BeanStore parent;
-
-       /**
-        * Create a new {@link BeanStore} using this builder.
-        *
-        * @return A new {@link BeanStore}
-        */
-       public BeanStore build() {
-               try {
-                       Class<? extends BeanStore> ic = isConcrete(implClass) ? 
implClass : getDefaultImplClass();
-                       return new BeanStore().addBeans(BeanStoreBuilder.class, 
this).createBean(ic);
-               } catch (ExecutableException e) {
-                       throw runtimeException(e);
-               }
-       }
-
-       /**
-        * Specifies the default implementation class if not specified via 
{@link #implClass(Class)}.
-        *
-        * @return The default implementation class if not specified via {@link 
#implClass(Class)}.
-        */
-       protected Class<? extends BeanStore> getDefaultImplClass() {
-               return BeanStore.class;
-       }
-
-       /**
-        * Specifies a subclass of {@link BeanStore} to create when the {@link 
#build()} method is called.
-        *
-        * @param value The new value for this setting.
-        * @return  This object (for method chaining).
-        */
-       @FluentSetter
-       public BeanStoreBuilder implClass(Class<? extends BeanStore> value) {
-               this.implClass = value;
-               return this;
-       }
-
-       /**
-        * Specifies the parent bean store.
-        *
-        * <p>
-        * Bean searches are performed recursively up this parent chain.
-        *
-        * @param value The new value for this setting.
-        * @return  This object (for method chaining).
-        */
-       @FluentSetter
-       public BeanStoreBuilder parent(BeanStore value) {
-               this.parent = value;
-               return this;
-       }
-
-       /**
-        * Specifies the outer bean context.
-        *
-        * <p>
-        * Used when calling {@link BeanStore#createBean(Class)} on a 
non-static inner class.
-        * This should be the instance of the outer object such as the servlet 
object when constructing inner classes
-        * of the servlet class.
-        *
-        * @param value The new value for this setting.
-        * @return  This object (for method chaining).
-        */
-       @FluentSetter
-       public BeanStoreBuilder outer(Object value) {
-               this.outer = value;
-               return this;
-       }
-
-       // <FluentSetters>
-
-       // </FluentSetters>
-}
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/BaseHttpPartParser.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/BaseHttpPartParser.java
index f6b199d..ef20bb7 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/BaseHttpPartParser.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/BaseHttpPartParser.java
@@ -20,7 +20,38 @@ import org.apache.juneau.parser.*;
 /**
  * Base class for implementations of {@link HttpPartParser}
  */
-public abstract class BaseHttpPartParser implements HttpPartParser {
+public abstract class BaseHttpPartParser extends BeanContextable implements 
HttpPartParser {
+
+       /**
+        * Constructor.
+        *
+        * @param builder The builder for this object.
+        */
+       protected BaseHttpPartParser(Builder builder) {
+               super(builder);
+       }
+
+       /**
+        * The builder class for this object.
+        */
+       public abstract static class Builder extends BeanContextableBuilder {
+
+               /**
+                * Constructor.
+                */
+               protected Builder() {
+                       super();
+               }
+
+               /**
+                * Copy constructor.
+                * 
+                * @param builder The builder to copy.
+                */
+               protected Builder(Builder builder) {
+                       super(builder);
+               }
+       }
 
        /**
         * Converts the specified input to the specified class type.
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/BaseHttpPartSerializer.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/BaseHttpPartSerializer.java
index a7ceed3..edff50a 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/BaseHttpPartSerializer.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/BaseHttpPartSerializer.java
@@ -12,12 +12,43 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.httppart;
 
+import org.apache.juneau.*;
 import org.apache.juneau.serializer.*;
 
 /**
  * Base class for implementations of {@link HttpPartSerializer}
  */
-public abstract class BaseHttpPartSerializer implements HttpPartSerializer {
+public abstract class BaseHttpPartSerializer extends BeanContextable 
implements HttpPartSerializer {
+
+       /**
+        * Constructor.
+        *
+        * @param builder The builder for this object.
+        */
+       protected BaseHttpPartSerializer(Builder builder) {
+               super(builder);
+       }
+
+       /**
+        * The builder class for this object.
+        */
+       public abstract static class Builder extends BeanContextableBuilder {
+
+               /**
+                * Constructor.
+                */
+               protected Builder() {
+                       super();
+               }
+
+               /**
+                * Copy constructor.
+                * @param builder The existing builder to copy.
+                */
+               protected Builder(Builder builder) {
+                       super(builder);
+               }
+       }
 
        /**
         * Converts the specified value to a string that can be used as an HTTP 
header value, query parameter value,
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/SimplePartParser.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/SimplePartParser.java
index b47cf12..7a7664f 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/SimplePartParser.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/SimplePartParser.java
@@ -12,6 +12,9 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.httppart;
 
+import static org.apache.juneau.internal.ExceptionUtils.*;
+
+import org.apache.juneau.*;
 import org.apache.juneau.parser.*;
 
 /**
@@ -45,7 +48,7 @@ public class SimplePartParser extends BaseHttpPartParser {
        
//-------------------------------------------------------------------------------------------------------------------
 
        /** Reusable instance of {@link SimplePartParser}, all default 
settings. */
-       public static final SimplePartParser DEFAULT = new SimplePartParser();
+       public static final SimplePartParser DEFAULT = create().build();
 
        /** Reusable instance of {@link SimplePartParser}, all default 
settings. */
        public static final SimplePartParserSession DEFAULT_SESSION = 
DEFAULT.createPartSession(null);
@@ -55,8 +58,56 @@ public class SimplePartParser extends BaseHttpPartParser {
        // Instance
        
//-------------------------------------------------------------------------------------------------------------------
 
+       /**
+        * Static creator.
+        *
+        * @return A new builder for this object.
+        */
+       public static Builder create() {
+               return new Builder();
+       }
+
+       /**
+        * Constructor
+        *
+        * @param builder The builder for this object.
+        */
+       protected SimplePartParser(Builder builder) {
+               super(builder);
+       }
+
+       /**
+        * The builder for this object.
+        *
+        */
+       public static class Builder extends BaseHttpPartParser.Builder {
+
+               Builder() {
+                       super();
+               }
+
+               Builder(Builder builder) {
+                       super(builder);
+               }
+
+               @Override
+               public SimplePartParser build() {
+                       return new SimplePartParser(this);
+               }
+
+               @Override
+               public BeanContextableBuilder copy() {
+                       return new Builder(this);
+               }
+       }
+
        @Override
        public SimplePartParserSession createPartSession(ParserSessionArgs 
args) {
                return new SimplePartParserSession();
        }
+
+       @Override
+       public Builder copy() {
+               throw unsupportedOperationException("Not implemented.");
+       }
 }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/SimplePartSerializer.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/SimplePartSerializer.java
index 44cd1d5..9bcb892 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/SimplePartSerializer.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/SimplePartSerializer.java
@@ -12,6 +12,9 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.httppart;
 
+import static org.apache.juneau.internal.ExceptionUtils.*;
+
+import org.apache.juneau.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.serializer.*;
 
@@ -28,14 +31,62 @@ public class SimplePartSerializer extends 
BaseHttpPartSerializer {
        
//-------------------------------------------------------------------------------------------------------------------
 
        /** Reusable instance of {@link SimplePartSerializer}, all default 
settings. */
-       public static final SimplePartSerializer DEFAULT = new 
SimplePartSerializer();
+       public static final SimplePartSerializer DEFAULT = create().build();
 
        
//-------------------------------------------------------------------------------------------------------------------
        // Instance
        
//-------------------------------------------------------------------------------------------------------------------
 
+       /**
+        * Static creator.
+        *
+        * @return A new builder for this object.
+        */
+       public static Builder create() {
+               return new Builder();
+       }
+
+       /**
+        * Constructor
+        *
+        * @param builder The builder for this object.
+        */
+       protected SimplePartSerializer(Builder builder) {
+               super(builder);
+       }
+
+       /**
+        * The builder for this object.
+        *
+        */
+       public static class Builder extends BaseHttpPartSerializer.Builder {
+
+               Builder() {
+                       super();
+               }
+
+               Builder(Builder builder) {
+                       super(builder);
+               }
+
+               @Override
+               public SimplePartSerializer build() {
+                       return new SimplePartSerializer(this);
+               }
+
+               @Override
+               public BeanContextableBuilder copy() {
+                       return new Builder(this);
+               }
+       }
+
        @Override
        public SimplePartSerializerSession 
createPartSession(SerializerSessionArgs args) {
                return new SimplePartSerializerSession();
        }
+
+       @Override
+       public Builder copy() {
+               throw unsupportedOperationException("Not implemented.");
+       }
 }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/RequestBeanMeta.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/RequestBeanMeta.java
index d689238..0808740 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/RequestBeanMeta.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/RequestBeanMeta.java
@@ -13,13 +13,13 @@
 package org.apache.juneau.httppart.bean;
 
 import static org.apache.juneau.httppart.bean.Utils.*;
-import static org.apache.juneau.internal.ClassUtils.*;
 import static org.apache.juneau.httppart.HttpPartType.*;
 import static org.apache.juneau.annotation.InvalidAnnotationException.*;
 
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.cp.*;
 import org.apache.juneau.http.annotation.*;
 import org.apache.juneau.httppart.*;
 import org.apache.juneau.reflect.*;
@@ -71,8 +71,8 @@ public class RequestBeanMeta {
 
        RequestBeanMeta(Builder b) {
                this.cm = b.cm;
-               this.serializer = castOrCreate(HttpPartSerializer.class, 
b.serializer, true, b.cp);
-               this.parser = castOrCreate(HttpPartParser.class, b.parser, 
true, b.cp);
+               this.serializer = 
BeanStore.INSTANCE.createBean(HttpPartSerializer.class, b.serializer);
+               this.parser = 
BeanStore.INSTANCE.createBean(HttpPartParser.class, b.parser);
                Map<String,RequestBeanPropertyMeta> properties = new 
LinkedHashMap<>();
                for (Map.Entry<String,RequestBeanPropertyMeta.Builder> e : 
b.properties.entrySet())
                        properties.put(e.getKey(), 
e.getValue().build(serializer, parser));
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/RequestBeanPropertyMeta.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/RequestBeanPropertyMeta.java
index f5e98ed..bcbb3e9 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/RequestBeanPropertyMeta.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/bean/RequestBeanPropertyMeta.java
@@ -12,7 +12,6 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.httppart.bean;
 
-import static org.apache.juneau.internal.ClassUtils.*;
 import static java.util.Optional.*;
 
 import java.lang.annotation.*;
@@ -20,6 +19,7 @@ import java.lang.reflect.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.cp.*;
 import org.apache.juneau.http.annotation.*;
 import org.apache.juneau.httppart.*;
 import org.apache.juneau.reflect.*;
@@ -50,8 +50,8 @@ public class RequestBeanPropertyMeta {
                this.partType = b.partType;
                this.schema = b.schema;
                this.getter = b.getter;
-               this.serializer = ofNullable(schema.getSerializer() == null ? 
serializer : castOrCreate(HttpPartSerializer.class, schema.getSerializer(), 
true, b.cp));
-               this.parser = schema.getParser() == null ? parser : 
castOrCreate(HttpPartParser.class, schema.getParser(), true, b.cp);
+               this.serializer = ofNullable(schema.getSerializer() == null ? 
serializer : BeanStore.INSTANCE.createBean(HttpPartSerializer.class, 
schema.getSerializer()));
+               this.parser = schema.getParser() == null ? parser : 
BeanStore.INSTANCE.createBean(HttpPartParser.class, schema.getParser());
        }
 
        static class Builder {
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/testutils/TriFunction.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/Function2.java
similarity index 80%
copy from 
juneau-utest/src/test/java/org/apache/juneau/testutils/TriFunction.java
copy to 
juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/Function2.java
index 96511ce..332942a 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/testutils/TriFunction.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/Function2.java
@@ -10,18 +10,26 @@
 //* "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.testutils;
+package org.apache.juneau.internal;
 
 import java.util.*;
 import java.util.function.*;
 
+/**
+ * A function that takes in 2 arguments.
+ *
+ * @param <A> The first argument.
+ * @param <B> The second argument.
+ * @param <R> The return type.
+ */
+@SuppressWarnings("javadoc")
 @FunctionalInterface
-interface TriFunction<A,B,C,R> {
+public interface Function2<A,B,R> {
 
-       R apply(A a, B b, C c);
+       R apply(A a, B b);
 
-       default <V> TriFunction<A, B, C, V> andThen(Function<? super R, ? 
extends V> after) {
+       default <V> Function2<A, B, V> andThen(Function<? super R, ? extends V> 
after) {
                Objects.requireNonNull(after);
-               return (A a, B b, C c) -> after.apply(apply(a, b, c));
+               return (A a, B b) -> after.apply(apply(a, b));
        }
 }
\ No newline at end of file
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/testutils/TriFunction.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/Function3.java
similarity index 81%
copy from 
juneau-utest/src/test/java/org/apache/juneau/testutils/TriFunction.java
copy to 
juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/Function3.java
index 96511ce..bc6f2e0 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/testutils/TriFunction.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/Function3.java
@@ -10,17 +10,26 @@
 //* "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.testutils;
+package org.apache.juneau.internal;
 
 import java.util.*;
 import java.util.function.*;
 
+/**
+ * A function that takes in 3 arguments.
+ *
+ * @param <A> The first argument.
+ * @param <B> The second argument.
+ * @param <C> The third argument.
+ * @param <R> The return type.
+ */
+@SuppressWarnings("javadoc")
 @FunctionalInterface
-interface TriFunction<A,B,C,R> {
+public interface Function3<A,B,C,R> {
 
        R apply(A a, B b, C c);
 
-       default <V> TriFunction<A, B, C, V> andThen(Function<? super R, ? 
extends V> after) {
+       default <V> Function3<A, B, C, V> andThen(Function<? super R, ? extends 
V> after) {
                Objects.requireNonNull(after);
                return (A a, B b, C c) -> after.apply(apply(a, b, c));
        }
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/testutils/TriFunction.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/Function4.java
similarity index 76%
copy from 
juneau-utest/src/test/java/org/apache/juneau/testutils/TriFunction.java
copy to 
juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/Function4.java
index 96511ce..443e7b4 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/testutils/TriFunction.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/Function4.java
@@ -10,18 +10,28 @@
 //* "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.testutils;
+package org.apache.juneau.internal;
 
 import java.util.*;
 import java.util.function.*;
 
+/**
+ * A function that takes in 4 arguments.
+ *
+ * @param <A> The first argument.
+ * @param <B> The second argument.
+ * @param <C> The third argument.
+ * @param <D> The fourth argument.
+ * @param <R> The return type.
+ */
+@SuppressWarnings("javadoc")
 @FunctionalInterface
-interface TriFunction<A,B,C,R> {
+public interface Function4<A,B,C,D,R> {
 
-       R apply(A a, B b, C c);
+       R apply(A a, B b, C c, D d);
 
-       default <V> TriFunction<A, B, C, V> andThen(Function<? super R, ? 
extends V> after) {
+       default <V> Function4<A, B, C, D, V> andThen(Function<? super R, ? 
extends V> after) {
                Objects.requireNonNull(after);
-               return (A a, B b, C c) -> after.apply(apply(a, b, c));
+               return (A a, B b, C c, D d) -> after.apply(apply(a, b, c ,d));
        }
 }
\ No newline at end of file
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/mstat/MethodExecStore.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/mstat/MethodExecStore.java
index e538b08..39a9a4b 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/mstat/MethodExecStore.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/mstat/MethodExecStore.java
@@ -22,7 +22,7 @@ import org.apache.juneau.cp.*;
 
 /**
  * Method execution statistics database.
- * 
+ *
  * <p>
  * Used for tracking basic call statistics on Java methods.
  */
@@ -55,7 +55,7 @@ public class MethodExecStore {
         * @param builder The store to use for storing thrown exception 
statistics.
         */
        public MethodExecStore(MethodExecStoreBuilder builder) {
-               this.beanStore = 
ofNullable(builder.beanStore).orElseGet(BeanStore::new);
+               this.beanStore = 
ofNullable(builder.beanStore).orElseGet(()->BeanStore.create().build());
                this.thrownStore = 
ofNullable(builder.thrownStore).orElse(beanStore.getBean(ThrownStore.class).orElseGet(ThrownStore::new));
                this.statsImplClass = builder.statsImplClass;
        }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/mstat/ThrownStore.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/mstat/ThrownStore.java
index be3a95e..d0c0400 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/mstat/ThrownStore.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/mstat/ThrownStore.java
@@ -63,7 +63,7 @@ public class ThrownStore {
         */
        public ThrownStore(ThrownStoreBuilder builder) {
                this.parent = ofNullable(builder.parent);
-               this.beanStore = 
ofNullable(builder.beanStore).orElseGet(BeanStore::new);
+               this.beanStore = 
ofNullable(builder.beanStore).orElseGet(()->BeanStore.create().build());
 
                this.statsImplClass = firstNonNull(builder.statsImplClass, 
parent.isPresent() ? parent.get().statsImplClass : null, null);
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/Parser.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/Parser.java
index 3b8e956..86b334a 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/Parser.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/Parser.java
@@ -12,6 +12,8 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.parser;
 
+import static java.util.Optional.*;
+
 import java.io.*;
 import java.lang.reflect.*;
 import java.util.*;
@@ -330,7 +332,7 @@ public abstract class Parser extends BeanContextable {
        protected Parser(ParserBuilder builder) {
                super(builder);
 
-               _consumes = builder.consumes;
+               _consumes = ofNullable(builder.consumes).orElse("");
                ContextProperties cp = getContextProperties();
                trimStrings = cp.getBoolean(PARSER_trimStrings).orElse(false);
                strict = cp.getBoolean(PARSER_strict).orElse(false);
@@ -339,7 +341,7 @@ public abstract class Parser extends BeanContextable {
                unbuffered = cp.getBoolean(PARSER_unbuffered).orElse(false);
                listener = cp.getClass(PARSER_listener, 
ParserListener.class).orElse(null);
 
-               String[] consumes = StringUtils.split(builder.consumes, ',');
+               String[] consumes = StringUtils.split(_consumes, ',');
                this.consumes = new MediaType[consumes.length];
                for (int i = 0; i < consumes.length; i++) {
                        this.consumes[i] = MediaType.of(consumes[i]);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/VarResolverBuilder.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/VarResolverBuilder.java
index f479bba..54ae243 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/VarResolverBuilder.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/VarResolverBuilder.java
@@ -30,14 +30,14 @@ import org.apache.juneau.svl.vars.*;
 public class VarResolverBuilder {
 
        private final List<Var> vars;
-       private BeanStore beanStore = new BeanStore();
+       private BeanStore beanStore;
 
        /**
         * Constructor.
         */
        public VarResolverBuilder() {
                vars = AList.create();
-               beanStore = new BeanStore();
+               beanStore = BeanStore.create().build();
        }
 
        /**
diff --git 
a/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/client/ThirdPartyProxyTest.java
 
b/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/client/ThirdPartyProxyTest.java
index 0fd1d8a..66d7228 100644
--- 
a/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/client/ThirdPartyProxyTest.java
+++ 
b/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/client/ThirdPartyProxyTest.java
@@ -24,6 +24,7 @@ import static org.apache.juneau.http.HttpParts.*;
 import java.util.*;
 import java.util.concurrent.atomic.*;
 
+import org.apache.juneau.BeanContextableBuilder;
 import org.apache.juneau.collections.*;
 import org.apache.juneau.html.*;
 import org.apache.juneau.http.annotation.*;
@@ -2536,6 +2537,30 @@ public class ThirdPartyProxyTest extends RestTestcase {
        }
 
        public static class DummyPartSerializer extends BaseHttpPartSerializer {
+               public DummyPartSerializer(Builder builder) {
+                       super(builder);
+               }
+
+               public static Builder create() {
+                       return new Builder();
+               }
+
+               public static class Builder extends 
BaseHttpPartSerializer.Builder {
+
+                       Builder() {
+                               super();
+                       }
+
+                       Builder(Builder builder) {
+                               super(builder);
+                       }
+
+                       @Override
+                       public Builder copy() {
+                               return new Builder(this);
+                       }
+               }
+
                @Override
                public HttpPartSerializerSession 
createPartSession(SerializerSessionArgs args) {
                        return new BaseHttpPartSerializerSession() {
@@ -2545,5 +2570,9 @@ public class ThirdPartyProxyTest extends RestTestcase {
                                }
                        };
                }
+               @Override
+               public BeanContextableBuilder copy() {
+                       return null;
+               }
        }
 }
diff --git 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
index 45ccb77..63d9209 100644
--- 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
+++ 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
@@ -1823,7 +1823,7 @@ public class RestClient extends BeanContextable 
implements HttpClient, Closeable
                this.skipEmptyQueryData = 
cp.getBoolean(RESTCLIENT_skipEmptyQueryData).orElse(false);
                this.skipEmptyFormData = 
cp.getBoolean(RESTCLIENT_skipEmptyFormData).orElse(false);
 
-               BeanStore bs = this.beanStore = new BeanStore()
+               BeanStore bs = this.beanStore = BeanStore.create().build()
                        .addBean(ContextProperties.class, cp)
                        .addBean(RestClient.class, this);
 
diff --git 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteOperationArg.java
 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteOperationArg.java
index 1a2ec1d..0f647fa 100644
--- 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteOperationArg.java
+++ 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteOperationArg.java
@@ -18,11 +18,10 @@ import java.util.*;
 
 import static org.apache.juneau.httppart.HttpPartType.*;
 
-import org.apache.juneau.*;
+import org.apache.juneau.cp.*;
 import org.apache.juneau.http.annotation.*;
 import org.apache.juneau.httppart.*;
 import org.apache.juneau.reflect.*;
-import org.apache.juneau.serializer.*;
 
 /**
  * Represents the metadata about an annotated argument of a method on a REST 
proxy class.
@@ -41,28 +40,10 @@ public final class RemoteOperationArg {
        RemoteOperationArg(int index, HttpPartType partType, HttpPartSchema 
schema) {
                this.index = index;
                this.partType = partType;
-               this.serializer = ofNullable(createSerializer(partType, 
schema));
+               this.serializer = 
ofNullable(BeanStore.INSTANCE.createBean(schema.getSerializer()));
                this.schema = schema;
        }
 
-       @SuppressWarnings("unchecked")
-       private static HttpPartSerializer createSerializer(HttpPartType 
partType, HttpPartSchema schema) {
-               Class<? extends HttpPartSerializer> c = schema.getSerializer();
-               if (c == null)
-                       return null;
-               ConstructorInfo cc = ClassInfo.of(c).getPublicConstructor();
-               if (cc != null) {
-                       try {
-                               return cc.invoke();
-                       } catch (ExecutableException e) {
-                               throw new RuntimeException(e);
-                       }
-               }
-               if (Serializer.class.isAssignableFrom(c))
-                       return 
(HttpPartSerializer)Serializer.createSerializerBuilder((Class<? extends 
Serializer>)c).build();
-               return null;
-       }
-
        /**
         * Returns the name of the HTTP part.
         *
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
index 057474c..e223c19 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
@@ -1105,13 +1105,13 @@ public class RestContext extends BeanContext {
         * @return The bean store builder for this REST resource.
         * @throws Exception If bean store could not be instantiated.
         */
-       protected BeanStoreBuilder createBeanStoreBuilder(Object resource, 
ContextProperties properties, RestContext parent) throws Exception {
+       protected BeanStore.Builder createBeanStoreBuilder(Object resource, 
ContextProperties properties, RestContext parent) throws Exception {
 
                Class<? extends BeanStore> c = 
properties.getIfClass(REST_beanStore, BeanStore.class).orElse(null);
 
                BeanStore root = parent == null ? null : parent.rootBeanStore;
 
-               BeanStoreBuilder x = BeanStore
+               BeanStore.Builder x = BeanStore
                        .create()
                        .parent(root)
                        .implClass(c)
@@ -1122,8 +1122,8 @@ public class RestContext extends BeanContext {
                        .parent(root)
                        .outer(resource)
                        .build()
-                       .addBean(BeanStoreBuilder.class, x)
-                       .beanCreateMethodFinder(BeanStoreBuilder.class, 
resource)
+                       .addBean(BeanStore.Builder.class, x)
+                       .beanCreateMethodFinder(BeanStore.Builder.class, 
resource)
                        .find("createBeanStoreBuilder")
                        .withDefault(x)
                        .run();
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/http/remote/ListSerializer.java 
b/juneau-utest/src/test/java/org/apache/juneau/http/remote/ListSerializer.java
deleted file mode 100644
index 27df8b1..0000000
--- 
a/juneau-utest/src/test/java/org/apache/juneau/http/remote/ListSerializer.java
+++ /dev/null
@@ -1,39 +0,0 @@
-// 
***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright 
ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not 
use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                
                                              *
-// *                                                                           
                                              *
-// *  http://www.apache.org/licenses/LICENSE-2.0                               
                                              *
-// *                                                                           
                                              *
-// * Unless required by applicable law or agreed to in writing, software 
distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the 
License.                                              *
-// 
***************************************************************************************************************************
-package org.apache.juneau.http.remote;
-
-import static org.apache.juneau.internal.ArrayUtils.*;
-import static org.apache.juneau.internal.StringUtils.*;
-
-import java.util.*;
-
-import org.apache.juneau.httppart.*;
-import org.apache.juneau.serializer.*;
-
-public class ListSerializer extends BaseHttpPartSerializer {
-       @Override
-       public HttpPartSerializerSession 
createPartSession(SerializerSessionArgs args) {
-               return new BaseHttpPartSerializerSession() {
-                       @Override
-                       public String serialize(HttpPartType partType, 
HttpPartSchema schema, Object value) throws SerializeException, 
SchemaValidationException {
-                               if (value instanceof List)
-                                       return join((List<?>)value, '|');
-                               if (value instanceof Collection)
-                                       return join((Collection<?>)value, '|');
-                               if (isArray(value))
-                                       return join(toList(value, 
Object.class), "|");
-                               return "?" + value + "?";
-                       }
-               };
-       }
-}
\ No newline at end of file
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_FormDataAnnotation_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_FormDataAnnotation_Test.java
index b20ce7f..8b789e5 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_FormDataAnnotation_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_FormDataAnnotation_Test.java
@@ -698,7 +698,7 @@ public class Remote_FormDataAnnotation_Test {
 
        @Remote
        public static interface J1 {
-               @RemoteOp(path="/") String 
postX1(@FormData(n="x",serializer=XPartSerializer.class) String b);
+               @RemoteOp(path="/") String 
postX1(@FormData(n="x",serializer=MockWriterSerializer.X.class) String b);
        }
 
        @Test
@@ -726,7 +726,7 @@ public class Remote_FormDataAnnotation_Test {
        @Remote(path="/")
        public static interface K1 {
                @RemoteOp(path="/") String postX1(@Request K1a rb);
-               @RemoteOp(path="/") String 
postX2(@Request(serializer=XSerializer.class) K1a rb);
+               @RemoteOp(path="/") String 
postX2(@Request(serializer=MockWriterSerializer.X.class) K1a rb);
        }
 
        public static class K1a {
@@ -788,7 +788,7 @@ public class Remote_FormDataAnnotation_Test {
        @Remote(path="/")
        public static interface K2 {
                @RemoteOp(path="/") String postX1(@Request K2a rb);
-               @RemoteOp(path="/") String 
postX2(@Request(serializer=XSerializer.class) K2a rb);
+               @RemoteOp(path="/") String 
postX2(@Request(serializer=MockWriterSerializer.X.class) K2a rb);
        }
 
        public static class K2a {
@@ -826,7 +826,7 @@ public class Remote_FormDataAnnotation_Test {
        @Remote(path="/")
        public static interface K3 {
                @RemoteOp(path="/") String postX1(@Request K3a rb);
-               @RemoteOp(path="/") String 
postX2(@Request(serializer=XSerializer.class) K3a rb);
+               @RemoteOp(path="/") String 
postX2(@Request(serializer=MockWriterSerializer.X.class) K3a rb);
        }
 
        public static class K3a {
@@ -912,7 +912,7 @@ public class Remote_FormDataAnnotation_Test {
        @Remote(path="/")
        public static interface K6 {
                @RemoteOp(path="/") String postX1(@Request K6a rb);
-               @RemoteOp(path="/") String 
postX2(@Request(serializer=XSerializer.class) K6a rb);
+               @RemoteOp(path="/") String 
postX2(@Request(serializer=MockWriterSerializer.X.class) K6a rb);
        }
 
        public static class K6a {
@@ -924,7 +924,7 @@ public class Remote_FormDataAnnotation_Test {
                public List<Object> getX1() {
                        return 
AList.of("foo","","true","123","null",true,123,null);
                }
-               @FormData(n="c",serializer=ListSerializer.class)
+               @FormData(n="c",serializer=MockWriterSerializer.X.class)
                public List<Object> getX2() {
                        return 
AList.of("foo","","true","123","null",true,123,null);
                }
@@ -940,7 +940,7 @@ public class Remote_FormDataAnnotation_Test {
                public Object[] getX5() {
                        return new 
Object[]{"foo","","true","123","null",true,123,null};
                }
-               @FormData(n="g",serializer=ListSerializer.class)
+               @FormData(n="g",serializer=MockWriterSerializer.X.class)
                public Object[] getX6() {
                        return new 
Object[]{"foo","","true","123","null",true,123,null};
                }
@@ -958,9 +958,9 @@ public class Remote_FormDataAnnotation_Test {
        public void k06_requestBean_collections() throws Exception {
                K6 x1 = remote(K.class,K6.class);
                K6 x2 = 
client(K.class).partSerializer(UonSerializer.class).build().getRemote(K6.class);
-               
assertEquals("{a:'foo,,true,123,null,true,123,null',b:'foo,,true,123,null,true,123,null',c:'foo||true|123|null|true|123|null',d:'',f:'foo,,true,123,null,true,123,null',g:'foo||true|123|null|true|123|null',h:''}",x1.postX1(new
 K6a()));
-               
assertEquals("{a:'@(foo,\\'\\',\\'true\\',\\'123\\',\\'null\\',true,123,null)',b:'@(foo,\\'\\',\\'true\\',\\'123\\',\\'null\\',true,123,null)',c:'foo||true|123|null|true|123|null',d:'@()',f:'@(foo,\\'\\',\\'true\\',\\'123\\',\\'null\\',true,123,null)',g:'foo||true|123|null|true|123|null',h:'@()'}",x2.postX1(new
 K6a()));
-               
assertEquals("{a:'fooXXtrueX123XnullXtrueX123Xnull',b:'fooXXtrueX123XnullXtrueX123Xnull',c:'foo||true|123|null|true|123|null',d:'',f:'fooXXtrueX123XnullXtrueX123Xnull',g:'foo||true|123|null|true|123|null',h:''}",x2.postX2(new
 K6a()));
+               assertString(x1.postX1(new 
K6a())).is("{a:'foo,,true,123,null,true,123,null',b:'foo,,true,123,null,true,123,null',c:'xfoo||true|123|null|true|123|nullx',d:'',f:'foo,,true,123,null,true,123,null',g:'xfoo||true|123|null|true|123|nullx',h:''}");
+               assertString(x2.postX1(new 
K6a())).is("{a:'@(foo,\\'\\',\\'true\\',\\'123\\',\\'null\\',true,123,null)',b:'@(foo,\\'\\',\\'true\\',\\'123\\',\\'null\\',true,123,null)',c:'xfoo||true|123|null|true|123|nullx',d:'@()',f:'@(foo,\\'\\',\\'true\\',\\'123\\',\\'null\\',true,123,null)',g:'xfoo||true|123|null|true|123|nullx',h:'@()'}");
+               assertString(x2.postX2(new 
K6a())).is("{a:'xfoo||true|123|null|true|123|nullx',b:'xfoo||true|123|null|true|123|nullx',c:'xfoo||true|123|null|true|123|nullx',d:'xx',f:'xfoo||true|123|null|true|123|nullx',g:'xfoo||true|123|null|true|123|nullx',h:'xx'}");
        }
 
        
//------------------------------------------------------------------------------------------------------------------
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_HeaderAnnotation_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_HeaderAnnotation_Test.java
index 58828e9..d065e91 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_HeaderAnnotation_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_HeaderAnnotation_Test.java
@@ -662,7 +662,7 @@ public class Remote_HeaderAnnotation_Test {
 
        @Remote
        public static interface J1 {
-               @RemoteOp(path="/") String 
getX1(@Header(n="x",serializer=XPartSerializer.class) String b);
+               @RemoteOp(path="/") String 
getX1(@Header(n="x",serializer=MockWriterSerializer.X.class) String b);
        }
 
        @Test
@@ -690,7 +690,7 @@ public class Remote_HeaderAnnotation_Test {
        @Remote(path="/")
        public static interface K1 {
                @RemoteOp(path="/") String getX1(@Request K1a rb);
-               @RemoteOp(path="/") String 
getX2(@Request(serializer=XSerializer.class) K1a rb);
+               @RemoteOp(path="/") String 
getX2(@Request(serializer=MockWriterSerializer.X.class) K1a rb);
        }
 
        public static class K1a {
@@ -752,7 +752,7 @@ public class Remote_HeaderAnnotation_Test {
        @Remote(path="/")
        public static interface K2 {
                @RemoteOp(path="/") String getX1(@Request K2a rb);
-               @RemoteOp(path="/") String 
getX2(@Request(serializer=XSerializer.class) K2a rb);
+               @RemoteOp(path="/") String 
getX2(@Request(serializer=MockWriterSerializer.X.class) K2a rb);
        }
 
        public static class K2a {
@@ -790,7 +790,7 @@ public class Remote_HeaderAnnotation_Test {
        @Remote(path="/")
        public static interface K3 {
                @RemoteOp(path="/") String getX1(@Request K3a rb);
-               @RemoteOp(path="/") String 
getX2(@Request(serializer=XSerializer.class) K3a rb);
+               @RemoteOp(path="/") String 
getX2(@Request(serializer=MockWriterSerializer.X.class) K3a rb);
        }
 
        public static class K3a {
@@ -836,7 +836,7 @@ public class Remote_HeaderAnnotation_Test {
        @Remote(path="/")
        public static interface K4 {
                @RemoteOp(path="/") String getX1(@Request K4a rb);
-               @RemoteOp(path="/") String 
getX2(@Request(serializer=XSerializer.class) K4a rb);
+               @RemoteOp(path="/") String 
getX2(@Request(serializer=MockWriterSerializer.X.class) K4a rb);
        }
 
        public static class K4a {
@@ -848,7 +848,7 @@ public class Remote_HeaderAnnotation_Test {
                public List<Object> getX1() {
                        return 
AList.of("foo","","true","123","null",true,123,null);
                }
-               @Header(name="c",serializer=ListSerializer.class)
+               @Header(name="c",serializer=MockWriterSerializer.X.class)
                public List<Object> getX2() {
                        return 
AList.of("foo","","true","123","null",true,123,null);
                }
@@ -864,7 +864,7 @@ public class Remote_HeaderAnnotation_Test {
                public Object[] getX5() {
                        return new 
Object[]{"foo","","true","123","null",true,123,null};
                }
-               @Header(name="g",serializer=ListSerializer.class)
+               @Header(name="g",serializer=MockWriterSerializer.X.class)
                public Object[] getX6() {
                        return new 
Object[]{"foo","","true","123","null",true,123,null};
                }
@@ -882,9 +882,9 @@ public class Remote_HeaderAnnotation_Test {
        public void k04_requestBean_collections() throws Exception {
                K4 x1 = remote(K.class,K4.class);
                K4 x2 = 
client(K.class).partSerializer(UonSerializer.class).build().getRemote(K4.class);
-               
assertEquals("{a:'foo,,true,123,null,true,123,null',b:'foo,,true,123,null,true,123,null',c:'foo||true|123|null|true|123|null',d:'',f:'foo,,true,123,null,true,123,null',g:'foo||true|123|null|true|123|null',h:''}",x1.getX1(new
 K4a()));
-               
assertEquals("{a:'@(foo,\\'\\',\\'true\\',\\'123\\',\\'null\\',true,123,null)',b:'@(foo,\\'\\',\\'true\\',\\'123\\',\\'null\\',true,123,null)',c:'foo||true|123|null|true|123|null',d:'@()',f:'@(foo,\\'\\',\\'true\\',\\'123\\',\\'null\\',true,123,null)',g:'foo||true|123|null|true|123|null',h:'@()'}",x2.getX1(new
 K4a()));
-               
assertEquals("{a:'fooXXtrueX123XnullXtrueX123Xnull',b:'fooXXtrueX123XnullXtrueX123Xnull',c:'foo||true|123|null|true|123|null',d:'',f:'fooXXtrueX123XnullXtrueX123Xnull',g:'foo||true|123|null|true|123|null',h:''}",x2.getX2(new
 K4a()));
+               assertString(x1.getX1(new 
K4a())).is("{a:'foo,,true,123,null,true,123,null',b:'foo,,true,123,null,true,123,null',c:'xfoo||true|123|null|true|123|nullx',d:'',f:'foo,,true,123,null,true,123,null',g:'xfoo||true|123|null|true|123|nullx',h:''}");
+               assertString(x2.getX1(new 
K4a())).is("{a:'@(foo,\\'\\',\\'true\\',\\'123\\',\\'null\\',true,123,null)',b:'@(foo,\\'\\',\\'true\\',\\'123\\',\\'null\\',true,123,null)',c:'xfoo||true|123|null|true|123|nullx',d:'@()',f:'@(foo,\\'\\',\\'true\\',\\'123\\',\\'null\\',true,123,null)',g:'xfoo||true|123|null|true|123|nullx',h:'@()'}");
+               assertString(x2.getX2(new 
K4a())).is("{a:'xfoo||true|123|null|true|123|nullx',b:'xfoo||true|123|null|true|123|nullx',c:'xfoo||true|123|null|true|123|nullx',d:'xx',f:'xfoo||true|123|null|true|123|nullx',g:'xfoo||true|123|null|true|123|nullx',h:'xx'}");
        }
 
        
//------------------------------------------------------------------------------------------------------------------
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_PathAnnotation_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_PathAnnotation_Test.java
index 4397dc5..f246e6d 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_PathAnnotation_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_PathAnnotation_Test.java
@@ -570,7 +570,7 @@ public class Remote_PathAnnotation_Test {
 
        @Remote
        public static interface H1 {
-               @RemoteOp(path="/{x}") String 
getX1(@Path(n="x",serializer=XPartSerializer.class) String b);
+               @RemoteOp(path="/{x}") String 
getX1(@Path(n="x",serializer=MockWriterSerializer.X.class) String b);
        }
 
        @Test
@@ -598,7 +598,7 @@ public class Remote_PathAnnotation_Test {
        @Remote(path="/")
        public static interface K1 {
                @RemoteOp(path="/{a}/{b}/{c}/{e}/{g}/{h}") String 
getX1(@Request K1a rb);
-               @RemoteOp(path="/{a}/{b}/{c}/{e}/{g}/{h}") String 
getX2(@Request(serializer=XSerializer.class) K1a rb);
+               @RemoteOp(path="/{a}/{b}/{c}/{e}/{g}/{h}") String 
getX2(@Request(serializer=MockWriterSerializer.X.class) K1a rb);
        }
 
        public static class K1a {
@@ -644,7 +644,7 @@ public class Remote_PathAnnotation_Test {
        @Remote(path="/")
        public static interface K2 {
                
@RemoteOp(path="/{a1}/{a2}/{a3}/{a4}/{b1}/{b2}/{b3}/{c1}/{c2}/{c3}/{c4}") 
String getX1(@Request K2a rb);
-               
@RemoteOp(path="/{a1}/{a2}/{a3}/{a4}/{b1}/{b2}/{b3}/{c1}/{c2}/{c3}/{c4}") 
String getX2(@Request(serializer=XSerializer.class) K2a rb);
+               
@RemoteOp(path="/{a1}/{a2}/{a3}/{a4}/{b1}/{b2}/{b3}/{c1}/{c2}/{c3}/{c4}") 
String getX2(@Request(serializer=MockWriterSerializer.X.class) K2a rb);
        }
 
        public static class K2a {
@@ -682,7 +682,7 @@ public class Remote_PathAnnotation_Test {
        @Remote(path="/")
        public static interface K3 {
                
@RemoteOp(path="/{a1}/{a2}/{a3}/{a4}/{b1}/{b2}/{b3}/{c1}/{c2}/{c3}/{c4}/{e1}/{e2}/{e3}/{e4}")
 String getX1(@Request K3a rb);
-               
@RemoteOp(path="/{a1}/{a2}/{a3}/{a4}/{b1}/{b2}/{b3}/{c1}/{c2}/{c3}/{c4}/{e1}/{e2}/{e3}/{e4}")
 String getX2(@Request(serializer=XSerializer.class) K3a rb);
+               
@RemoteOp(path="/{a1}/{a2}/{a3}/{a4}/{b1}/{b2}/{b3}/{c1}/{c2}/{c3}/{c4}/{e1}/{e2}/{e3}/{e4}")
 String getX2(@Request(serializer=MockWriterSerializer.X.class) K3a rb);
        }
 
        public static class K3a {
@@ -724,7 +724,7 @@ public class Remote_PathAnnotation_Test {
        @Remote(path="/")
        public static interface K4 {
                @RemoteOp(path="/{a}/{b}/{c}/{d}/{f}/{g}/{h}") String 
getX1(@Request K4a rb);
-               @RemoteOp(path="/{a}/{b}/{c}/{d}/{f}/{g}/{h}") String 
getX2(@Request(serializer=XSerializer.class) K4a rb);
+               @RemoteOp(path="/{a}/{b}/{c}/{d}/{f}/{g}/{h}") String 
getX2(@Request(serializer=MockWriterSerializer.X.class) K4a rb);
        }
 
        public static class K4a {
@@ -736,7 +736,7 @@ public class Remote_PathAnnotation_Test {
                public List<Object> getX1() {
                        return 
AList.of("foo","","true","123","null",true,123,null);
                }
-               @Path(n="c",serializer=ListSerializer.class)
+               @Path(n="c",serializer=MockWriterSerializer.X.class)
                public List<Object> getX2() {
                        return 
AList.of("foo","","true","123","null",true,123,null);
                }
@@ -748,7 +748,7 @@ public class Remote_PathAnnotation_Test {
                public Object[] getX5() {
                        return new 
Object[]{"foo","","true","123","null",true,123,null};
                }
-               @Path(n="g",serializer=ListSerializer.class)
+               @Path(n="g",serializer=MockWriterSerializer.X.class)
                public Object[] getX6() {
                        return new 
Object[]{"foo","","true","123","null",true,123,null};
                }
@@ -762,9 +762,9 @@ public class Remote_PathAnnotation_Test {
        public void k04_requestBean_collections() throws Exception {
                K4 x1 = remote(K.class,K4.class);
                K4 x2 = 
client(K.class).partSerializer(UonSerializer.class).build().getRemote(K4.class);
-               
assertEquals("foo,,true,123,null,true,123,null/foo,,true,123,null,true,123,null/foo||true|123|null|true|123|null//foo,,true,123,null,true,123,null/foo||true|123|null|true|123|null/",x1.getX1(new
 K4a()));
-               
assertEquals("@(foo,'','true','123','null',true,123,null)/@(foo,'','true','123','null',true,123,null)/foo||true|123|null|true|123|null/@()/@(foo,'','true','123','null',true,123,null)/foo||true|123|null|true|123|null/@()",x2.getX1(new
 K4a()));
-               
assertEquals("fooXXtrueX123XnullXtrueX123Xnull/fooXXtrueX123XnullXtrueX123Xnull/foo||true|123|null|true|123|null//fooXXtrueX123XnullXtrueX123Xnull/foo||true|123|null|true|123|null/",x2.getX2(new
 K4a()));
+               assertString(x1.getX1(new 
K4a())).is("foo,,true,123,null,true,123,null/foo,,true,123,null,true,123,null/xfoo||true|123|null|true|123|nullx//foo,,true,123,null,true,123,null/xfoo||true|123|null|true|123|nullx/");
+               assertString(x2.getX1(new 
K4a())).is("@(foo,'','true','123','null',true,123,null)/@(foo,'','true','123','null',true,123,null)/xfoo||true|123|null|true|123|nullx/@()/@(foo,'','true','123','null',true,123,null)/xfoo||true|123|null|true|123|nullx/@()");
+               assertString(x2.getX2(new 
K4a())).is("xfoo||true|123|null|true|123|nullx/xfoo||true|123|null|true|123|nullx/xfoo||true|123|null|true|123|nullx/xx/xfoo||true|123|null|true|123|nullx/xfoo||true|123|null|true|123|nullx/xx");
        }
 
        
//------------------------------------------------------------------------------------------------------------------
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_QueryAnnotation_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_QueryAnnotation_Test.java
index e00096c..367c7ca 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_QueryAnnotation_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_QueryAnnotation_Test.java
@@ -680,7 +680,7 @@ public class Remote_QueryAnnotation_Test {
 
        @Remote
        public static interface J1 {
-               @RemoteOp(path="/") String 
getX1(@Query(n="x",serializer=XPartSerializer.class) String b);
+               @RemoteOp(path="/") String 
getX1(@Query(n="x",serializer=MockWriterSerializer.X.class) String b);
        }
 
        @Test
@@ -708,7 +708,7 @@ public class Remote_QueryAnnotation_Test {
        @Remote(path="/")
        public static interface K1 {
                @RemoteOp(path="/") String getX1(@Request K1b rb);
-               @RemoteOp(path="/") String 
getX2(@Request(serializer=XSerializer.class) K1b rb);
+               @RemoteOp(path="/") String 
getX2(@Request(serializer=MockWriterSerializer.X.class) K1b rb);
        }
 
        public static interface K1a {
@@ -753,7 +753,7 @@ public class Remote_QueryAnnotation_Test {
        @Remote(path="/")
        public static interface K2 {
                @RemoteOp(path="/") String getX1(@Request K2a rb);
-               @RemoteOp(path="/") String 
getX2(@Request(serializer=XSerializer.class) K2a rb);
+               @RemoteOp(path="/") String 
getX2(@Request(serializer=MockWriterSerializer.X.class) K2a rb);
        }
 
        public static class K2a {
@@ -791,7 +791,7 @@ public class Remote_QueryAnnotation_Test {
        @Remote(path="/")
        public static interface K3 {
                @RemoteOp(path="/") String getX1(@Request K3a rb);
-               @RemoteOp(path="/") String 
getX2(@Request(serializer=XSerializer.class) K3a rb);
+               @RemoteOp(path="/") String 
getX2(@Request(serializer=MockWriterSerializer.X.class) K3a rb);
        }
 
        public static class K3a {
@@ -876,7 +876,7 @@ public class Remote_QueryAnnotation_Test {
        @Remote(path="/")
        public static interface K6 {
                @RemoteOp(path="/") String getX1(@Request K6a rb);
-               @RemoteOp(path="/") String 
getX2(@Request(serializer=XSerializer.class) K6a rb);
+               @RemoteOp(path="/") String 
getX2(@Request(serializer=MockWriterSerializer.X.class) K6a rb);
        }
 
        public static class K6a {
@@ -888,7 +888,7 @@ public class Remote_QueryAnnotation_Test {
                public List<Object> getX1() {
                        return 
AList.of("foo","","true","123","null",true,123,null);
                }
-               @Query(n="c",serializer=ListSerializer.class)
+               @Query(n="c",serializer=MockWriterSerializer.X.class)
                public List<Object> getX2() {
                        return 
AList.of("foo","","true","123","null",true,123,null);
                }
@@ -904,7 +904,7 @@ public class Remote_QueryAnnotation_Test {
                public Object[] getX5() {
                        return new 
Object[]{"foo","","true","123","null",true,123,null};
                }
-               @Query(n="g",serializer=ListSerializer.class)
+               @Query(n="g",serializer=MockWriterSerializer.X.class)
                public Object[] getX6() {
                        return new 
Object[]{"foo","","true","123","null",true,123,null};
                }
@@ -922,9 +922,9 @@ public class Remote_QueryAnnotation_Test {
        public void k06_requestBean_collections() throws Exception {
                K6 x1 = remote(K.class,K6.class);
                K6 x2 = 
client(K.class).partSerializer(UonSerializer.class).build().getRemote(K6.class);
-               
assertEquals("{a:'foo,,true,123,null,true,123,null',b:'foo,,true,123,null,true,123,null',c:'foo||true|123|null|true|123|null',d:'',f:'foo,,true,123,null,true,123,null',g:'foo||true|123|null|true|123|null',h:''}",x1.getX1(new
 K6a()));
-               
assertEquals("{a:'@(foo,\\'\\',\\'true\\',\\'123\\',\\'null\\',true,123,null)',b:'@(foo,\\'\\',\\'true\\',\\'123\\',\\'null\\',true,123,null)',c:'foo||true|123|null|true|123|null',d:'@()',f:'@(foo,\\'\\',\\'true\\',\\'123\\',\\'null\\',true,123,null)',g:'foo||true|123|null|true|123|null',h:'@()'}",x2.getX1(new
 K6a()));
-               
assertEquals("{a:'fooXXtrueX123XnullXtrueX123Xnull',b:'fooXXtrueX123XnullXtrueX123Xnull',c:'foo||true|123|null|true|123|null',d:'',f:'fooXXtrueX123XnullXtrueX123Xnull',g:'foo||true|123|null|true|123|null',h:''}",x2.getX2(new
 K6a()));
+               assertString(x1.getX1(new 
K6a())).is("{a:'foo,,true,123,null,true,123,null',b:'foo,,true,123,null,true,123,null',c:'xfoo||true|123|null|true|123|nullx',d:'',f:'foo,,true,123,null,true,123,null',g:'xfoo||true|123|null|true|123|nullx',h:''}");
+               assertString(x2.getX1(new 
K6a())).is("{a:'@(foo,\\'\\',\\'true\\',\\'123\\',\\'null\\',true,123,null)',b:'@(foo,\\'\\',\\'true\\',\\'123\\',\\'null\\',true,123,null)',c:'xfoo||true|123|null|true|123|nullx',d:'@()',f:'@(foo,\\'\\',\\'true\\',\\'123\\',\\'null\\',true,123,null)',g:'xfoo||true|123|null|true|123|nullx',h:'@()'}");
+               assertString(x2.getX2(new 
K6a())).is("{a:'xfoo||true|123|null|true|123|nullx',b:'xfoo||true|123|null|true|123|nullx',c:'xfoo||true|123|null|true|123|nullx',d:'xx',f:'xfoo||true|123|null|true|123|nullx',g:'xfoo||true|123|null|true|123|nullx',h:'xx'}");
        }
 
        
//------------------------------------------------------------------------------------------------------------------
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_RequestAnnotation_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_RequestAnnotation_Test.java
index 10951ca..9ddf3ab 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_RequestAnnotation_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_RequestAnnotation_Test.java
@@ -258,7 +258,7 @@ public class Remote_RequestAnnotation_Test {
                }
        }
 
-       @Request(serializer=XPartSerializer.class)
+       @Request(serializer=MockWriterSerializer.X.class)
        public static class E1 {
                @Body
                public String getBody() {
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/http/remote/XSerializer.java 
b/juneau-utest/src/test/java/org/apache/juneau/http/remote/XSerializer.java
deleted file mode 100644
index 6601a68..0000000
--- a/juneau-utest/src/test/java/org/apache/juneau/http/remote/XSerializer.java
+++ /dev/null
@@ -1,39 +0,0 @@
-// 
***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright 
ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not 
use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                
                                              *
-// *                                                                           
                                              *
-// *  http://www.apache.org/licenses/LICENSE-2.0                               
                                              *
-// *                                                                           
                                              *
-// * Unless required by applicable law or agreed to in writing, software 
distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the 
License.                                              *
-// 
***************************************************************************************************************************
-package org.apache.juneau.http.remote;
-
-import static org.apache.juneau.internal.ArrayUtils.*;
-import static org.apache.juneau.internal.StringUtils.*;
-
-import java.util.*;
-
-import org.apache.juneau.httppart.*;
-import org.apache.juneau.serializer.*;
-
-public class XSerializer extends BaseHttpPartSerializer {
-       @Override
-       public HttpPartSerializerSession 
createPartSession(SerializerSessionArgs args) {
-               return new BaseHttpPartSerializerSession() {
-                       @Override
-                       public String serialize(HttpPartType partType, 
HttpPartSchema schema, Object value) throws SerializeException, 
SchemaValidationException {
-                               if (value instanceof List)
-                                       return join((List<?>)value, "X");
-                               if (value instanceof Collection)
-                                       return join((Collection<?>)value, "X");
-                               if (isArray(value))
-                                       return join(toList(value, 
Object.class), "X");
-                               return "x" + value + "x";
-                       }
-               };
-       }
-}
\ No newline at end of file
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Config_RestClient_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Config_RestClient_Test.java
index 68da3b9..d8d4502 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Config_RestClient_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Config_RestClient_Test.java
@@ -14,6 +14,7 @@ package org.apache.juneau.rest.client;
 
 import static org.apache.juneau.assertions.Assertions.*;
 import static org.apache.juneau.http.HttpResponses.*;
+import static org.apache.juneau.internal.ExceptionUtils.*;
 import static org.apache.juneau.http.HttpHeaders.*;
 import static org.junit.Assert.*;
 import static org.junit.runners.MethodSorters.*;
@@ -37,12 +38,10 @@ import org.apache.juneau.http.response.*;
 import org.apache.juneau.httppart.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.marshall.*;
-import org.apache.juneau.parser.*;
-import org.apache.juneau.parser.ParseException;
 import org.apache.juneau.rest.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.mock.*;
-import org.apache.juneau.serializer.*;
+import org.apache.juneau.testutils.*;
 import org.apache.juneau.xml.*;
 import org.junit.*;
 
@@ -452,29 +451,25 @@ public class RestClient_Config_RestClient_Test {
                }
        }
 
-       public static class A12a extends SimplePartSerializer {
-               @Override
-               public SimplePartSerializerSession 
createPartSession(SerializerSessionArgs args) {
-                       return new SimplePartSerializerSession() {
-                               @Override
-                               public String serialize(HttpPartType type, 
HttpPartSchema schema, Object value) {
-                                       return "x" + 
SimpleJson.DEFAULT.toString(value);
-                               }
-                       };
+       public static class A12a extends MockWriterSerializer {
+               public A12a(Builder builder) {
+                       super(builder.partFunction((t,s,o)->"x" + 
SimpleJson.DEFAULT.toString(o)));
                }
        }
 
-       public static class A12b extends SimplePartParser {
-               @Override
-               public SimplePartParserSession 
createPartSession(ParserSessionArgs args) {
-                       return new SimplePartParserSession() {
-                               @Override
-                               public <T> T parse(HttpPartType partType, 
HttpPartSchema schema, String in, ClassMeta<T> toType) throws ParseException, 
SchemaValidationException {
-                                       if (toType.isInstanceOf(ABean.class))
-                                               return 
SimpleJson.DEFAULT.read(in.substring(1),toType);
-                                       return 
super.parse(null,schema,in,toType);
-                               }
-                       };
+       public static class A12b extends MockReaderParser {
+               public A12b(Builder builder) {
+                       super(builder.partFunction((t,s,in,c)->in(t,s,in,c)));
+               }
+
+               private static Object in(HttpPartType type, HttpPartSchema 
schema, String in, ClassMeta<?> c) {
+                       try {
+                               if (c.isInstanceOf(ABean.class))
+                                       return 
SimpleJson.DEFAULT.read(in.substring(1),c);
+                               return 
SimplePartParser.DEFAULT.parse(type,schema,in,c);
+                       } catch (Exception e) {
+                               throw runtimeException(e);
+                       }
                }
        }
 
@@ -486,7 +481,7 @@ public class RestClient_Config_RestClient_Test {
                b = 
x.get().header("Foo",bean).run().assertHeader("Foo").is("x{f:1}").getHeader("Foo").asType(ABean.class).get();
                assertEquals("{f:1}",b.toString());
 
-               x = client(A12.class).header(serializedHeader("Foo", 
bean)).partSerializer(new A12a()).partParser(new A12b()).build();
+               x = client(A12.class).header(serializedHeader("Foo", 
bean)).partSerializer(new A12a(MockWriterSerializer.create())).partParser(new 
A12b(MockReaderParser.create())).build();
                b = 
x.get("/").header("Foo",bean).run().assertHeader("Foo").is("x{f:1}").getHeader("Foo").asType(ABean.class).get();
                assertEquals("{f:1}",b.toString());
        }
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_FormData_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_FormData_Test.java
index a7b7869..1f02bca 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_FormData_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_FormData_Test.java
@@ -26,7 +26,6 @@ import org.apache.http.*;
 import org.apache.juneau.collections.*;
 import org.apache.juneau.http.part.*;
 import org.apache.juneau.httppart.*;
-import org.apache.juneau.marshall.*;
 import org.apache.juneau.rest.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.mock.*;
@@ -144,25 +143,13 @@ public class RestClient_FormData_Test {
                
x2.post("/formData").formData("foo",s).run().assertBody().asString().urlDecode().is("foo=bar,baz");
        }
 
-       public static class A8 extends SimplePartSerializer {
-               @Override
-               public SimplePartSerializerSession 
createPartSession(SerializerSessionArgs args) {
-                       return new SimplePartSerializerSession() {
-                               @Override
-                               public String serialize(HttpPartType type, 
HttpPartSchema schema, Object value) {
-                                       return "x" + 
SimpleJson.DEFAULT.toString(value);
-                               }
-                       };
-               }
-       }
-
        @Test
        public void a10_formData_String_Supplier_Schema_Serializer() throws 
Exception {
                TestSupplier s = TestSupplier.of(OList.of("foo","bar"));
-               RestClient x = 
client().formData(part("foo",s,T_ARRAY_PIPES).serializer(new A8())).build();
-               
x.post("/formData").run().assertBody().asString().urlDecode().is("foo=x['foo','bar']");
+               RestClient x = 
client().formData(part("foo",s,T_ARRAY_PIPES).serializer(MockWriterSerializer.X)).build();
+               
x.post("/formData").run().assertBody().asString().urlDecode().is("foo=xfoo|barx");
                s.set(OList.of("bar","baz"));
-               
x.post("/formData").run().assertBody().asString().urlDecode().is("foo=x['bar','baz']");
+               
x.post("/formData").run().assertBody().asString().urlDecode().is("foo=xbar|bazx");
        }
 
        @Test
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Headers_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Headers_Test.java
index e9c4536..2336406 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Headers_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Headers_Test.java
@@ -153,21 +153,9 @@ public class RestClient_Headers_Test {
                
x.get("/headers").header("Foo",s).run().assertBody().is("['bar','bar']");
        }
 
-       public static class A8 extends SimplePartSerializer {
-               @Override
-               public SimplePartSerializerSession 
createPartSession(SerializerSessionArgs args) {
-                       return new SimplePartSerializerSession() {
-                               @Override
-                               public String serialize(HttpPartType type, 
HttpPartSchema schema, Object value) {
-                                       return "x" + 
SimpleJson.DEFAULT.toString(value);
-                               }
-                       };
-               }
-       }
-
        @Test
        public void a09_headers_String_Object_Schema_Serializer() throws 
Exception {
-               checkFooClient().header(header("Foo",bean,null).serializer(new 
A8())).build().get("/headers").run().assertBody().is("['x{f:1}']");
+               
checkFooClient().header(header("Foo",bean,null).serializer(MockWriterSerializer.X)).build().get("/headers").run().assertBody().is("['x{f:1}x']");
        }
 
        @Test
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Query_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Query_Test.java
index 6a27899..c0ddf48 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Query_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Query_Test.java
@@ -25,11 +25,9 @@ import java.util.*;
 import org.apache.juneau.collections.*;
 import org.apache.juneau.http.part.*;
 import org.apache.juneau.httppart.*;
-import org.apache.juneau.marshall.*;
 import org.apache.juneau.rest.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.mock.*;
-import org.apache.juneau.serializer.*;
 import org.apache.juneau.testutils.*;
 import org.apache.juneau.uon.*;
 import org.junit.*;
@@ -105,26 +103,14 @@ public class RestClient_Query_Test {
                
x.get("/query").queryData(part("bar",s,T_ARRAY_PIPES)).run().assertBody().asString().urlDecode().is("foo=bar|baz&bar=bar|baz");
        }
 
-       public static class A8 extends SimplePartSerializer {
-               @Override
-               public SimplePartSerializerSession 
createPartSession(SerializerSessionArgs args) {
-                       return new SimplePartSerializerSession() {
-                               @Override
-                               public String serialize(HttpPartType type, 
HttpPartSchema schema, Object value) {
-                                       return "x" + 
SimpleJson.DEFAULT.toString(value);
-                               }
-                       };
-               }
-       }
-
        @Test
        public void a08_query_String_Supplier_Schema_Serializer() throws 
Exception {
                List<String> l1 = AList.of("foo","bar"), l2 = 
AList.of("bar","baz");
                TestSupplier s = TestSupplier.of(l1);
-               RestClient x = 
client().queryData(part("foo",s,T_ARRAY_PIPES).serializer(new A8())).build();
-               
x.get("/query").run().assertBody().asString().urlDecode().is("foo=x['foo','bar']");
+               RestClient x = 
client().queryData(part("foo",s,T_ARRAY_PIPES).serializer(MockWriterSerializer.X)).build();
+               
x.get("/query").run().assertBody().asString().urlDecode().is("foo=xfoo|barx");
                s.set(l2);
-               
x.get("/query").run().assertBody().asString().urlDecode().is("foo=x['bar','baz']");
+               
x.get("/query").run().assertBody().asString().urlDecode().is("foo=xbar|bazx");
        }
 
        @Test
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/testutils/MockReaderParser.java 
b/juneau-utest/src/test/java/org/apache/juneau/testutils/MockReaderParser.java
index b1b87de..ce89aa6 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/testutils/MockReaderParser.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/testutils/MockReaderParser.java
@@ -14,20 +14,24 @@
 package org.apache.juneau.testutils;
 
 import java.io.*;
+import java.lang.reflect.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.httppart.*;
 import org.apache.juneau.parser.*;
 
 /**
  * Utility class for creating mocked reader parsers.
  */
-public class MockReaderParser extends ReaderParser {
+public class MockReaderParser extends ReaderParser implements HttpPartParser {
 
        private final MockReaderParserFunction function;
+       private final MockReaderParserPartFunction partFunction;
 
        protected MockReaderParser(Builder builder) {
                super(builder);
                this.function = builder.function;
+               this.partFunction = builder.partFunction;
        }
 
        public static Builder create() {
@@ -47,8 +51,31 @@ public class MockReaderParser extends ReaderParser {
                };
        }
 
+       @Override
+       public HttpPartParserSession createPartSession(ParserSessionArgs args) {
+               return new HttpPartParserSession() {
+
+                       @Override
+                       @SuppressWarnings("unchecked")
+                       public <T> T parse(HttpPartType partType, 
HttpPartSchema schema, String in, ClassMeta<T> toType) throws ParseException, 
SchemaValidationException {
+                               return (T)partFunction.apply(partType, schema, 
in, toType);
+                       }
+
+                       @Override
+                       public <T> T parse(HttpPartType partType, 
HttpPartSchema schema, String in, Class<T> toType) throws ParseException, 
SchemaValidationException {
+                               throw new NoSuchMethodError("Not implemented.");
+                       }
+
+                       @Override
+                       public <T> T parse(HttpPartType partType, 
HttpPartSchema schema, String in, Type toType, Type... toTypeArgs) throws 
ParseException, SchemaValidationException {
+                               throw new NoSuchMethodError("Not implemented.");
+                       }
+               };
+       }
+
        public static class Builder extends ReaderParserBuilder {
                MockReaderParserFunction function;
+               MockReaderParserPartFunction partFunction;
 
                public Builder() {
                        super();
@@ -58,8 +85,13 @@ public class MockReaderParser extends ReaderParser {
                        super(copyFrom);
                }
 
-               public Builder function(MockReaderParserFunction function) {
-                       this.function = function;
+               public Builder function(MockReaderParserFunction value) {
+                       function = value;
+                       return this;
+               }
+
+               public Builder partFunction(MockReaderParserPartFunction value) 
{
+                       partFunction = value;
                        return this;
                }
 
@@ -79,4 +111,14 @@ public class MockReaderParser extends ReaderParser {
        public Builder copy() {
                throw new NoSuchMethodError("Not implemented.");
        }
+
+       @Override
+       public <T> ClassMeta<T> getClassMeta(Class<T> c) {
+               return this.getBeanContext().getClassMeta(c);
+       }
+
+       @Override
+       public <T> ClassMeta<T> getClassMeta(Type t, Type... args) {
+               return this.getBeanContext().getClassMeta(t, args);
+       }
 }
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/testutils/MockReaderParserFunction.java
 
b/juneau-utest/src/test/java/org/apache/juneau/testutils/MockReaderParserFunction.java
index d216004..89d41cc 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/testutils/MockReaderParserFunction.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/testutils/MockReaderParserFunction.java
@@ -13,6 +13,7 @@
 package org.apache.juneau.testutils;
 
 import org.apache.juneau.*;
+import org.apache.juneau.internal.*;
 import org.apache.juneau.parser.*;
 
-public interface MockReaderParserFunction extends 
TriFunction<ReaderParserSession,String,ClassMeta<?>,Object> {}
+public interface MockReaderParserFunction extends 
Function3<ReaderParserSession,String,ClassMeta<?>,Object> {}
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/testutils/MockStreamParserFunction.java
 
b/juneau-utest/src/test/java/org/apache/juneau/testutils/MockReaderParserPartFunction.java
similarity index 88%
copy from 
juneau-utest/src/test/java/org/apache/juneau/testutils/MockStreamParserFunction.java
copy to 
juneau-utest/src/test/java/org/apache/juneau/testutils/MockReaderParserPartFunction.java
index 4f06ac3..546ffb7 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/testutils/MockStreamParserFunction.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/testutils/MockReaderParserPartFunction.java
@@ -13,6 +13,7 @@
 package org.apache.juneau.testutils;
 
 import org.apache.juneau.*;
-import org.apache.juneau.parser.*;
+import org.apache.juneau.httppart.*;
+import org.apache.juneau.internal.*;
 
-public interface MockStreamParserFunction extends 
TriFunction<InputStreamParserSession,byte[],ClassMeta<?>,Object> {}
+public interface MockReaderParserPartFunction extends 
Function4<HttpPartType,HttpPartSchema,String,ClassMeta<?>,Object> {}
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/testutils/MockStreamParserFunction.java
 
b/juneau-utest/src/test/java/org/apache/juneau/testutils/MockStreamParserFunction.java
index 4f06ac3..80a4a55 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/testutils/MockStreamParserFunction.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/testutils/MockStreamParserFunction.java
@@ -13,6 +13,7 @@
 package org.apache.juneau.testutils;
 
 import org.apache.juneau.*;
+import org.apache.juneau.internal.*;
 import org.apache.juneau.parser.*;
 
-public interface MockStreamParserFunction extends 
TriFunction<InputStreamParserSession,byte[],ClassMeta<?>,Object> {}
+public interface MockStreamParserFunction extends 
Function3<InputStreamParserSession,byte[],ClassMeta<?>,Object> {}
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/testutils/MockWriterSerializer.java
 
b/juneau-utest/src/test/java/org/apache/juneau/testutils/MockWriterSerializer.java
index 53e0f69..58fa44d 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/testutils/MockWriterSerializer.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/testutils/MockWriterSerializer.java
@@ -13,24 +13,60 @@
 
 package org.apache.juneau.testutils;
 
+import static org.apache.juneau.internal.ArrayUtils.*;
+import static org.apache.juneau.internal.StringUtils.*;
+
 import java.io.*;
 import java.util.*;
 import java.util.function.*;
 
+import org.apache.juneau.httppart.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.serializer.*;
 
 /**
  * Utility class for creating mocked writer serializers.
  */
-public class MockWriterSerializer extends WriterSerializer {
+public class MockWriterSerializer extends WriterSerializer implements 
HttpPartSerializer {
+
+       
//-----------------------------------------------------------------------------------------------------------------
+       // Predefined types
+       
//-----------------------------------------------------------------------------------------------------------------
+
+       public static final X X = new X(create());
+
+       public static class X extends MockWriterSerializer {
+               protected X(Builder builder) {
+                       super(builder
+                               .function((s,o) -> out(o))
+                               .partFunction((s,t,o) -> out(o))
+                       );
+               }
+
+               private static String out(Object value) {
+                       if (value instanceof List)
+                               value = join((List<?>)value, '|');
+                       if (value instanceof Collection)
+                               value = join((Collection<?>)value, '|');
+                       if (isArray(value))
+                               value = join(toList(value, Object.class), "|");
+                       return "x" + value + "x";
+               }
+       }
+
+       
//-----------------------------------------------------------------------------------------------------------------
+       // Instance
+       
//-----------------------------------------------------------------------------------------------------------------
 
        private final MockWriterSerializerFunction function;
+       private final MockWriterSerializerPartFunction partFunction;
        private final Function<SerializerSession,Map<String,String>> headers;
 
+
        protected MockWriterSerializer(Builder builder) {
                super(builder);
                this.function = builder.function;
+               this.partFunction = builder.partFunction;
                this.headers = builder.headers;
        }
 
@@ -52,8 +88,19 @@ public class MockWriterSerializer extends WriterSerializer {
                };
        }
 
+       @Override
+       public HttpPartSerializerSession 
createPartSession(SerializerSessionArgs args) {
+               return new HttpPartSerializerSession() {
+                       @Override
+                       public String serialize(HttpPartType type, 
HttpPartSchema schema, Object value) throws SerializeException, 
SchemaValidationException {
+                               return partFunction.apply(type, schema, value);
+                       }
+               };
+       }
+
        public static class Builder extends WriterSerializerBuilder {
                MockWriterSerializerFunction function = (s,o) -> 
StringUtils.stringify(o);
+               MockWriterSerializerPartFunction partFunction = (t,s,o) -> 
StringUtils.stringify(o);
                Function<SerializerSession,Map<String,String>> headers = (s) -> 
Collections.emptyMap();
 
                public Builder() {
@@ -64,13 +111,18 @@ public class MockWriterSerializer extends WriterSerializer 
{
                        super(copyFrom);
                }
 
-               public Builder function(MockWriterSerializerFunction function) {
-                       this.function = function;
+               public Builder function(MockWriterSerializerFunction value) {
+                       function = value;
+                       return this;
+               }
+
+               public Builder partFunction(MockWriterSerializerPartFunction 
value) {
+                       partFunction = value;
                        return this;
                }
 
-               public Builder 
headers(Function<SerializerSession,Map<String,String>> headers) {
-                       this.headers = headers;
+               public Builder 
headers(Function<SerializerSession,Map<String,String>> value) {
+                       headers = value;
                        return this;
                }
 
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/testutils/MockWriterSerializerFunction.java
 
b/juneau-utest/src/test/java/org/apache/juneau/testutils/MockWriterSerializerFunction.java
index 4a1244c..7799a5f 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/testutils/MockWriterSerializerFunction.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/testutils/MockWriterSerializerFunction.java
@@ -12,8 +12,7 @@
 
//***************************************************************************************************************************
 package org.apache.juneau.testutils;
 
-import java.util.function.*;
-
+import org.apache.juneau.internal.*;
 import org.apache.juneau.serializer.*;
 
-public interface MockWriterSerializerFunction extends 
BiFunction<SerializerSession,Object,String> {}
+public interface MockWriterSerializerFunction extends 
Function2<SerializerSession,Object,String> {}
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/testutils/TriFunction.java 
b/juneau-utest/src/test/java/org/apache/juneau/testutils/MockWriterSerializerPartFunction.java
similarity index 83%
rename from 
juneau-utest/src/test/java/org/apache/juneau/testutils/TriFunction.java
rename to 
juneau-utest/src/test/java/org/apache/juneau/testutils/MockWriterSerializerPartFunction.java
index 96511ce..69a0075 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/testutils/TriFunction.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/testutils/MockWriterSerializerPartFunction.java
@@ -12,16 +12,8 @@
 
//***************************************************************************************************************************
 package org.apache.juneau.testutils;
 
-import java.util.*;
-import java.util.function.*;
 
-@FunctionalInterface
-interface TriFunction<A,B,C,R> {
+import org.apache.juneau.httppart.*;
+import org.apache.juneau.internal.*;
 
-       R apply(A a, B b, C c);
-
-       default <V> TriFunction<A, B, C, V> andThen(Function<? super R, ? 
extends V> after) {
-               Objects.requireNonNull(after);
-               return (A a, B b, C c) -> after.apply(apply(a, b, c));
-       }
-}
\ No newline at end of file
+public interface MockWriterSerializerPartFunction extends 
Function3<HttpPartType,HttpPartSchema,Object,String> {}
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/testutils/XPartSerializer.java 
b/juneau-utest/src/test/java/org/apache/juneau/testutils/XPartSerializer.java
deleted file mode 100644
index 1373fc5..0000000
--- 
a/juneau-utest/src/test/java/org/apache/juneau/testutils/XPartSerializer.java
+++ /dev/null
@@ -1,37 +0,0 @@
-// 
***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright 
ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not 
use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                
                                              *
-// *                                                                           
                                              *
-// *  http://www.apache.org/licenses/LICENSE-2.0                               
                                              *
-// *                                                                           
                                              *
-// * Unless required by applicable law or agreed to in writing, software 
distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the 
License.                                              *
-// 
***************************************************************************************************************************
-package org.apache.juneau.testutils;
-
-import org.apache.juneau.httppart.*;
-import org.apache.juneau.serializer.*;
-
-/**
- * Test serializer.
- */
-public class XPartSerializer extends BaseHttpPartSerializer {
-
-       @Override
-       public HttpPartSerializerSession 
createPartSession(SerializerSessionArgs args) {
-               return new BaseHttpPartSerializerSession() {
-                       @Override
-                       public String serialize(HttpPartType partType, 
HttpPartSchema schema, Object value) throws SerializeException, 
SchemaValidationException {
-                               return "x" + value + "x";
-                       }
-               };
-       }
-
-       @Override
-       public String serialize(HttpPartType partType, HttpPartSchema schema, 
Object value) throws SchemaValidationException, SerializeException {
-               return createPartSession(null).serialize(partType, schema, 
value);
-       }
-}
\ No newline at end of file

Reply via email to