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 c9f7601485d1dfd1c424da4de3eabcbc16edd6b6
Author: James Bognar <[email protected]>
AuthorDate: Tue May 12 11:37:54 2026 -0400

    refactor: replace ClassMeta with ClassInfo in BeanMeta/BeanPropertyMeta 
(TODO-5 Step 2)
    
    Co-authored-by: Cursor <[email protected]>
---
 .../src/main/java/org/apache/juneau/BeanMeta.java  | 48 +++++++++++-----------
 .../java/org/apache/juneau/BeanPropertyMeta.java   | 15 +++++++
 todo/TODO-5-bean-runtime-types-to-commons.md       |  4 +-
 3 files changed, 42 insertions(+), 25 deletions(-)

diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java
index fc12d17631..f464590b26 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java
@@ -361,6 +361,7 @@ public class BeanMeta<T> {
        private final Supplier<BeanRegistry> beanRegistry;                      
   // The bean registry for this bean.
        private final Supplier<List<ClassInfo>> classHierarchy;                 
   // List of all classes traversed in the class hierarchy.
        private final ClassMeta<T> classMeta;                                   
   // The target class type that this meta object describes.
+       private final ClassInfo classInfo;                                      
   // Pure-reflection view of the bean class (Step 2 of TODO-5 — decouples bean 
modeling from ClassMeta).
        private final Supplier<String> dictionaryName;                          
   // The @Marshalled(typeName) annotation defined on this bean class.
        private final BeanPropertyMeta dynaProperty;                            
   // "extras" property.
        @SuppressWarnings("rawtypes")
@@ -405,6 +406,7 @@ public class BeanMeta<T> {
        })
        protected BeanMeta(ClassMeta<T> cm, MarshalledFilter bf, String[] 
pNames, ClassInfo implClass) {
                classMeta = cm;
+               classInfo = cm;
                marshallingContext = cm.getMarshallingContext();
                beanFilter = bf;
                implClassConstructor = opt(implClass).map(x -> 
x.getPublicConstructor(x2 -> x2.hasNumParameters(0)).orElse(null)).orElse(null);
@@ -416,8 +418,8 @@ public class BeanMeta<T> {
 
                // Local variables for initialization
                var ap = marshallingContext.getAnnotationProvider();
-               var c = cm.inner();
-               var ci = cm;
+               var c = classInfo.inner();
+               var ci = classInfo;
                String notABeanReasonTemp = null;
                var propertiesValue = 
Value.<Map<String,BeanPropertyMeta>>empty();
                var hiddenPropertiesMap = 
CollectionUtils.<String,BeanPropertyMeta>map();
@@ -446,7 +448,7 @@ public class BeanMeta<T> {
                        fixedBeanProps.forEach(x -> normalProps.put(x, 
BeanPropertyMeta.builder(this, x)));
 
                        if (marshallingContext.isUseJavaBeanIntrospector()) {
-                               var c2 = bfo.map(x -> 
x.getInterfaceClass()).filter(Objects::nonNull).orElse(classMeta);
+                               var c2 = bfo.map(x -> 
x.getInterfaceClass()).filter(Objects::nonNull).orElse(classInfo);
                                BeanInfo bi = null;
                                if (! c2.isInterface())
                                        bi = 
Introspector.getBeanInfo(c2.inner(), stopClass.inner());
@@ -605,9 +607,9 @@ public class BeanMeta<T> {
                setterProps = u(setterPropsMap);
                dynaProperty = dynaPropertyValue.get();
                unsortedProperties = unsortedPropertiesTemp;
-               typeProperty = BeanPropertyMeta.builder(this, 
typePropertyName).canRead().canWrite().rawMetaType(marshallingContext.string()).beanRegistry(beanRegistry.get()).build();
+               typeProperty = BeanPropertyMeta.builder(this, 
typePropertyName).canRead().canWrite().rawMetaType(String.class).beanRegistry(beanRegistry.get()).build();
                dictionaryName = memoize(this::findDictionaryName);
-               beanProxyInvocationHandler = 
memoize(()->marshallingContext.isUseInterfaceProxies() && c.isInterface() ? new 
BeanProxyInvocationHandler<>(this) : null);
+               beanProxyInvocationHandler = memoize(() -> 
marshallingContext.isUseInterfaceProxies() && classInfo.isInterface() ? new 
BeanProxyInvocationHandler<>(this) : null);
                var factoryClassTemp = btList.stream().map(x -> 
x.inner().factory()).filter(x -> x != 
org.apache.juneau.commons.function.BeanFactory.Void.class).findFirst().orElse(null);
                factoryClass = factoryClassTemp;
        }
@@ -638,7 +640,7 @@ public class BeanMeta<T> {
 
        @Override /* Overridden from Object */
        public boolean equals(Object o) {
-               return (o instanceof BeanMeta<?> o2) && eq(this, o2, (x, y) -> 
eq(x.classMeta, y.classMeta));
+               return (o instanceof BeanMeta<?> o2) && eq(this, o2, (x, y) -> 
eq(x.classInfo, y.classInfo));
        }
 
        /**
@@ -760,7 +762,7 @@ public class BeanMeta<T> {
 
        @Override /* Overridden from Object */
        public int hashCode() {
-               return classMeta.hashCode();
+               return classInfo.hashCode();
        }
 
        /**
@@ -796,7 +798,7 @@ public class BeanMeta<T> {
        protected FluentMap<String,Object> properties() {
                // @formatter:off
                return filteredBeanPropertyMap()
-                       .a(PROP_class, classMeta.getName())
+                       .a(PROP_class, classInfo.getName())
                        .a(PROP_properties, properties);
                // @formatter:on
        }
@@ -953,16 +955,16 @@ public class BeanMeta<T> {
                                throw new ExecutableException(e);
                        }
                }
-               if (classMeta.isMemberClass() && classMeta.isNotStatic()) {
+               if (classInfo.isMemberClass() && classInfo.isNotStatic()) {
                        if (hasConstructor())
                                return getConstructor().<T>newInstance(outer);
                } else {
                        if (hasConstructor())
                                return getConstructor().<T>newInstance();
-                       var h = classMeta.getProxyInvocationHandler();
+                       var h = beanProxyInvocationHandler.get();
                        if (nn(h)) {
-                               var cl = classMeta.getClassLoader();
-                               return (T)Proxy.newProxyInstance(cl, 
a(classMeta.inner(), java.io.Serializable.class), h);
+                               var inner = classInfo.inner();
+                               return 
(T)Proxy.newProxyInstance(inner.getClassLoader(), a(inner, 
java.io.Serializable.class), h);
                        }
                }
                return null;
@@ -1024,7 +1026,7 @@ public class BeanMeta<T> {
        private BeanConstructor findBeanConstructor() {
                var ap = marshallingContext.getAnnotationProvider();
                var vis = marshallingContext.getBeanConstructorVisibility();
-               var ci = classMeta;
+               var ci = classInfo;
 
                var l = ci.getPublicConstructors().stream().filter(x -> 
ap.has(BeanCtor.class, x)).toList();
                if (l.isEmpty())
@@ -1057,8 +1059,8 @@ public class BeanMeta<T> {
                if (implClassConstructor != null)
                        return new 
BeanConstructor(opt(implClassConstructor.accessible()), liste());
 
-               var ba = ap.find(Marshalled.class, classMeta);
-               var btList = 
ap.find(org.apache.juneau.commons.bean.BeanType.class, classMeta);
+               var ba = ap.find(Marshalled.class, classInfo);
+               var btList = 
ap.find(org.apache.juneau.commons.bean.BeanType.class, classInfo);
                var con = ci.getNoArgConstructor((! ba.isEmpty() || ! 
btList.isEmpty()) ? Visibility.PRIVATE : vis).orElse(null);
                if (con != null)
                        return new BeanConstructor(opt(con.accessible()), 
liste());
@@ -1109,9 +1111,9 @@ public class BeanMeta<T> {
                var v = marshallingContext.getBeanFieldVisibility();
                var noIgnoreTransients = ! 
marshallingContext.isIgnoreTransientFields();
                var ap = marshallingContext.getAnnotationProvider();
-               var isRecord = classMeta.isRecord();
+               var isRecord = classInfo.isRecord();
                var recordComponentNames = isRecord
-                       ? 
classMeta.getRecordComponents().stream().map(java.lang.reflect.RecordComponent::getName).collect(java.util.stream.Collectors.toSet())
+                       ? 
classInfo.getRecordComponents().stream().map(java.lang.reflect.RecordComponent::getName).collect(java.util.stream.Collectors.toSet())
                        : Set.<String>of();
                // @formatter:off
                return classHierarchy.get().stream()
@@ -1176,7 +1178,7 @@ public class BeanMeta<T> {
        private List<BeanMethod> findBeanMethods() {
                var l = new LinkedList<BeanMethod>();
                var ap = marshallingContext.getAnnotationProvider();
-               var ci = classMeta;
+               var ci = classInfo;
                var v = marshallingContext.getBeanMethodVisibility();
                var pn = opt(beanFilter).map(x -> 
x.getPropertyNamer()).orElse(marshallingContext.getPropertyNamer());
                var suppressedFromBeanIgnoredFields = 
findSuppressedPropertyNamesFromIgnoredFields(pn);
@@ -1313,8 +1315,8 @@ public class BeanMeta<T> {
                var beanDictionaryClasses = opt(beanFilter).map(x -> new 
ArrayList<>(x.getBeanDictionary())).orElse(new ArrayList<>());
 
                // Bean dictionary from @Marshalled(typeName) annotation.
-               var ba = 
marshallingContext.getAnnotationProvider().find(Marshalled.class, classMeta);
-               ba.stream().map(x -> 
x.inner().typeName()).filter(Utils::ne).findFirst().ifPresent(x -> 
beanDictionaryClasses.add(classMeta));
+               var ba = 
marshallingContext.getAnnotationProvider().find(Marshalled.class, classInfo);
+               ba.stream().map(x -> 
x.inner().typeName()).filter(Utils::ne).findFirst().ifPresent(x -> 
beanDictionaryClasses.add(classInfo));
 
                return new BeanRegistry(marshallingContext, null, 
beanDictionaryClasses);
        }
@@ -1349,7 +1351,7 @@ public class BeanMeta<T> {
                var result = new LinkedList<ClassInfo>();
                // If @Marshalled.interfaceClass is specified on the parent 
class, then we want
                // to use the properties defined on that class, not the 
subclass.
-               var c2 = (nn(beanFilter) && nn(beanFilter.getInterfaceClass()) 
? beanFilter.getInterfaceClass() : classMeta);
+               var c2 = (nn(beanFilter) && nn(beanFilter.getInterfaceClass()) 
? beanFilter.getInterfaceClass() : classInfo);
                findClassHierarchy(c2, stopClass, result::add);
                return u(result);
        }
@@ -1420,7 +1422,7 @@ public class BeanMeta<T> {
                                return s;
                }
 
-               var n = classMeta
+               var n = classInfo
                        .getParentsAndInterfaces()
                        .stream()
                        .skip(1)
@@ -1435,7 +1437,7 @@ public class BeanMeta<T> {
                if (n != null)
                        return n;
 
-               return 
classMeta.getMarshallingContext().getAnnotationProvider().find(Marshalled.class,
 classMeta)
+               return 
marshallingContext.getAnnotationProvider().find(Marshalled.class, classInfo)
                        .stream()
                        .map(AnnotationInfo::inner)
                        .filter(x -> ! x.typeName().isEmpty())
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 72f1a580fc..1d749a4bc4 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
@@ -166,6 +166,21 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
                        return this;
                }
 
+               /**
+                * 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.
+                *
+                * @param value The raw metadata type for this bean property.
+                * @return This object.
+                */
+               public Builder rawMetaType(Class<?> value) {
+                       return 
rawMetaType(bc.getClassMeta(assertArgNotNull(ARG_value, value)));
+               }
+
                private static ObjectSwap 
marshalledPropSwap(AnnotationInfo<MarshalledProp> ai) {
                        var p = ai.inner();
                        if (! p.format().isEmpty())
diff --git a/todo/TODO-5-bean-runtime-types-to-commons.md 
b/todo/TODO-5-bean-runtime-types-to-commons.md
index b086acfdbe..1fc5b3b08a 100644
--- a/todo/TODO-5-bean-runtime-types-to-commons.md
+++ b/todo/TODO-5-bean-runtime-types-to-commons.md
@@ -9,7 +9,7 @@ This is the remaining work from **Phase 5 of the bean-layer 
split**. Phase 5a (t
 **Step 1 complete.** A `BeanConfigContext` POJO + builder now lives in 
`commons.bean`; `MarshallingContext.getBeanConfigContext()` returns a memoized 
snapshot view. The eight runtime types still live in `juneau-marshall` and 
still use `MarshallingContext` directly — Step 1 is purely additive 
infrastructure that future steps can lean on.
 
 - [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  
[...]
-- [ ] **Step 2** — Replace `ClassMeta` with `ClassInfo` in `BeanMeta` / 
`BeanPropertyMeta`. Most `cm.*` calls (`isAnonymousClass`, `isMemberClass`, 
`isAssignableTo`, `getModifiers`, `getRecordComponents`, `inner`, …) are pure 
reflection that already exists on `ClassInfo`. Two outliers — 
`cm.getProxyInvocationHandler()` (replace with a `BeanConfigContext` hook or 
move proxy creation into `BeanMeta`) and `cm.getMarshallingContext().string()` 
(use a plain `Class<String>`/`ClassInfo`).
+- [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 [...]
 - [ ] **Step 3** — Remove swap-aware `get/set` from `BeanPropertyMeta`. Add 
identity-default `BiFunction<Object,Object,Object>` callbacks (or a small 
`BeanPropertyTransform` SPI) so the marshalling layer installs swap-aware 
behavior at session construction.
 - [ ] **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.
 - [ ] **Step 5** — Remove `BeanRegistry` field from `BeanPropertyMeta`. Lift 
dictionary metadata into a marshalling-side companion (`MarshalledPropertyMeta` 
or a side-map keyed by `BeanPropertyMeta`).
@@ -19,7 +19,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 2 is the recommended 
next checkpoint — it removes one of the two big blockers (`ClassMeta` coupling) 
without yet attempting the swap/registry/session decoupling that requires 
reworking serializer/parser code paths.
+The "incomplete-but-documented over broken-build" rule from Phase 5a still 
applies. When picking up the next slice of this work, Step 3 is the recommended 
next checkpoint — Step 2 removed the general `ClassMeta` reflection coupling, 
so the next blocker is the swap-aware `get`/`set` paths in `BeanPropertyMeta` 
(and the associated `rawTypeMeta` / `typeMeta` / `ObjectSwap` / `BeanRegistry` 
fields that Step 2 intentionally left in place).
 
 ---
 

Reply via email to