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 9ff4e3234a2b4274e065e4fabaa45ee13d41d940
Author: James Bognar <[email protected]>
AuthorDate: Wed May 13 09:38:16 2026 -0400

    refactor: route BeanPropertyMeta/BeanMap through commons SPI seams; lift 
@Uri to post-processor (TODO-5 Phase C Task 5 Steps A-E1)
    
    - Replace remaining MarshallingContext casts with BeanTypeResolver SPI calls
    - Retype readTransform/writeTransform BiFunctions to BeanSession
    - Route BeanProxyInvocationHandler.equals through commons-side BeanMap 
construction
    - Inline BeanMap.of(T) to bypass MarshallingContext.DEFAULT_SESSION
    - Lift @Uri annotation reads from BeanPropertyMeta.Builder.validate() to 
MarshalledPropertyPostProcessor
    
    Co-authored-by: Cursor <[email protected]>
---
 .../src/main/java/org/apache/juneau/BeanMap.java   |  3 +-
 .../java/org/apache/juneau/BeanPropertyMeta.java   | 37 ++++-----
 .../apache/juneau/BeanProxyInvocationHandler.java  |  4 +-
 .../juneau/MarshalledPropertyPostProcessor.java    | 17 +++-
 todo/TODO-5-bean-runtime-types-to-commons.md       | 95 ++++++++++++++++++++++
 5 files changed, 131 insertions(+), 25 deletions(-)

diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMap.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMap.java
index aee7aa8f68..4ba73a7f2d 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMap.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMap.java
@@ -76,8 +76,9 @@ public class BeanMap<T> extends AbstractMap<String,Object> 
implements Delegate<T
         * @param bean The bean being wrapped.
         * @return A new {@link BeanMap} instance wrapping the bean.
         */
+       @SuppressWarnings("unchecked")
        public static <T> BeanMap<T> of(T bean) {
-               return MarshallingContext.DEFAULT_SESSION.toBeanMap(bean);
+               return new BeanMap<>(bean, BeanMeta.of((Class<T>) 
bean.getClass()));
        }
 
        /**
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 1eb2c56926..b2dda12be2 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
@@ -82,7 +82,7 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
         */
        public static class Builder {
                BeanMeta<?> beanMeta;  // Package-private for BeanMeta access
-               Object bc;  // Object-typed (was MarshallingContext) so the 
field can live in commons.bean; cast to MarshallingContext at marshalling-side 
use sites.  Null when the owning BeanMeta was built via the commons-side path.
+               BeanTypeResolver bc;  // The bean-modeling SPI seam to the 
marshalling-side type resolver.  Null when the owning BeanMeta was built via 
the commons-side path.
                BeanConfigContext config;  // Package-private for BeanMeta 
access.  Always non-null — sourced from the owning BeanMeta.
                String name;  // Package-private for BeanMeta access
                FieldInfo field;  // Package-private for BeanMeta access
@@ -92,11 +92,11 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
                MethodInfo extraKeys;  // Package-private for BeanMeta access
                BeanTypeInfo<?> rawTypeMeta;  // Package-private for BeanMeta 
access (used to install swap-aware transforms).  Null on commons-side path (no 
type resolution).  Concrete instances are always {@link ClassMeta} since it's 
the only in-tree implementation; the field is typed against the bean-modeling 
SPI seam so the field can live in commons.bean.
                Object swap;  // Object-typed so the field can live in 
commons.bean; cast to ObjectSwap by marshalling-side consumers.  Set only via 
MarshalledPropertyPostProcessor (marshalling-side post-processor).
-               BiFunction<MarshallingSession,Object,Object> readTransform;  // 
Package-private; defaults to identity if null.
-               BiFunction<MarshallingSession,Object,Object> writeTransform; // 
Package-private; defaults to identity if null.
+               BiFunction<BeanSession,Object,Object> readTransform;  // 
Package-private; defaults to identity if null.  Typed against the commons.bean 
SPI seam; marshalling-side installers cast the session argument back to {@link 
MarshallingSession} where needed (see {@link 
MarshalledPropertyPostProcessor#installSwapAwareTransforms}).
+               BiFunction<BeanSession,Object,Object> writeTransform; // 
Package-private; defaults to identity if null.  Typed against the commons.bean 
SPI seam (see readTransform note).
                List<ClassInfo> dictionaryClasses;  // Package-private for 
BeanMeta access; @MarshalledProp(dictionary={}) classes scanned during 
validate().
                private boolean isConstructorArg;
-               private boolean isUri;
+               boolean isUri;  // Package-private so 
MarshalledPropertyPostProcessor can set @Uri-derived flag.  Mirrors 
rawTypeMeta.isUri() plus @Uri annotation reads on field/getter/setter.
                private boolean isDyna;
                private boolean isDynaGetterMap;
                BeanTypeInfo<?> typeMeta;  // Package-private so the 
marshalling-side post-processor can override after @Swap/@MarshalledProp 
detection.  Concrete instances are always {@link ClassMeta}; typed against the 
bean-modeling SPI seam.
@@ -109,7 +109,7 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
 
                Builder(BeanMeta<?> beanMeta, String name) {
                        this.beanMeta = beanMeta;
-                       this.bc = beanMeta.getMarshallingContext();
+                       this.bc = beanMeta.getMarshallingContext();  // 
MarshallingContext implements BeanTypeResolver; null on commons-side path.
                        this.config = beanMeta.getConfig();
                        this.name = name;
                }
@@ -147,7 +147,7 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
                 * @param value The transform function.  Must not be 
<jk>null</jk>.
                 * @return This object.
                 */
-               public Builder 
readTransform(BiFunction<MarshallingSession,Object,Object> value) {
+               public Builder 
readTransform(BiFunction<BeanSession,Object,Object> value) {
                        readTransform = assertArgNotNull(ARG_value, value);
                        return this;
                }
@@ -167,7 +167,7 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
                 * @param value The transform function.  Must not be 
<jk>null</jk>.
                 * @return This object.
                 */
-               public Builder 
writeTransform(BiFunction<MarshallingSession,Object,Object> value) {
+               public Builder 
writeTransform(BiFunction<BeanSession,Object,Object> value) {
                        writeTransform = assertArgNotNull(ARG_value, value);
                        return this;
                }
@@ -199,13 +199,13 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
                 * Sets the raw metadata type for this bean property from a 
{@link Class}.
                 *
                 * <p>
-                * Convenience overload that resolves the supplied class to a 
{@link ClassMeta} via the property's
-                * {@link MarshallingContext}, allowing callers from the 
bean-modeling layer to seed the type without
-                * holding a {@link ClassMeta} reference.
+                * Convenience overload that resolves the supplied class via 
the property's
+                * {@link BeanTypeResolver}, allowing callers from the 
bean-modeling layer to seed the type without
+                * holding a {@link BeanTypeInfo} reference.
                 *
                 * <p>
                 * When the owning {@link BeanMeta} was built via the 
commons-side path
-                * ({@link BeanMeta#of(Class, BeanConfigContext)}), no 
marshalling context is available, so
+                * ({@link BeanMeta#of(Class, BeanConfigContext)}), no resolver 
is available, so
                 * {@code rawTypeMeta}/{@code typeMeta} are left <jk>null</jk> 
and the property runs in raw-reflection mode.
                 *
                 * @param value The raw metadata type for this bean property.
@@ -215,7 +215,9 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
                        assertArgNotNull(ARG_value, value);
                        if (bc == null)
                                return this;
-                       return rawMetaType(((MarshallingContext) 
bc).getClassMeta(value));
+                       rawTypeMeta = bc.resolveType(null, info(value), null);
+                       typeMeta = rawTypeMeta;
+                       return this;
                }
 
                /**
@@ -375,7 +377,6 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
                                        if (ne(beanp.wo()))
                                                writeOnly = bool(beanp.wo());
                                });
-                               isUri |= ap.has(Uri.class, ifi);
                        }
 
                        if (nn(getter)) {
@@ -384,7 +385,6 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
                                        rawTypeMeta = 
bc.resolveType(opt(last(lbp)).orElse(null), getter.getReturnType(), 
typeVarImpls);
                                if (nn(rawTypeMeta))
                                        isUri |= rawTypeMeta.isUri();
-                               isUri |= ap.has(Uri.class, gi);
                                lbp.forEach(x -> {
                                        var beanp = x.inner();
                                        if (ne(beanp.ro()))
@@ -400,7 +400,6 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
                                        rawTypeMeta = 
bc.resolveType(opt(last(lbp)).orElse(null), setter.getParameterTypes().get(0), 
typeVarImpls);
                                if (nn(rawTypeMeta))
                                        isUri |= rawTypeMeta.isUri();
-                               isUri |= ap.has(Uri.class, si);
                                lbp.forEach(x -> {
                                        var beanp = x.inner();
                                        if (ne(beanp.ro()))
@@ -498,7 +497,7 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
 
        private final AnnotationProvider ap;                             // 
Annotation provider for finding annotations on this property.  Sourced from bc 
(marshalling-side) or beanMeta.getConfig() (commons-side).
        private final Supplier<List<AnnotationInfo<?>>> annotations;     // 
Memoized list of all annotations on this property.
-       private final Object bc;                                         // 
MarshallingContext, but Object-typed so the field can live in commons.bean.  
Cast at marshalling-side use sites.  Null when the owning BeanMeta was built 
via the commons-side path.
+       private final BeanTypeResolver bc;                               // The 
bean-modeling SPI seam to the marshalling-side type resolver.  Null when the 
owning BeanMeta was built via the commons-side path.
        private final BeanConfigContext config;                          // 
Bean-modeling settings facade — always non-null.  Mirrors the BeanMeta's config.
        private final BeanMeta<?> beanMeta;                              // The 
bean that this property belongs to.
        private final boolean canRead;                                   // 
True if this property can be read.
@@ -515,12 +514,12 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
        private final String name;                                       // The 
name of the property.
        private final Object overrideValue;                              // The 
bean property value (if it's an overridden delegate).
        private final BeanTypeInfo<?> rawTypeMeta;                       // The 
real class type of the bean property.  Concrete instances are always {@link 
ClassMeta}; typed against the bean-modeling SPI seam for the eventual move to 
commons.bean.
-       private final BiFunction<MarshallingSession,Object,Object> 
readTransform;  // Applied to raw getter result; identity by default.
+       private final BiFunction<BeanSession,Object,Object> readTransform;  // 
Applied to raw getter result; identity by default.  Typed against the 
commons.bean SPI seam.
        private final boolean readOnly;                                  // 
True if this property is read-only.
        private final MethodInfo setter;                                 // The 
bean property setter.
        private final Object swap;                                       // 
ObjectSwap, but Object-typed so the field can live in commons.bean; cast at 
marshalling-side use sites.  Defined only via @MarshalledProp(format=...) or 
@Swap.
        private final BeanTypeInfo<?> typeMeta;                          // The 
transformed class type of the bean property.  Concrete instances are always 
{@link ClassMeta}; typed against the bean-modeling SPI seam.
-       private final BiFunction<MarshallingSession,Object,Object> 
writeTransform; // Applied to incoming value before raw setter; identity by 
default.
+       private final BiFunction<BeanSession,Object,Object> writeTransform; // 
Applied to incoming value before raw setter; identity by default.  Typed 
against the commons.bean SPI seam.
        private final boolean writeOnly;                                 // 
True if this property is write-only.
 
        /**
@@ -554,7 +553,7 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
                readTransform = b.readTransform != null ? b.readTransform : 
(session, o) -> o;
                writeTransform = b.writeTransform != null ? b.writeTransform : 
(session, o) -> o;
 
-               ap = nn(bc) ? ((MarshallingContext) bc).getAnnotationProvider() 
: b.config.getAnnotationProvider();
+               ap = nn(bc) ? bc.getAnnotationProvider() : 
b.config.getAnnotationProvider();
                hashCode = h(beanMeta, name);
        }
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanProxyInvocationHandler.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanProxyInvocationHandler.java
index be571d4962..56327347a8 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanProxyInvocationHandler.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanProxyInvocationHandler.java
@@ -131,7 +131,9 @@ public class BeanProxyInvocationHandler<T> implements 
InvocationHandler {
                                        return beanProps.equals(ih2.beanProps);
                                }
                        }
-                       return eq(beanProps, 
meta.getMarshallingContext().toBeanMap(arg));
+                       @SuppressWarnings("unchecked")
+                       var argMeta = (BeanMeta<Object>) 
BeanMeta.of(arg.getClass(), meta.getConfig());
+                       return eq(beanProps, BeanMap.of(arg, argMeta));
                }
 
                if (mi.hasName("hashCode") && mi.getParameterCount() == 0)
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MarshalledPropertyPostProcessor.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MarshalledPropertyPostProcessor.java
index d7638d1591..2265b8bd7e 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MarshalledPropertyPostProcessor.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MarshalledPropertyPostProcessor.java
@@ -80,6 +80,7 @@ final class MarshalledPropertyPostProcessor {
                                bdClasses.addAll(l(mp.dictionary()));
                        });
                        ap.find(Swap.class, 
b.innerField).stream().findFirst().ifPresent(x -> b.swap = swapSwap(x));
+                       b.isUri |= ap.has(Uri.class, b.innerField);
                }
 
                if (nn(b.getter)) {
@@ -90,6 +91,7 @@ final class MarshalledPropertyPostProcessor {
                                bdClasses.addAll(l(mp.dictionary()));
                        });
                        ap.find(Swap.class, b.getter).stream().forEach(x -> 
b.swap = swapSwap(x));
+                       b.isUri |= ap.has(Uri.class, b.getter);
                }
 
                if (nn(b.setter)) {
@@ -100,6 +102,7 @@ final class MarshalledPropertyPostProcessor {
                                bdClasses.addAll(l(mp.dictionary()));
                        });
                        ap.find(Swap.class, b.setter).stream().forEach(x -> 
b.swap = swapSwap(x));
+                       b.isUri |= ap.has(Uri.class, b.setter);
                }
 
                if (! bdClasses.isEmpty()) {
@@ -152,14 +155,18 @@ final class MarshalledPropertyPostProcessor {
                if (p.readTransform == null) {
                        p.readTransform = (session, o) -> {
                                try {
+                                       // The transform is typed against 
BeanSession (commons.bean SPI) but ObjectSwap.swap requires a
+                                       // MarshallingSession.  The 
marshalling-side BeanMap always wires a MarshallingSession into its
+                                       // transform call sites, so the 
narrowing cast is safe.
+                                       var ms = (MarshallingSession) session;
                                        if (nn(sw))
-                                               return sw.swap(session, o);
+                                               return sw.swap(ms, o);
                                        if (o == null)
                                                return null;
                                        if (rtm.hasChildSwaps()) {
                                                ObjectSwap f = 
rtm.getChildObjectSwapForSwap(o.getClass());
                                                if (nn(f))
-                                                       return f.swap(session, 
o);
+                                                       return f.swap(ms, o);
                                        }
                                        return o;
                                } catch (RuntimeException e) {
@@ -172,14 +179,16 @@ final class MarshalledPropertyPostProcessor {
                if (p.writeTransform == null) {
                        p.writeTransform = (session, o) -> {
                                try {
+                                       // See readTransform note: BeanSession 
→ MarshallingSession is safe on the marshalling-side path.
+                                       var ms = (MarshallingSession) session;
                                        if (nn(sw))
-                                               return sw.unswap(session, o, 
rtm);
+                                               return sw.unswap(ms, o, rtm);
                                        if (o == null)
                                                return null;
                                        if (rtm.hasChildSwaps()) {
                                                ObjectSwap f = 
rtm.getChildObjectSwapForUnswap(o.getClass());
                                                if (nn(f))
-                                                       return 
f.unswap(session, o, rtm);
+                                                       return f.unswap(ms, o, 
rtm);
                                        }
                                        return o;
                                } catch (RuntimeException e) {
diff --git a/todo/TODO-5-bean-runtime-types-to-commons.md 
b/todo/TODO-5-bean-runtime-types-to-commons.md
index eb62da62cb..f7eec1ef29 100644
--- a/todo/TODO-5-bean-runtime-types-to-commons.md
+++ b/todo/TODO-5-bean-runtime-types-to-commons.md
@@ -38,6 +38,101 @@ Build + full test green (`scripts/test.py --full`).
 
 ---
 
+## Status (Phase C Task 5 — Steps A-E1 landed, uncommitted)
+
+**Phase C Task 5 Steps A-E1 LANDED in the working tree (uncommitted).** Build 
+ targeted tests green. The bean-runtime cluster files are not yet moved (Steps 
G-J), but additional SPI decoupling is in place:
+
+### Steps completed in this checkpoint
+
+- **Step A — Two `((MarshallingContext) bc).X()` casts replaced with 
`BeanTypeResolver` SPI calls.**
+  - `BeanPropertyMeta.Builder.bc` and `BeanPropertyMeta.bc` instance fields 
retyped from `Object` to `BeanTypeResolver`. `MarshallingContext` implements 
`BeanTypeResolver`, so the marshalling-side construction path is unchanged.
+  - `Builder.rawMetaType(Class<?>)` now calls `bc.resolveType(null, 
info(value), null)` instead of `((MarshallingContext) bc).getClassMeta(value)`.
+  - `BeanPropertyMeta` constructor `ap` initialization now reads 
`bc.getAnnotationProvider()` directly without a `MarshallingContext` cast.
+
+- **Step B — `BiFunction<MarshallingSession,Object,Object>` retyped to 
`BiFunction<BeanSession,Object,Object>`.**
+  - `BeanPropertyMeta.Builder.readTransform` / `writeTransform` fields plus 
`BeanPropertyMeta.readTransform` / `writeTransform` instance fields and the 
corresponding Builder setter signatures all retyped to use the `BeanSession` 
SPI.
+  - Lambdas inside 
`MarshalledPropertyPostProcessor.installSwapAwareTransforms` now narrow 
`session` to `MarshallingSession` via a local `var ms = (MarshallingSession) 
session;` since `ObjectSwap.swap`/`ObjectSwap.unswap` require the 
marshalling-side session. Comment documents that the marshalling-side `BeanMap` 
always wires a `MarshallingSession`, so the narrowing cast is safe.
+
+- **Step C — `BeanProxyInvocationHandler.equals` routed off 
`meta.getMarshallingContext().toBeanMap(arg)`.**
+  - Replaced with `BeanMap.of(arg, (BeanMeta<Object>) 
BeanMeta.of(arg.getClass(), meta.getConfig()))` (the `BeanMap.of(T, 
BeanMeta<T>)` static factory shipped in Step 6).
+  - Equality semantics preserved: builds a fresh `BeanMeta` against the same 
`BeanConfigContext`, then compares property maps. No session is wired; equality 
only reads.
+
+- **Step D — `BeanMap.of(T)` static factory inlined.**
+  - Replaced `MarshallingContext.DEFAULT_SESSION.toBeanMap(bean)` with `new 
BeanMap<>(bean, BeanMeta.of((Class<T>) bean.getClass()))`.
+  - **Behavioral change:** The returned `BeanMap` no longer carries a 
`MarshallingSession`, so `ObjectSwap` transformations are not applied through 
`get`/`put`. The previous behavior was session-aware via `DEFAULT_SESSION`; the 
new behavior is bean-modeling-only. Verified by running `BeanMap_Test`, 
`BeanProxyInvocationHandler_Test`, `BeanMeta_Test` (all green) and the full 
`--build-only` check.
+
+- **Step E1 — `@Uri` annotation reads lifted from 
`BeanPropertyMeta.Builder.validate()` to 
`MarshalledPropertyPostProcessor.process()`.**
+  - The three `isUri |= ap.has(Uri.class, ifi/gi/si)` reads inside 
`validate()` are gone; the equivalent reads now live in the marshalling-side 
post-processor and update the same `b.isUri` flag (now package-private on the 
builder so the post-processor can write it).
+  - The `rawTypeMeta.isUri()` reads remain in `validate()` — they are 
bean-modeling concerns (`BeanTypeInfo.isUri()` is the commons SPI).
+
+### Build / test status
+
+- `python3 scripts/test.py --build-only` — **GREEN** after each step.
+- Targeted tests run (`BeanProxyInvocationHandler_Test`, `BeanMap_Test`, 
`BeanMeta_Test`, `transforms/BeanMap_Test`, `UriAnnotation_Test`) — all 86 
tests green.
+- Full test suite not re-run (per "incomplete-but-documented over 
broken-build" rule below).
+
+### Step F audit — remaining juneau-marshall coupling in the 7 files
+
+A full audit reveals the cluster is **not yet move-ready**. The 7 files still 
reference these `juneau-marshall` types:
+
+**`BeanMap.java`** still depends on:
+- `MarshallingSession` — held as the `private MarshallingSession session` 
field, returned from `getMarshallingSession()`, accepted by 
`setMarshallingSession(MarshallingSession)`. Used in `getBean(boolean)` for 
`session.convertToType(rawVal, cm)` (constructor-args path).
+- `ClassMeta` — used as `var cm = pm.getClassMeta()` in `getBean(boolean)` and 
via `meta.getClassMeta()` in Javadoc/error formatting.
+- `org.apache.juneau.annotation.*` (wildcard) — only used for Javadoc 
cross-references (`@Marshalled`, `@Swap`, `@MarshalledProp` etc.).
+- `org.apache.juneau.internal.*` — used for `FilteredKeyMap` (instantiated in 
`keySet()`). FilteredKeyMap itself depends on `ClassMeta`.
+- `org.apache.juneau.swap.*` — Javadoc-only references to `ObjectSwap`.
+
+**`BeanMapEntry.java`** still depends on:
+- `org.apache.juneau.annotation.*` — wildcard import. Need to audit whether 
any non-Javadoc reference survives.
+- `org.apache.juneau.swap.*` — Javadoc-only references.
+
+**`BeanMeta.java`** still depends on:
+- `org.apache.juneau.annotation.*` — actively reads `@Marshalled` (lines 226, 
232, 453, 1178) for bean detection, `typePropertyName`, and 
constructor-visibility relaxation. Reads `@Name` (~6 sites) for property-name 
resolution.
+- `Marshalled` annotation reads still need lifting into 
`MarshalledBeanMetaInitializer` (helper methods that take the 
`AnnotationProvider` + `ClassInfo` and return: (1) `isBean(...)`, (2) 
`typePropertyName(...)`, (3) `allowsPrivateConstructor(...)`).
+- `@Name` could either move to `commons.bean` (clean but ~26 files would need 
import updates) or stay in `juneau-marshall.annotation` and have its reads 
abstracted behind a marshalling-side helper.
+- `MarshalledBeanMetaInitializer.findMarshalledFilter(cm)` and 
`.classInfoOf(cm)`, etc. — already in place; bean-side path works without them.
+- `MarshalledPropertyPostProcessor.process((MarshallingContext) 
marshallingContext, p)` — called via cast; `marshallingContext` field is 
`Object`-typed already. The post-processor itself stays in juneau-marshall.
+- `MarshallingContext` — referenced only via the cast above plus three Javadoc 
cross-references.
+- `BeanRegistry` — narrowing cast inside `getBeanRegistry()` and 
`getPropertyBeanRegistry()`. Could stay marshalling-side-only since the 
bean-side type is the wider `BeanRegistryLookup`.
+- `MarshalledFilter` — narrowing cast inside `getMarshalledFilter()`. Same 
pattern.
+- `BeanProxyInvocationHandler` — instantiated in the 
`beanProxyInvocationHandler` supplier. Both types move together.
+
+**`BeanPropertyMeta.java`** still depends on:
+- `MarshallingSession` — parameter type on the private 
`setPropertyValue(BeanMap<?>, String, Object, Object, boolean, boolean, 
MarshallingSession)`. Method is invoked from `set(...)` with `session = 
m.getMarshallingSession()`. Retyping to `BeanSession` is mechanically 
straightforward (the `session.parseToMap` / `session.parseToList` / 
`session.convertToType` / `session.convertToMemberType` methods are already on 
`BeanSession`), but **the method body still casts `swap` to `ObjectSwap` at  
[...]
+- `ObjectSwap` — narrowing cast at line 1249 (`((ObjectSwap) 
swap).getSwapClass()`). Need to either: (a) extract this branch into a 
marshalling-side helper, (b) add a separate `Class<?> swapClass` field on the 
builder to avoid the cast, or (c) accept the cast lives at a narrow site that 
can stay `Object`-typed plus runtime reflection on a method reference.
+- `BeanInstantiator` — used in two sites inside `setPropertyValue` to build 
empty collections/maps. Lives in `commons.inject`, so it's already 
commons-side. **Re-checked: `BeanInstantiator` is in 
`org.apache.juneau.commons.inject`, NOT marshalling-side. No action needed.**
+- `ParseException` / `SerializeException` — caught/thrown inside 
`set`/`setPropertyValue`. Both live in `juneau-marshall.parser` / 
`juneau-marshall.serializer`. Move-blocker.
+- `BeanRegistry` — narrowing cast inside `getBeanRegistry()`. Stays 
marshalling-side.
+- `ClassMeta` — Javadoc cross-references only.
+- `Uri` — fully lifted (Step E1).
+- `Name` — Javadoc-only references after Step E1. Worth confirming with a grep 
before move.
+
+**`BeanPropertyValue.java`** — clean. Only `commons.*` imports.
+
+**`BeanPropertyConsumer.java`** — clean. Only `commons.*` imports.
+
+**`BeanProxyInvocationHandler.java`** — clean. Only commons static imports 
after Step C.
+
+### Why the move is not yet safe (summary)
+
+The two stubborn move-blockers are:
+
+1. **`BeanMap.session` typed as `MarshallingSession`** and the 
`getBean(boolean)` constructor-args path that calls `session.convertToType`. 
The field could be retyped to `BeanSession`, the public 
`getMarshallingSession()` removed/renamed to `getBeanSession()`, and the one 
external caller (`ParserSession` at line 902) adjusted to cast. That's still 
20-30 lines of mechanical work but introduces a public-API breaking change to 
`BeanMap`.
+2. **`BeanPropertyMeta.setPropertyValue(..., MarshallingSession session)`** 
retains an `(ObjectSwap) swap` cast inside the function body. Cleanest fix: 
capture the swap class as a side-data on the builder when 
`installSwapAwareTransforms` runs, replacing the cast with a `Class<?>` 
comparison. Mechanical but adds one more SPI field.
+
+Plus the secondary work:
+
+3. **`BeanMeta` `@Marshalled` reads** — three call sites need lift-out to 
`MarshalledBeanMetaInitializer`. Mechanical.
+4. **`@Name` handling** — either move to `commons.bean` (clean but ~26 file 
import-fixups) or hide behind a marshalling-side helper (extra plumbing for 
property-name resolution).
+5. **`FilteredKeyMap` relocation** — move to `commons.collections`, retype its 
`classMeta` field to `BeanTypeInfo`.
+6. **`ParseException` / `SerializeException` references in 
`BeanPropertyMeta`** — replace with `RuntimeException` rethrows or a 
commons-side `BeanRuntimeException` wrapper.
+
+### Next step recommendation
+
+Pick up the remaining SPI cleanup as a fresh checkpoint focused on items 1-6 
above. The cluster is much closer to move-ready than it was; the heavy lifts 
from Phase 5a/8a/8b are all in place. After the remaining items land, Steps G-J 
(the physical `git mv` + reference sweep + standalone compile verification) 
should be a couple of hours of mechanical work plus the import-fix wave.
+
+---
+
 ## Status (as of Phase C Tasks 1-2-3-4-4-deferred checkpoint, uncommitted)
 
 **Phase C Tasks 1, 2, 3, 4, 4-deferred LANDED (working tree, uncommitted).** 
Build + full test green. See "Phase C status" block under Step 8b-ii for full 
detail. Summary:

Reply via email to