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

commit 3a74fcd50a49526ead445e492ee5553ae4357c6a
Author: James Bognar <[email protected]>
AuthorDate: Tue May 12 13:22:19 2026 -0400

    refactor: extract SPI seams in commons.bean for bean-runtime types (TODO-5 
Step 8a)
    
    Lays the groundwork for physically relocating 
BeanMap/BeanMeta/BeanPropertyMeta
    and friends into commons.bean by extracting the minimum runtime seams those
    types need from the marshalling layer.
    
    - New SPI: org.apache.juneau.commons.bean.BeanSession.  Captures the
      session-aware operations (convertToType, convertToMemberType, toBeanMap) 
that
      BeanMap/BeanPropertyMeta need from MarshallingSession.  Target-type 
parameters
      are typed as Object so commons.bean does not have to import ClassMeta.
    - MarshallingSession implements BeanSession; new bridge methods dispatch
      Object-typed targetType into the existing ClassMeta/Class overloads.
    - BeanConfigContext gains four bean-modeling-relevant boolean settings that
      previously only lived on MarshallingContext: beanMapPutReturnsOldValue,
      ignoreInvocationExceptionsOnGetters/Setters, 
ignoreUnknownNullBeanProperties.
      Builder, copy() and defaults are wired through.
    - MarshallingContext.buildBeanConfigContext() now populates the four new
      settings from its own resolved values.
    - BeanPropertyMeta now reads those four settings via BeanConfigContext, so 
the
      call sites no longer depend on MarshallingContext.
    - BeanConfigContext_Test extended to exercise the new defaults, builder 
fluent
      setters, and copy() preservation.
    
    The 8 target types still reference ClassMeta/MarshallingContext for the
    remaining type-resolution and registry-lookup hot paths; those will be 
retyped
    or seam-extracted in Step 8b alongside the physical git mv.
    
    Co-authored-by: Cursor <[email protected]>
---
 .../juneau/commons/bean/BeanConfigContext.java     | 91 +++++++++++++++++++++
 .../apache/juneau/commons/bean/BeanSession.java    | 92 ++++++++++++++++++++++
 .../java/org/apache/juneau/BeanPropertyMeta.java   | 10 +--
 .../java/org/apache/juneau/MarshallingContext.java |  4 +
 .../java/org/apache/juneau/MarshallingSession.java | 49 +++++++++++-
 .../commons/bean/BeanConfigContext_Test.java       | 20 +++++
 6 files changed, 260 insertions(+), 6 deletions(-)

diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/bean/BeanConfigContext.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/bean/BeanConfigContext.java
index e9309fa9ee..63ee537c74 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/bean/BeanConfigContext.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/bean/BeanConfigContext.java
@@ -92,14 +92,18 @@ public final class BeanConfigContext {
        private final Visibility beanFieldVisibility;
        private final Visibility beanMethodVisibility;
 
+       private final boolean beanMapPutReturnsOldValue;
        private final boolean beansRequireDefaultConstructor;
        private final boolean beansRequireSerializable;
        private final boolean beansRequireSettersForGetters;
        private final boolean beansRequireSomeProperties;
        private final boolean findFluentSetters;
+       private final boolean ignoreInvocationExceptionsOnGetters;
+       private final boolean ignoreInvocationExceptionsOnSetters;
        private final boolean ignoreMissingSetters;
        private final boolean ignoreTransientFields;
        private final boolean ignoreUnknownBeanProperties;
+       private final boolean ignoreUnknownNullBeanProperties;
        private final boolean unsortedProperties;
        private final boolean useInterfaceProxies;
        private final boolean useJavaBeanIntrospector;
@@ -120,14 +124,18 @@ public final class BeanConfigContext {
                beanConstructorVisibility = b.beanConstructorVisibility;
                beanFieldVisibility = b.beanFieldVisibility;
                beanMethodVisibility = b.beanMethodVisibility;
+               beanMapPutReturnsOldValue = b.beanMapPutReturnsOldValue;
                beansRequireDefaultConstructor = 
b.beansRequireDefaultConstructor;
                beansRequireSerializable = b.beansRequireSerializable;
                beansRequireSettersForGetters = b.beansRequireSettersForGetters;
                beansRequireSomeProperties = b.beansRequireSomeProperties;
                findFluentSetters = b.findFluentSetters;
+               ignoreInvocationExceptionsOnGetters = 
b.ignoreInvocationExceptionsOnGetters;
+               ignoreInvocationExceptionsOnSetters = 
b.ignoreInvocationExceptionsOnSetters;
                ignoreMissingSetters = b.ignoreMissingSetters;
                ignoreTransientFields = b.ignoreTransientFields;
                ignoreUnknownBeanProperties = b.ignoreUnknownBeanProperties;
+               ignoreUnknownNullBeanProperties = 
b.ignoreUnknownNullBeanProperties;
                unsortedProperties = b.unsortedProperties;
                useInterfaceProxies = b.useInterfaceProxies;
                useJavaBeanIntrospector = b.useJavaBeanIntrospector;
@@ -181,6 +189,17 @@ public final class BeanConfigContext {
         */
        public Visibility getBeanMethodVisibility() { return 
beanMethodVisibility; }
 
+       /**
+        * Returns whether {@code BeanMap.put(String,Object)} returns the 
previous property value.
+        *
+        * <p>
+        * When <jk>false</jk> (the default), {@code BeanMap.put(...)} always 
returns <jk>null</jk> for performance reasons —
+        * the underlying bean's getter is skipped before the setter is invoked.
+        *
+        * @return <jk>true</jk> if old values are returned.
+        */
+       public boolean isBeanMapPutReturnsOldValue() { return 
beanMapPutReturnsOldValue; }
+
        /**
         * Returns whether classes must have a no-arg constructor to be 
considered beans.
         *
@@ -216,6 +235,27 @@ public final class BeanConfigContext {
         */
        public boolean isFindFluentSetters() { return findFluentSetters; }
 
+       /**
+        * Returns whether exceptions thrown from bean property getters should 
be silently swallowed.
+        *
+        * <p>
+        * When <jk>true</jk>, an exception thrown by a getter is treated as a 
<jk>null</jk> property value rather than
+        * propagated to the caller.
+        *
+        * @return <jk>true</jk> if getter invocation exceptions are ignored.
+        */
+       public boolean isIgnoreInvocationExceptionsOnGetters() { return 
ignoreInvocationExceptionsOnGetters; }
+
+       /**
+        * Returns whether exceptions thrown from bean property setters should 
be silently swallowed.
+        *
+        * <p>
+        * When <jk>true</jk>, an exception thrown by a setter is suppressed 
rather than propagated to the caller.
+        *
+        * @return <jk>true</jk> if setter invocation exceptions are ignored.
+        */
+       public boolean isIgnoreInvocationExceptionsOnSetters() { return 
ignoreInvocationExceptionsOnSetters; }
+
        /**
         * Returns whether bean properties without setters should be silently 
ignored during deserialization.
         *
@@ -237,6 +277,17 @@ public final class BeanConfigContext {
         */
        public boolean isIgnoreUnknownBeanProperties() { return 
ignoreUnknownBeanProperties; }
 
+       /**
+        * Returns whether attempts to set unknown bean properties to 
<jk>null</jk> should be silently ignored.
+        *
+        * <p>
+        * When <jk>true</jk> (the default), trying to set an unknown property 
to <jk>null</jk> is a no-op rather than an
+        * error.  When <jk>false</jk>, the property setter still rejects 
unknown property names.
+        *
+        * @return <jk>true</jk> if unknown null properties are silently 
ignored.
+        */
+       public boolean isIgnoreUnknownNullBeanProperties() { return 
ignoreUnknownNullBeanProperties; }
+
        /**
         * Returns whether properties should preserve their JVM-discovered 
(non-alphabetical) order.
         *
@@ -350,14 +401,18 @@ public final class BeanConfigContext {
                private Visibility beanFieldVisibility = Visibility.PUBLIC;
                private Visibility beanMethodVisibility = Visibility.PUBLIC;
 
+               private boolean beanMapPutReturnsOldValue;
                private boolean beansRequireDefaultConstructor;
                private boolean beansRequireSerializable;
                private boolean beansRequireSettersForGetters;
                private boolean beansRequireSomeProperties = true;
                private boolean findFluentSetters;
+               private boolean ignoreInvocationExceptionsOnGetters;
+               private boolean ignoreInvocationExceptionsOnSetters;
                private boolean ignoreMissingSetters = true;
                private boolean ignoreTransientFields = true;
                private boolean ignoreUnknownBeanProperties;
+               private boolean ignoreUnknownNullBeanProperties = true;
                private boolean unsortedProperties;
                private boolean useInterfaceProxies = true;
                private boolean useJavaBeanIntrospector;
@@ -380,14 +435,18 @@ public final class BeanConfigContext {
                        beanConstructorVisibility = 
src.beanConstructorVisibility;
                        beanFieldVisibility = src.beanFieldVisibility;
                        beanMethodVisibility = src.beanMethodVisibility;
+                       beanMapPutReturnsOldValue = 
src.beanMapPutReturnsOldValue;
                        beansRequireDefaultConstructor = 
src.beansRequireDefaultConstructor;
                        beansRequireSerializable = src.beansRequireSerializable;
                        beansRequireSettersForGetters = 
src.beansRequireSettersForGetters;
                        beansRequireSomeProperties = 
src.beansRequireSomeProperties;
                        findFluentSetters = src.findFluentSetters;
+                       ignoreInvocationExceptionsOnGetters = 
src.ignoreInvocationExceptionsOnGetters;
+                       ignoreInvocationExceptionsOnSetters = 
src.ignoreInvocationExceptionsOnSetters;
                        ignoreMissingSetters = src.ignoreMissingSetters;
                        ignoreTransientFields = src.ignoreTransientFields;
                        ignoreUnknownBeanProperties = 
src.ignoreUnknownBeanProperties;
+                       ignoreUnknownNullBeanProperties = 
src.ignoreUnknownNullBeanProperties;
                        unsortedProperties = src.unsortedProperties;
                        useInterfaceProxies = src.useInterfaceProxies;
                        useJavaBeanIntrospector = src.useJavaBeanIntrospector;
@@ -442,6 +501,14 @@ public final class BeanConfigContext {
                 */
                public Builder beanMethodVisibility(Visibility value) { 
beanMethodVisibility = assertArgNotNull("value", value); return this; }
 
+               /**
+                * Toggles whether {@code BeanMap.put(String,Object)} returns 
the previous value rather than <jk>null</jk>.
+                *
+                * @param value The new value.
+                * @return This object.
+                */
+               public Builder beanMapPutReturnsOldValue(boolean value) { 
beanMapPutReturnsOldValue = value; return this; }
+
                /**
                 * Toggles the requirement that beans have a no-arg default 
constructor.
                 *
@@ -482,6 +549,22 @@ public final class BeanConfigContext {
                 */
                public Builder findFluentSetters(boolean value) { 
findFluentSetters = value; return this; }
 
+               /**
+                * Toggles silent suppression of exceptions thrown by bean 
property getters.
+                *
+                * @param value The new value.
+                * @return This object.
+                */
+               public Builder ignoreInvocationExceptionsOnGetters(boolean 
value) { ignoreInvocationExceptionsOnGetters = value; return this; }
+
+               /**
+                * Toggles silent suppression of exceptions thrown by bean 
property setters.
+                *
+                * @param value The new value.
+                * @return This object.
+                */
+               public Builder ignoreInvocationExceptionsOnSetters(boolean 
value) { ignoreInvocationExceptionsOnSetters = value; return this; }
+
                /**
                 * Toggles silent ignoring of properties without setters during 
deserialization.
                 *
@@ -506,6 +589,14 @@ public final class BeanConfigContext {
                 */
                public Builder ignoreUnknownBeanProperties(boolean value) { 
ignoreUnknownBeanProperties = value; return this; }
 
+               /**
+                * Toggles silent ignoring of attempts to set unknown bean 
properties to <jk>null</jk>.
+                *
+                * @param value The new value.
+                * @return This object.
+                */
+               public Builder ignoreUnknownNullBeanProperties(boolean value) { 
ignoreUnknownNullBeanProperties = value; return this; }
+
                /**
                 * Toggles whether properties remain in JVM-discovered 
(non-alphabetical) order.
                 *
diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/bean/BeanSession.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/bean/BeanSession.java
new file mode 100644
index 0000000000..8b4b511079
--- /dev/null
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/bean/BeanSession.java
@@ -0,0 +1,92 @@
+/*
+ * 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.commons.bean;
+
+/**
+ * Minimum runtime surface that the bean-modeling layer needs from a 
marshalling session.
+ *
+ * <p>
+ * {@code BeanSession} is an SPI seam between the bean-modeling runtime (in 
{@code commons.bean}) and the
+ * marshalling stack (in {@code juneau-marshall}).  The marshalling layer's 
{@code MarshallingSession}
+ * implements this interface so the bean-modeling types (notably {@code 
BeanMap} and {@code BeanPropertyMeta})
+ * can request session-aware operations — type conversion, bean-map wrapping — 
without referencing any
+ * marshalling-aware concrete types.
+ *
+ * <p>
+ * On the commons-side construction path ({@code BeanMeta.of(Class, 
BeanConfigContext)}) the session is
+ * <jk>null</jk> and these operations are skipped; the bean-modeling code runs 
in raw-reflection mode.
+ *
+ * <h5 class='section'>Method parameter typing:</h5>
+ * <p>
+ * The {@code targetType} parameters are typed as {@link Object} because the 
marshalling layer expresses them
+ * as {@code ClassMeta<?>} — a marshalling-side type that {@code commons.bean} 
cannot reference.  Callers in
+ * the bean-modeling layer pass through whatever opaque type-metadata handle 
they received; the
+ * {@code MarshallingSession} implementation interprets it as a {@code 
ClassMeta}.
+ *
+ * <h5 class='section'>See Also:</h5><ul>
+ *     <li class='ja'>{@link BeanConfigContext} — bean-modeling configuration 
counterpart.
+ * </ul>
+ */
+public interface BeanSession {
+
+       /**
+        * Converts the specified value to the specified target type.
+        *
+        * <p>
+        * Implementations apply any registered conversions, swaps, or 
coercions necessary to produce a value
+        * compatible with {@code targetType}.  On the marshalling-side, this 
routes through
+        * {@code MarshallingSession.convertToType(Object, ClassMeta)}.
+        *
+        * @param value The value to convert.  May be <jk>null</jk>.
+        * @param targetType
+        *      The target type — typically a marshalling-side {@code 
ClassMeta<?>} handle passed through from
+        *      a {@code BeanPropertyMeta} or {@code BeanMap}.  Must not be 
<jk>null</jk>.
+        * @return The converted value.
+        */
+       Object convertToType(Object value, Object targetType);
+
+       /**
+        * Converts the specified value to the specified target type, 
instantiating non-static inner classes against
+        * an outer instance.
+        *
+        * @param outer The outer-class instance for non-static inner classes.  
May be <jk>null</jk>.
+        * @param value The value to convert.  May be <jk>null</jk>.
+        * @param targetType The target type — typically a marshalling-side 
{@code ClassMeta<?>}.  Must not be <jk>null</jk>.
+        * @return The converted value.
+        */
+       Object convertToMemberType(Object outer, Object value, Object 
targetType);
+
+       /**
+        * Wraps the specified bean in a {@code BeanMap}.
+        *
+        * <p>
+        * Equivalent to {@code MarshallingSession.toBeanMap(Object)} on the 
marshalling-side.  The return type is
+        * typed as {@link Object} (rather than {@code BeanMap}) because the 
bean-modeling {@code BeanMap} runtime
+        * type currently lives in {@code juneau-marshall}; callers in {@code 
commons.bean} treat the returned value
+        * opaquely and pass it through to other {@code BeanSession} / 
bean-modeling APIs that re-narrow it.
+        *
+        * <p>
+        * The signature is generic to allow implementations (notably {@code 
MarshallingSession}) to satisfy this
+        * method with their existing covariant {@code <T> BeanMap<T> 
toBeanMap(T)} declaration without an
+        * additional bridge method.
+        *
+        * @param <T> The bean type.
+        * @param bean The bean to wrap.  Must not be <jk>null</jk>.
+        * @return A new bean map (typically a {@code BeanMap}) wrapping the 
supplied bean.
+        */
+       <T> Object toBeanMap(T bean);
+}
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java
index 735d2ce234..d21237c5a9 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java
@@ -1060,7 +1060,7 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
                return invokeGetter(bean, pName);
 
        } catch (Exception e) {
-               if (nn(bc) && bc.isIgnoreInvocationExceptionsOnGetters()) {
+               if (config.isIgnoreInvocationExceptionsOnGetters()) {
                        if (nn(rawTypeMeta) && rawTypeMeta.isPrimitive())
                                return rawTypeMeta.getPrimitiveDefault();
                        return null;
@@ -1167,7 +1167,7 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
                        var isCollection = rawTypeMeta.isCollection();
 
                        if ((! isDyna) && field == null && setter == null && ! 
(isMap || isCollection)) {
-                               if ((value1 == null && nn(bc) && 
bc.isIgnoreUnknownNullBeanProperties()) || config.isIgnoreMissingSetters())
+                               if ((value1 == null && 
config.isIgnoreUnknownNullBeanProperties()) || config.isIgnoreMissingSetters())
                                        return null;
                                throw bex(beanMeta.getClassInfo(), "Setter or 
public field not defined on property ''{0}''", name);
                        }
@@ -1186,7 +1186,7 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
        })
        private Object setPropertyValue(BeanMap<?> m, String pName, Object 
value1, Object bean, boolean isMap, boolean isCollection, MarshallingSession 
session) throws ParseException {
                try {
-                       var r = (bc.isBeanMapPutReturnsOldValue() || isMap || 
isCollection) && (nn(getter) || nn(field)) ? get(m, pName) : null;
+                       var r = (config.isBeanMapPutReturnsOldValue() || isMap 
|| isCollection) && (nn(getter) || nn(field)) ? get(m, pName) : null;
                        var propertyClass = rawTypeMeta.inner();
                        var pcInfo = rawTypeMeta;
 
@@ -1331,7 +1331,7 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
                } catch (BeanRuntimeException e) {
                        throw e;
                } catch (Exception e1) {
-                       if (bc.isIgnoreInvocationExceptionsOnSetters()) {
+                       if (config.isIgnoreInvocationExceptionsOnSetters()) {
                                if (rawTypeMeta.isPrimitive())
                                        return 
rawTypeMeta.getPrimitiveDefault();
                                return null;
@@ -1423,7 +1423,7 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
        return swapAndFilterProperty(session, o);
 
        } catch (Exception e) {
-               if (nn(bc) && bc.isIgnoreInvocationExceptionsOnGetters()) {
+               if (config.isIgnoreInvocationExceptionsOnGetters()) {
                        if (nn(rawTypeMeta) && rawTypeMeta.isPrimitive())
                                return rawTypeMeta.getPrimitiveDefault();
                        return null;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MarshallingContext.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MarshallingContext.java
index cbf369aae2..91073ef242 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MarshallingContext.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MarshallingContext.java
@@ -3773,14 +3773,18 @@ public class MarshallingContext extends Context 
implements ConversionFinder {
                        .beanConstructorVisibility(beanConstructorVisibility)
                        .beanFieldVisibility(beanFieldVisibility)
                        .beanMethodVisibility(beanMethodVisibility)
+                       .beanMapPutReturnsOldValue(beanMapPutReturnsOldValue)
                        
.beansRequireDefaultConstructor(beansRequireDefaultConstructor)
                        .beansRequireSerializable(beansRequireSerializable)
                        
.beansRequireSettersForGetters(beansRequireSettersForGetters)
                        .beansRequireSomeProperties(beansRequireSomeProperties)
                        .findFluentSetters(findFluentSetters)
+                       
.ignoreInvocationExceptionsOnGetters(ignoreInvocationExceptionsOnGetters)
+                       
.ignoreInvocationExceptionsOnSetters(ignoreInvocationExceptionsOnSetters)
                        .ignoreMissingSetters(ignoreMissingSetters)
                        .ignoreTransientFields(ignoreTransientFields)
                        
.ignoreUnknownBeanProperties(ignoreUnknownBeanProperties)
+                       
.ignoreUnknownNullBeanProperties(ignoreUnknownNullBeanProperties)
                        .unsortedProperties(unsortedProperties)
                        .useInterfaceProxies(useInterfaceProxies)
                        .useJavaBeanIntrospector(useJavaBeanIntrospector)
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MarshallingSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MarshallingSession.java
index 15fe991f6d..0b5358bdec 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MarshallingSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MarshallingSession.java
@@ -54,7 +54,7 @@ import org.apache.juneau.commons.bean.*;
        "java:S115", // Constants use UPPER_snakeCase naming convention
        "java:S1452"  // Wildcard required - ClassMeta<?>, ObjectSwap<?,?>, 
etc. for bean metadata
 })
-public class MarshallingSession extends ContextSession implements 
ConverterSession {
+public class MarshallingSession extends ContextSession implements 
ConverterSession, BeanSession {
 
        // Property name constants
        private static final String PROP_locale = "locale";
@@ -1270,4 +1270,51 @@ public class MarshallingSession extends ContextSession 
implements ConverterSessi
                return array;
        }
 
+       
//-----------------------------------------------------------------------------------------------------------------
+       // BeanSession bridge methods — SPI seam to commons.bean.
+       
//-----------------------------------------------------------------------------------------------------------------
+
+       /**
+        * Bridge implementation of {@link BeanSession#convertToType(Object, 
Object)} that dispatches to the
+        * {@link ClassMeta}-typed overload when the supplied {@code 
targetType} is a {@link ClassMeta}, or to the
+        * {@link Class}-typed overload when it is a {@link Class}.
+        *
+        * <p>
+        * The bean-modeling layer calls this method through the {@link 
BeanSession} interface so it can request type
+        * conversion without referencing the marshalling-side {@link 
ClassMeta} concrete type.
+        *
+        * @param value The value to convert.  May be <jk>null</jk>.
+        * @param targetType A {@link ClassMeta} or {@link Class} describing 
the target type.  Must not be <jk>null</jk>.
+        * @return The converted value.
+        * @throws IllegalArgumentException If {@code targetType} is neither a 
{@link ClassMeta} nor a {@link Class}.
+        */
+       @Override /* BeanSession */
+       public final Object convertToType(Object value, Object targetType) {
+               if (targetType instanceof ClassMeta<?> cm)
+                       return convertToType(value, cm);
+               if (targetType instanceof Class<?> c)
+                       return convertToType(value, c);
+               throw illegalArg("Unsupported targetType for convertToType: 
{0}", targetType == null ? "null" : targetType.getClass().getName());
+       }
+
+       /**
+        * Bridge implementation of {@link 
BeanSession#convertToMemberType(Object, Object, Object)} that dispatches to the
+        * {@link ClassMeta}-typed overload when the supplied {@code 
targetType} is a {@link ClassMeta}, or to the
+        * {@link Class}-typed overload when it is a {@link Class}.
+        *
+        * @param outer The outer-class instance for non-static inner classes.  
May be <jk>null</jk>.
+        * @param value The value to convert.  May be <jk>null</jk>.
+        * @param targetType A {@link ClassMeta} or {@link Class} describing 
the target type.  Must not be <jk>null</jk>.
+        * @return The converted value.
+        * @throws IllegalArgumentException If {@code targetType} is neither a 
{@link ClassMeta} nor a {@link Class}.
+        */
+       @Override /* BeanSession */
+       public final Object convertToMemberType(Object outer, Object value, 
Object targetType) {
+               if (targetType instanceof ClassMeta<?> cm)
+                       return convertToMemberType(outer, value, cm);
+               if (targetType instanceof Class<?> c)
+                       return convertToMemberType(outer, value, c);
+               throw illegalArg("Unsupported targetType for 
convertToMemberType: {0}", targetType == null ? "null" : 
targetType.getClass().getName());
+       }
+
 }
\ No newline at end of file
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/commons/bean/BeanConfigContext_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/commons/bean/BeanConfigContext_Test.java
index 77e1e3a8bb..27e445953b 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/commons/bean/BeanConfigContext_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/commons/bean/BeanConfigContext_Test.java
@@ -44,14 +44,18 @@ class BeanConfigContext_Test extends TestBase {
        @Test
        void a02_default_booleanToggles() {
                var ctx = BeanConfigContext.DEFAULT;
+               assertFalse(ctx.isBeanMapPutReturnsOldValue());
                assertFalse(ctx.isBeansRequireDefaultConstructor());
                assertFalse(ctx.isBeansRequireSerializable());
                assertFalse(ctx.isBeansRequireSettersForGetters());
                assertTrue(ctx.isBeansRequireSomeProperties());
                assertFalse(ctx.isFindFluentSetters());
+               assertFalse(ctx.isIgnoreInvocationExceptionsOnGetters());
+               assertFalse(ctx.isIgnoreInvocationExceptionsOnSetters());
                assertTrue(ctx.isIgnoreMissingSetters());
                assertTrue(ctx.isIgnoreTransientFields());
                assertFalse(ctx.isIgnoreUnknownBeanProperties());
+               assertTrue(ctx.isIgnoreUnknownNullBeanProperties());
                assertFalse(ctx.isUnsortedProperties());
                assertTrue(ctx.isUseInterfaceProxies());
                assertFalse(ctx.isUseJavaBeanIntrospector());
@@ -97,26 +101,34 @@ class BeanConfigContext_Test extends TestBase {
        @Test
        void b02_builder_booleanToggles() {
                var ctx = BeanConfigContext.create()
+                       .beanMapPutReturnsOldValue(true)
                        .beansRequireDefaultConstructor(true)
                        .beansRequireSerializable(true)
                        .beansRequireSettersForGetters(true)
                        .beansRequireSomeProperties(false)
                        .findFluentSetters(true)
+                       .ignoreInvocationExceptionsOnGetters(true)
+                       .ignoreInvocationExceptionsOnSetters(true)
                        .ignoreMissingSetters(false)
                        .ignoreTransientFields(false)
                        .ignoreUnknownBeanProperties(true)
+                       .ignoreUnknownNullBeanProperties(false)
                        .unsortedProperties(true)
                        .useInterfaceProxies(false)
                        .useJavaBeanIntrospector(true)
                        .build();
+               assertTrue(ctx.isBeanMapPutReturnsOldValue());
                assertTrue(ctx.isBeansRequireDefaultConstructor());
                assertTrue(ctx.isBeansRequireSerializable());
                assertTrue(ctx.isBeansRequireSettersForGetters());
                assertFalse(ctx.isBeansRequireSomeProperties());
                assertTrue(ctx.isFindFluentSetters());
+               assertTrue(ctx.isIgnoreInvocationExceptionsOnGetters());
+               assertTrue(ctx.isIgnoreInvocationExceptionsOnSetters());
                assertFalse(ctx.isIgnoreMissingSetters());
                assertFalse(ctx.isIgnoreTransientFields());
                assertTrue(ctx.isIgnoreUnknownBeanProperties());
+               assertFalse(ctx.isIgnoreUnknownNullBeanProperties());
                assertTrue(ctx.isUnsortedProperties());
                assertFalse(ctx.isUseInterfaceProxies());
                assertTrue(ctx.isUseJavaBeanIntrospector());
@@ -244,14 +256,18 @@ class BeanConfigContext_Test extends TestBase {
                        .beanConstructorVisibility(Visibility.PRIVATE)
                        .beanFieldVisibility(Visibility.DEFAULT)
                        .beanMethodVisibility(Visibility.PROTECTED)
+                       .beanMapPutReturnsOldValue(true)
                        .beansRequireDefaultConstructor(true)
                        .beansRequireSerializable(true)
                        .beansRequireSettersForGetters(true)
                        .beansRequireSomeProperties(false)
                        .findFluentSetters(true)
+                       .ignoreInvocationExceptionsOnGetters(true)
+                       .ignoreInvocationExceptionsOnSetters(true)
                        .ignoreMissingSetters(false)
                        .ignoreTransientFields(false)
                        .ignoreUnknownBeanProperties(true)
+                       .ignoreUnknownNullBeanProperties(false)
                        .unsortedProperties(true)
                        .useInterfaceProxies(false)
                        .useJavaBeanIntrospector(true)
@@ -271,14 +287,18 @@ class BeanConfigContext_Test extends TestBase {
                assertEquals(src.getBeanConstructorVisibility(), 
copy.getBeanConstructorVisibility());
                assertEquals(src.getBeanFieldVisibility(), 
copy.getBeanFieldVisibility());
                assertEquals(src.getBeanMethodVisibility(), 
copy.getBeanMethodVisibility());
+               assertEquals(src.isBeanMapPutReturnsOldValue(), 
copy.isBeanMapPutReturnsOldValue());
                assertEquals(src.isBeansRequireDefaultConstructor(), 
copy.isBeansRequireDefaultConstructor());
                assertEquals(src.isBeansRequireSerializable(), 
copy.isBeansRequireSerializable());
                assertEquals(src.isBeansRequireSettersForGetters(), 
copy.isBeansRequireSettersForGetters());
                assertEquals(src.isBeansRequireSomeProperties(), 
copy.isBeansRequireSomeProperties());
                assertEquals(src.isFindFluentSetters(), 
copy.isFindFluentSetters());
+               assertEquals(src.isIgnoreInvocationExceptionsOnGetters(), 
copy.isIgnoreInvocationExceptionsOnGetters());
+               assertEquals(src.isIgnoreInvocationExceptionsOnSetters(), 
copy.isIgnoreInvocationExceptionsOnSetters());
                assertEquals(src.isIgnoreMissingSetters(), 
copy.isIgnoreMissingSetters());
                assertEquals(src.isIgnoreTransientFields(), 
copy.isIgnoreTransientFields());
                assertEquals(src.isIgnoreUnknownBeanProperties(), 
copy.isIgnoreUnknownBeanProperties());
+               assertEquals(src.isIgnoreUnknownNullBeanProperties(), 
copy.isIgnoreUnknownNullBeanProperties());
                assertEquals(src.isUnsortedProperties(), 
copy.isUnsortedProperties());
                assertEquals(src.isUseInterfaceProxies(), 
copy.isUseInterfaceProxies());
                assertEquals(src.isUseJavaBeanIntrospector(), 
copy.isUseJavaBeanIntrospector());

Reply via email to