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 834c64eca58b1b4162b3337edf89d407dc868dd0 Author: James Bognar <[email protected]> AuthorDate: Tue May 12 12:09:19 2026 -0400 refactor: drop MarshallingSession from BeanMap constructor; use transitional setter (TODO-5 Step 4) Co-authored-by: Cursor <[email protected]> --- .../src/main/java/org/apache/juneau/BeanMap.java | 31 +++++++++++++++++----- .../java/org/apache/juneau/BeanPropertyMeta.java | 13 +++++++-- .../java/org/apache/juneau/MarshallingSession.java | 8 ++++-- .../apache/juneau/internal/DelegateBeanMap.java | 3 ++- todo/TODO-5-bean-runtime-types-to-commons.md | 8 +++--- 5 files changed, 49 insertions(+), 14 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 24519be464..f3efd25e1d 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 @@ -95,24 +95,43 @@ public class BeanMap<T> extends AbstractMap<String,Object> implements Delegate<T /** The BeanMeta associated with the class of the object. */ protected BeanMeta<T> meta; - private final MarshallingSession session; + private MarshallingSession session; private final String typePropertyName; /** - * Instance of this class are instantiated through the MarshallingContext class. + * Constructor. + * + * <p> + * Bean-modeling-only constructor. Does not carry a {@link MarshallingSession} reference. + * The marshalling layer wires the session in via {@link #setMarshallingSession(MarshallingSession)} + * immediately after construction. * - * @param session The bean session object that created this bean map. * @param bean The bean to wrap inside this map. * @param meta The metadata associated with the bean class. */ - protected BeanMap(MarshallingSession session, T bean, BeanMeta<T> meta) { - this.session = session; + protected BeanMap(T bean, BeanMeta<T> meta) { this.bean = bean; this.meta = meta; if (ne(meta.getConstructorArgs())) propertyCache = new TreeMap<>(); - this.typePropertyName = session.getBeanTypePropertyName(meta.getClassMeta()); + this.typePropertyName = meta.getTypePropertyName(); + } + + /** + * Wires this bean map to a {@link MarshallingSession}. + * + * <p> + * Transitional API used by the marshalling layer (e.g. {@link MarshallingSession#toBeanMap(Object)}) + * to wire a session into a {@link BeanMap} immediately after construction. Required for any + * marshalling-side operation that depends on session-aware behavior (type conversion, child + * collection construction, etc.). Will be removed when {@link BeanMap} is fully decoupled from + * the marshalling layer (TODO-5 Step 5+). + * + * @param value The marshalling session that produced this bean map. + */ + protected void setMarshallingSession(MarshallingSession value) { + this.session = value; } /** 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 8bec99efa8..1c896d48e6 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 @@ -1297,7 +1297,7 @@ public class BeanPropertyMeta implements Comparable<BeanPropertyMeta> { if (o == null) return null; if (cm.isBean()) - return new BeanMap(session, o, new BeanMetaFiltered(cm.getBeanMeta(), properties)); + return newBeanMap(session, o, new BeanMetaFiltered(cm.getBeanMeta(), properties)); if (cm.isMap()) { var propsArray = properties == null ? null : properties.toArray(new String[0]); return new FilteredKeyMap(cm, (Map)o, propsArray); @@ -1309,11 +1309,20 @@ public class BeanPropertyMeta implements Comparable<BeanPropertyMeta> { } var bm = bc.getBeanMeta(o.getClass()); if (nn(bm)) - return new BeanMap(session, o, new BeanMetaFiltered(cm.getBeanMeta(), properties)); + return newBeanMap(session, o, new BeanMetaFiltered(cm.getBeanMeta(), properties)); } return o; } + @SuppressWarnings({ + "unchecked" // Type erasure requires unchecked cast for filtered bean map construction + }) + private static BeanMap newBeanMap(MarshallingSession session, Object o, BeanMetaFiltered meta) { + var bm = new BeanMap(o, meta); + bm.setMarshallingSession(session); + return bm; + } + @SuppressWarnings({ "java:S3776" // Cognitive complexity acceptable for inner property getter with delegate/swap handling }) 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 75cd894bea..15fe991f6d 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 @@ -1029,7 +1029,9 @@ public class MarshallingSession extends ContextSession implements ConverterSessi T bean = null; if (e(m.getConstructorArgs())) bean = newBean(outer, c); - return new BeanMap<>(this, bean, m); + var bm = new BeanMap<>(bean, m); + bm.setMarshallingSession(this); + return bm; } /** @@ -1126,7 +1128,9 @@ public class MarshallingSession extends ContextSession implements ConverterSessi BeanMeta m = cm.getBeanMeta(); if (m == null) throw bex(c, "Class is not a bean. Reason=''{0}''", cm.getNotABeanReason()); - return new BeanMap<>(this, o, m); + var bm = new BeanMap<>(o, m); + bm.setMarshallingSession(this); + return bm; } /** diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/DelegateBeanMap.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/DelegateBeanMap.java index 77e8b33cf8..4f2e776ff1 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/DelegateBeanMap.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/DelegateBeanMap.java @@ -64,7 +64,8 @@ public class DelegateBeanMap<T> extends BeanMap<T> { "unchecked" // Type erasure requires cast for BeanMap creation }) public DelegateBeanMap(T bean, MarshallingSession session) { - super(session, bean, session.getBeanMeta((Class<T>)bean.getClass())); + super(bean, session.getBeanMeta((Class<T>)bean.getClass())); + setMarshallingSession(session); } /** diff --git a/todo/TODO-5-bean-runtime-types-to-commons.md b/todo/TODO-5-bean-runtime-types-to-commons.md index 6cf99c7b34..f42ce844f0 100644 --- a/todo/TODO-5-bean-runtime-types-to-commons.md +++ b/todo/TODO-5-bean-runtime-types-to-commons.md @@ -4,14 +4,16 @@ This is the remaining work from **Phase 5 of the bean-layer split**. Phase 5a (t --- -## Status (as of Phase 5c checkpoint) +## Status (as of Phase 5d checkpoint) + +**Step 4 complete.** `BeanMap` no longer takes a `MarshallingSession` in its constructor. Picked **Option (c)** (transitional setter) per the plan — minimum-disturbance and no behavioral change. The `private final MarshallingSession session` field became `private MarshallingSession session` (no longer final, defaults to null), the constructor signature dropped to `BeanMap(T bean, BeanMeta<T> meta)`, and a new `protected void setMarshallingSession(MarshallingSession value)` is called by t [...] **Step 3 complete.** `BeanPropertyMeta.get`/`set` no longer call `ObjectSwap.swap`/`unswap` directly. The class now carries two install-time `BiFunction<MarshallingSession,Object,Object>` callbacks (`readTransform`/`writeTransform`) that default to identity. `BeanMeta` installs swap-aware closures via a new private helper `installSwapAwareTransforms(BeanPropertyMeta.Builder)` immediately after `Builder.validate()` succeeds (only when `Builder.swap != null` or `Builder.rawTypeMeta.hasChil [...] - [x] **Step 1** — `BeanConfigContext` POJO + builder in `commons.bean`. Carries: visibility settings, all `beans*Require*` toggles, `findFluentSetters`, `unsortedProperties`, `useInterfaceProxies`, `useJavaBeanIntrospector`, `ignoreMissingSetters`, `ignoreTransientFields`, `ignoreUnknownBeanProperties`, `propertyNamer`, `beanTypePropertyName`, `notBeanPackageNames` / `notBeanPackagePrefixes` / `notBeanClasses`, `BeanStore`, `AnnotationProvider`, optional `Predicate<ClassInfo>` override [...] - [x] **Step 2** — Replaced `ClassMeta` with `ClassInfo` for pure-reflection access inside `BeanMeta`. Added a `classInfo` field (a re-typed view of the same instance as `classMeta`, since `ClassMeta extends ClassInfoTyped extends ClassInfo`) and routed all reflection calls (`inner()`, `isMemberClass()`, `isNotStatic()`, `isAnonymousClass()`, `isRecord()`, `isInterface()`, `getRecordComponents()`, `getName()`, `getParentsAndInterfaces()`, `getPublicConstructors()`, `getDeclaredConstructo [...] - [x] **Step 3** — Removed swap-aware `get`/`set` from `BeanPropertyMeta`. Picked option (a) (pluggable callbacks). Added `BiFunction<MarshallingSession,Object,Object>` `readTransform` / `writeTransform` fields with identity defaults; exposed corresponding `Builder.readTransform(...)` / `Builder.writeTransform(...)` setters. The bean-modeling `get`/`set` paths inside `BeanPropertyMeta` no longer call `ObjectSwap.swap` / `ObjectSwap.unswap` directly — instead they invoke the installed tra [...] -- [ ] **Step 4** — Remove `MarshallingSession` back-pointer from `BeanMap`. After Step 3, `BeanMap.get/put` are raw property reads/writes; `MarshallingSession.toBeanMap` wraps a `BeanMap` for serialization and applies swaps externally. +- [x] **Step 4** — Removed `MarshallingSession` from the `BeanMap` constructor signature (Option c — transitional setter). `BeanMap` now exposes `setMarshallingSession(MarshallingSession)` that the marshalling layer wires in immediately after construction. The `session` field defaults to null on direct construction; only `BeanMap.getBean()` (for read-only beans with constructor args), `BeanPropertyMeta.add`/`set`, and child-properties-filter operations need it set, and they all go throug [...] - [ ] **Step 5** — Remove `BeanRegistry` field from `BeanPropertyMeta`. Lift dictionary metadata into a marshalling-side companion (`MarshalledPropertyMeta` or a side-map keyed by `BeanPropertyMeta`). - [ ] **Step 6** — `BeanMeta` becomes constructible by both `ClassMeta` and direct `commons.bean` callers via `BeanMeta.of(MyClass.class, BeanConfigContext.DEFAULT)`. `ClassMeta` becomes a *consumer* of `BeanMeta` rather than its creator. - [ ] **Step 7** — Re-check whether `ExtendedBeanMeta` and per-format extensions (`XmlBeanMeta`, `RdfBeanMeta`, `HtmlBeanMeta`) need to follow `BeanMeta` to `commons.bean`. Default expectation: they stay in `juneau-marshall`. @@ -19,7 +21,7 @@ This is the remaining work from **Phase 5 of the bean-layer split**. Phase 5a (t - [ ] **Step 9** — Reference sweep: 80–120 unique files (mostly inside `juneau-marshall`). Update imports, Javadoc `{@link …}` references, package-info docs. - [ ] **Step 10** — Update `juneau-docs` release notes / migration guide (`docs/pages/release-notes/9.5.0.md`, `## Package Moves` section) with the bean-runtime relocations. -The "incomplete-but-documented over broken-build" rule from Phase 5a still applies. When picking up the next slice of this work, **Step 4 is the recommended next checkpoint** — Step 3 made `BeanPropertyMeta.get`/`set` raw (modulo installed callback), so the next blocker is the `MarshallingSession` back-pointer carried by `BeanMap` and the parallel swap-application sites currently inside `BeanMap` (none today on the read path — `BeanMap.get` just delegates to `BeanPropertyMeta.get` — but [...] +The "incomplete-but-documented over broken-build" rule from Phase 5a still applies. When picking up the next slice of this work, **Step 5 is the recommended next checkpoint** — Step 4 dropped the constructor coupling but the `BeanMap.session` field is still read by `BeanPropertyMeta.add` / `BeanPropertyMeta.set` / `applyChildPropertiesFilter` (for `convertToType` / `JsonList(session)` / `JsonMap(session)` construction) and a transitional `BeanMap.getMarshallingSession()` accessor still s [...] ---
