This is an automated email from the ASF dual-hosted git repository.

jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git


The following commit(s) were added to refs/heads/master by this push:
     new 3ebddbf460 Marshall module improvements
3ebddbf460 is described below

commit 3ebddbf46036456347fec1d15661b54ebd38e560
Author: James Bognar <[email protected]>
AuthorDate: Thu Dec 11 15:12:21 2025 -0500

    Marshall module improvements
---
 TODO.md                                            |  50 +------
 .../juneau/commons/utils/AssertionUtils.java       |   2 -
 .../juneau/commons/utils/ThrowableUtils.java       |   1 +
 .../src/main/java/org/apache/juneau/BeanMeta.java  |   7 +-
 .../java/org/apache/juneau/BeanPropertyMeta.java   | 160 +++++++++++++++------
 .../main/java/org/apache/juneau/BeanSession.java   |   5 +
 .../apache/juneau/internal/DelegateBeanMap.java    |   2 +-
 7 files changed, 129 insertions(+), 98 deletions(-)

diff --git a/TODO.md b/TODO.md
index a928b0298f..18c6c1eea3 100644
--- a/TODO.md
+++ b/TODO.md
@@ -1,48 +1,4 @@
-# TODO List
+# TODO
 
-**Last generated TODO number: TODO-94**
-
-This file tracks pending tasks for the Apache Juneau project. For completed 
items, see [TODO-completed.md](TODO-completed.md).
-
-## Issues to Fix
-
-- [ ] TODO-3 Figure out why CallLogger and ThrownStore objects are not 
automatically injected into REST classes in spring boot.
-
-## Code Quality Improvements
-
-- [ ] TODO-5 Fields should be alphabetized.
-- [ ] TODO-6 Investigate if there are any other W3 or RFC specifications that 
would make good candidates for new bean modules.
-- [ ] TODO-12 Tests for Spring Boot testing.
-- [ ] TODO-14 The name parameter on annotations like Query when used on method 
parameters should be optional if parameter names are persisted in the bytecode.
-- [x] TODO-15 It appears StringUtils is going to become a commonly-used 
external class. Let's see if we can enhance it with commonly used string 
utility methods.
-- [ ] TODO-27 Determine if there are any other good candidates for 
Stringifiers and Listifiers.
-- [ ] TODO-29 Finish setting up SonarQube analysis in git workflow.
-- [ ] TODO-54 Search for places in code where Calendar should be replaced with 
ZonedDateTime.
-- [ ] TODO-90 Investigate replacing `StringUtils.parseIsoCalendar()` with 
java.time APIs and removing the helper if possible.
-- [ ] TODO-92 Investigate if `ClassInfo.asSubclass(Class<U>)` can return a 
`ClassInfoTyped<U>` object instead of `ClassInfo` for better type safety.
-- [ ] TODO-93 Investigate if `ReflectionUtils.info(Class<?>)` should return a 
`ClassInfoTyped` object instead of `ClassInfo` for better type safety.
-
-## Framework Improvements
-
-- [x] TODO-19 ClassInfo improvements to getMethod (e.g. getMethodExact vs 
getMethod).
-- [ ] TODO-21 Thrown NotFound causes - javax.servlet.ServletException: Invalid 
method response: 200
-- [x] TODO-89 Add ClassInfoTyped
-- [ ] TODO-91 Security: LogsResource returns HTTP 500 instead of 404 for 
malformed query parameters (CWE-74). When accessing log file URLs with encoded 
special characters in query parameters (e.g., `?method=VIEW%5C%5C%5C%22`), the 
system returns HTTP 500 "Invalid method response: 200" instead of HTTP 404. The 
error suggests it's incorrectly trying to find a Java method matching a 
malformed path. Should return 404 for invalid/malformed requests.
-- [ ] TODO-94 Add a "cloaked" mode to IRS to always return 404s in place of 
40x/50x responses.
-
-## HTTP Response/Exception Improvements
-
-- [ ] TODO-22 HttpResponse should use list of Headers and have a 
headers(Header...) method.
-- [ ] TODO-23 HttpResponse should allow you to set code.
-- [ ] TODO-24 HttpException subclasses can set status, but does it use code?
-- [ ] TODO-25 HttpException should use list of Headers and have a 
headers(Header...) method.
-
-- [ ] TODO-26 @ResponseBody and @ResponseHeaders shouldn't be required on 
HttpResponse objects.
-
-## Notes
-
-This TODO list tracks specific issues that need to be addressed in the Juneau 
project.
-
-## Website/Docs
-
-- [ ] TODO-29 Add searching to website using Algolia DocSearch.
+- Find all places where we have system properties defined for juneau and 
convert them to use the new Settings class.
+- Document "juneau.enableVerboseExceptions" setting.
diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/utils/AssertionUtils.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/utils/AssertionUtils.java
index 3e48330236..30f2cf3612 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/utils/AssertionUtils.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/utils/AssertionUtils.java
@@ -19,8 +19,6 @@ package org.apache.juneau.commons.utils;
 import static org.apache.juneau.commons.utils.ThrowableUtils.*;
 import static org.apache.juneau.commons.utils.Utils.*;
 
-import java.util.concurrent.atomic.*;
-
 /**
  * Utility methods for argument validation and assertion.
  *
diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/utils/ThrowableUtils.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/utils/ThrowableUtils.java
index 7621517243..cec04b04de 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/utils/ThrowableUtils.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/utils/ThrowableUtils.java
@@ -31,6 +31,7 @@ import org.apache.juneau.commons.settings.*;
 public class ThrowableUtils {
 
        static AtomicBoolean VERBOSE = new 
AtomicBoolean(Settings.get().getBoolean("juneau.enableVerboseExceptions").orElse(false));
+//     static AtomicBoolean VERBOSE = new AtomicBoolean(true);
 
        /**
         * Interface used with {@link 
Utils#safeSupplier(SupplierWithThrowable)}.
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 eba30e0626..5be5b93fa3 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
@@ -495,7 +495,7 @@ public class BeanMeta<T> {
                                var p = i.next();
                                try {
                                        if (p.field == null)
-                                               
p.setInnerField(findInnerBeanField(p.name));
+                                               
findInnerBeanField(p.name).ifPresent(x -> p.setInnerField(x));
 
                                        if (p.validate(beanContext, 
beanRegistry.get(), typeVarImpls, readOnlyProps, writeOnlyProps)) {
 
@@ -1349,7 +1349,7 @@ public class BeanMeta<T> {
         * @return The {@link FieldInfo} for the field if found, or 
<jk>null</jk> if no matching field exists
         *      in the class hierarchy.
         */
-       private FieldInfo findInnerBeanField(String name) {
+       private Optional<FieldInfo> findInnerBeanField(String name) {
                var noIgnoreTransients = ! 
beanContext.isIgnoreTransientFields();
                var ap = beanContext.getAnnotationProvider();
 
@@ -1362,8 +1362,7 @@ public class BeanMeta<T> {
                                        && ! ap.has(BeanIgnore.class, x)
                                        && x.hasName(name)
                        ).stream())
-                       .findFirst()
-                       .orElse(null);
+                       .findFirst();
                // @formatter:on
        }
 }
\ No newline at end of file
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 2929add051..12a2ffd3e9 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
@@ -18,6 +18,7 @@ package org.apache.juneau;
 
 import static org.apache.juneau.commons.reflect.AnnotationTraversal.*;
 import static org.apache.juneau.commons.reflect.ReflectionUtils.*;
+import static org.apache.juneau.commons.utils.AssertionUtils.*;
 import static org.apache.juneau.commons.utils.ClassUtils.*;
 import static org.apache.juneau.commons.utils.CollectionUtils.*;
 import static org.apache.juneau.commons.utils.StringUtils.*;
@@ -88,6 +89,7 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
                 * @return This object.
                 */
                public Builder beanRegistry(BeanRegistry value) {
+                       assertArgNotNull("value", value);
                        this.beanRegistry = value;
                        return this;
                }
@@ -106,6 +108,7 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
                 * @return This object.
                 */
                public Builder delegateFor(BeanPropertyMeta value) {
+                       assertArgNotNull("value", value);
                        this.delegateFor = value;
                        return this;
                }
@@ -128,6 +131,7 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
                 * @return This object.
                 */
                public Builder rawMetaType(ClassMeta<?> value) {
+                       assertArgNotNull("value", value);
                        this.rawTypeMeta = value;
                        this.typeMeta = rawTypeMeta;
                        return this;
@@ -156,60 +160,128 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
                        }
                        if (ci.isChildOf(Surrogate.class))
                                throw unsupportedOp("TODO - Surrogate swaps not 
yet supported on bean properties.");
-                       throw rex("Invalid class used in @Swap annotation.  
Must be a subclass of ObjectSwap or Surrogate. {0}", cn(c));
-               }
+               throw rex("Invalid class used in @Swap annotation.  Must be a 
subclass of ObjectSwap or Surrogate. {0}", cn(c));
+       }
 
-               Builder canRead() {
-                       this.canRead = true;
-                       return this;
-               }
+       /**
+        * Marks this property as readable.
+        *
+        * @return This object.
+        */
+       public Builder canRead() {
+               this.canRead = true;
+               return this;
+       }
 
-               Builder canWrite() {
-                       this.canWrite = true;
-                       return this;
-               }
+       /**
+        * Marks this property as writable.
+        *
+        * @return This object.
+        */
+       public Builder canWrite() {
+               this.canWrite = true;
+               return this;
+       }
 
-               BeanPropertyMeta.Builder setAsConstructorArg() {
-                       this.isConstructorArg = true;
-                       return this;
-               }
+       /**
+        * Marks this property as a constructor argument.
+        *
+        * @return This object.
+        */
+       public BeanPropertyMeta.Builder setAsConstructorArg() {
+               this.isConstructorArg = true;
+               return this;
+       }
 
-               BeanPropertyMeta.Builder setExtraKeys(Method extraKeys) {
-                       setAccessible(extraKeys);
-                       this.extraKeys = extraKeys;
-                       return this;
-               }
+       /**
+        * Sets the extra keys method for this bean property.
+        *
+        * @param value The method that returns extra keys for this property.
+        * @return This object.
+        */
+       public BeanPropertyMeta.Builder setExtraKeys(Method value) {
+               assertArgNotNull("value", value);
+               setAccessible(value);
+               this.extraKeys = value;
+               return this;
+       }
 
-               BeanPropertyMeta.Builder setField(Field field) {
-                       setAccessible(field);
-                       this.field = field;
-                       this.innerField = field;
-                       return this;
-               }
+       /**
+        * Sets the field for this bean property.
+        *
+        * @param value The field for this bean property.
+        * @return This object.
+        */
+       public BeanPropertyMeta.Builder setField(Field value) {
+               assertArgNotNull("value", value);
+               setAccessible(value);
+               this.field = value;
+               this.innerField = value;
+               return this;
+       }
 
-               BeanPropertyMeta.Builder setGetter(Method getter) {
-                       setAccessible(getter);
-                       this.getter = getter;
-                       return this;
-               }
+       /**
+        * Sets the getter method for this bean property.
+        *
+        * @param value The getter method for this bean property.
+        * @return This object.
+        */
+       public BeanPropertyMeta.Builder setGetter(Method value) {
+               assertArgNotNull("value", value);
+               setAccessible(value);
+               this.getter = value;
+               return this;
+       }
 
-               BeanPropertyMeta.Builder setInnerField(FieldInfo innerField) {
-                       this.innerField = innerField == null ? null : 
innerField.inner();
-                       return this;
-               }
+       /**
+        * Sets the inner field for this bean property from a {@link FieldInfo}.
+        *
+        * @param value The field info containing the inner field.
+        * @return This object.
+        */
+       public BeanPropertyMeta.Builder setInnerField(FieldInfo value) {
+               assertArgNotNull("value", value);
+               this.innerField = value == null ? null : value.inner();
+               return this;
+       }
 
-               BeanPropertyMeta.Builder setInnerField(Field innerField) {
-                       this.innerField = innerField;
-                       return this;
-               }
+       /**
+        * Sets the inner field for this bean property.
+        *
+        * @param value The inner field for this bean property.
+        * @return This object.
+        */
+       public BeanPropertyMeta.Builder setInnerField(Field value) {
+               assertArgNotNull("value", value);
+               this.innerField = value;
+               return this;
+       }
 
-               BeanPropertyMeta.Builder setSetter(Method setter) {
-                       setAccessible(setter);
-                       this.setter = setter;
-                       return this;
-               }
+       /**
+        * Sets the setter method for this bean property.
+        *
+        * @param value The setter method for this bean property.
+        * @return This object.
+        */
+       public BeanPropertyMeta.Builder setSetter(Method value) {
+               assertArgNotNull("value", value);
+               setAccessible(value);
+               this.setter = value;
+               return this;
+       }
 
-               boolean validate(BeanContext bc, BeanRegistry 
parentBeanRegistry, Map<Class<?>,Class<?>[]> typeVarImpls, Set<String> bpro, 
Set<String> bpwo) throws Exception {
+       /**
+        * Validates this bean property configuration.
+        *
+        * @param bc The bean context.
+        * @param parentBeanRegistry The parent bean registry.
+        * @param typeVarImpls Type variable implementations.
+        * @param bpro Bean properties read-only set.
+        * @param bpwo Bean properties write-only set.
+        * @return <jk>true</jk> if this property is valid, <jk>false</jk> 
otherwise.
+        * @throws Exception If validation fails.
+        */
+       public boolean validate(BeanContext bc, BeanRegistry 
parentBeanRegistry, Map<Class<?>,Class<?>[]> typeVarImpls, Set<String> bpro, 
Set<String> bpwo) throws Exception {
 
                        var bdClasses = list();
                        var ap = bc.getAnnotationProvider();
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanSession.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanSession.java
index de7c08f462..c6ee73707c 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanSession.java
@@ -300,6 +300,11 @@ public class BeanSession extends ContextSession {
                return ctx._class();
        }
 
+       /**
+        * Returns the annotation provider for this session.
+        *
+        * @return The annotation provider for this session.
+        */
        public AnnotationProvider getAnnotationProvider() {
                return ctx.getAnnotationProvider();
        }
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 b5dacaab5b..426c3b8d54 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
@@ -132,7 +132,7 @@ public class DelegateBeanMap<T> extends BeanMap<T> {
                        if (overrideValues.containsKey(k))
                                p = BeanPropertyMeta.builder(this.meta, 
k).overrideValue(overrideValues.get(k)).delegateFor(p).build();
                        if (p == null)
-                               p = BeanPropertyMeta.builder(this.meta, 
k).overrideValue(null).delegateFor(p).build();
+                               p = BeanPropertyMeta.builder(this.meta, 
k).overrideValue(null).build();
                        l.add(p);
                });
                return l;

Reply via email to