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 6619f10cfe New BeanCreator API
6619f10cfe is described below

commit 6619f10cfeb2d3d1f1d9aad092a6cb77ccbb23c4
Author: James Bognar <[email protected]>
AuthorDate: Wed Jan 21 12:03:05 2026 -0500

    New BeanCreator API
---
 .../apache/juneau/commons/reflect/ClassInfo.java   |  2 +-
 .../java/org/apache/juneau/rest/RestOpContext.java | 16 ++++++++++++++-
 .../juneau/commons/reflect/ClassInfo_Test.java     | 24 +++++++++++-----------
 3 files changed, 28 insertions(+), 14 deletions(-)

diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/ClassInfo.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/ClassInfo.java
index e89d7e5fb9..b5e3b16904 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/ClassInfo.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/ClassInfo.java
@@ -2735,7 +2735,7 @@ public class ClassInfo extends ElementInfo implements 
Annotatable, Type, Compara
         * @return The cached {@link MethodInfo} wrapper for this method.
         */
        MethodInfo getMethod(Method x) {
-               return methodCache.get(x, () -> new MethodInfo(this, x));
+               return methodCache.get(x, () -> new MethodInfo(eq(this.inner, 
x.getDeclaringClass()) ? this : of(x.getDeclaringClass()), x));
        }
 
        /**
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContext.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContext.java
index 1a51d77bac..7ff56b6eb0 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContext.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContext.java
@@ -130,12 +130,26 @@ public class RestOpContext extends Context implements 
Comparable<RestOpContext>
                        var ap = 
context.getBeanContext().getAnnotationProvider();
 
                        var mi = MethodInfo.of(context.getResourceClass(), 
method);
+                       var resourceClass = 
ClassInfo.of(context.getResourceClass());
 
                        try {
                                var vr = context.getVarResolver();
                                var vrs = vr.createSession();
 
-                               var work = AnnotationWorkList.of(vrs, 
rstream(ap.find(mi, SELF, MATCHING_METHODS, DECLARING_CLASS, RETURN_TYPE, 
PACKAGE)).filter(CONTEXT_APPLY_FILTER));
+                               // For DECLARING_CLASS traversal, we need to 
search from the resource class hierarchy,
+                               // not the method's declaring class hierarchy, 
to ensure we find annotations on the
+                               // resource class even when the method is 
declared in a parent class.
+                               // We search class annotations first 
(parent-to-child), then method annotations (parent-to-child),
+                               // so that method-level annotations override 
class-level ones.
+                               // Use LinkedHashSet to deduplicate while 
preserving order (parent-to-child).
+                               var declaringClassAnnotations = 
rstream(ap.find(resourceClass, SELF, PARENTS));
+                               var methodAnnotations = rstream(ap.find(mi, 
SELF, MATCHING_METHODS, RETURN_TYPE, PACKAGE));
+                               var allAnnotationsSet = new 
java.util.LinkedHashSet<AnnotationInfo<?>>();
+                               
declaringClassAnnotations.forEach(allAnnotationsSet::add);
+                               
methodAnnotations.forEach(allAnnotationsSet::add);
+                               var allAnnotations = allAnnotationsSet.stream();
+
+                               var work = AnnotationWorkList.of(vrs, 
allAnnotations.filter(CONTEXT_APPLY_FILTER));
 
                                apply(work);
 
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/ClassInfo_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/ClassInfo_Test.java
index 55fce15ea2..c88d407abe 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/ClassInfo_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/ClassInfo_Test.java
@@ -2004,10 +2004,10 @@ public class ClassInfo_Test extends TestBase {
        
//====================================================================================================
        @Test
        void a059_getPublicMethods() {
-               
check("CC3.c1a(),CC3.c2b(),CC3.c3a(),CC3.i1a(),CC3.i1b(),CC3.i2a(),CC3.i2b()", 
cc3.getPublicMethods());
-               check("CI2.i1a(),CI2.i1b(),CI2.i2a(),CI2.i2b()", 
ci2.getPublicMethods());
+               
check("CC1.c1a(),CC2.c2b(),CC3.c3a(),CC1.i1a(),CC2.i1b(),CC2.i2a(),CC3.i2b()", 
cc3.getPublicMethods());
+               check("CI1.i1a(),CI1.i1b(),CI2.i2a(),CI2.i2b()", 
ci2.getPublicMethods());
                // Test twice to verify caching
-               check("CI2.i1a(),CI2.i1b(),CI2.i2a(),CI2.i2b()", 
ci2.getPublicMethods());
+               check("CI1.i1a(),CI1.i1b(),CI2.i2a(),CI2.i2b()", 
ci2.getPublicMethods());
 
                // Test on types
                check("", aTypeInfo.getPublicMethods());
@@ -3364,35 +3364,35 @@ public class ClassInfo_Test extends TestBase {
                assertEquals("static class 
org.apache.juneau.commons.reflect.ClassInfo_Test$ToStringTestPackage", 
ClassInfo.of(ToStringTestPackage.class).toString());
                assertEquals("protected static class 
org.apache.juneau.commons.reflect.ClassInfo_Test$ToStringTestProtected", 
ClassInfo.of(ToStringTestProtected.class).toString());
                assertEquals("private static class 
org.apache.juneau.commons.reflect.ClassInfo_Test$ToStringTestPrivate", 
ClassInfo.of(ToStringTestPrivate.class).toString());
-               
+
                // Final class
                assertEquals("public static final class 
org.apache.juneau.commons.reflect.ClassInfo_Test$ToStringTestFinal", 
ClassInfo.of(ToStringTestFinal.class).toString());
-               
+
                // Abstract class (Modifier.toString() returns "public abstract 
static" in standard Java modifier order)
                assertEquals("public abstract static class 
org.apache.juneau.commons.reflect.ClassInfo_Test$ToStringTestAbstract", 
ClassInfo.of(ToStringTestAbstract.class).toString());
-               
+
                // Generic class
                assertEquals("public static class 
org.apache.juneau.commons.reflect.ClassInfo_Test$ToStringTestGeneric<T>", 
ClassInfo.of(ToStringTestGeneric.class).toString());
-               
+
                // Generic class with bounds
                assertEquals("public static class 
org.apache.juneau.commons.reflect.ClassInfo_Test$ToStringTestGenericWithBounds<T
 extends java.lang.Comparable<T> & java.io.Serializable>", 
ClassInfo.of(ToStringTestGenericWithBounds.class).toString());
-               
+
                // Enum
                assertEquals("public static enum 
org.apache.juneau.commons.reflect.ClassInfo_Test$ToStringTestEnum", 
ClassInfo.of(ToStringTestEnum.class).toString());
-               
+
                // Annotation
                assertEquals("public static @interface 
org.apache.juneau.commons.reflect.ClassInfo_Test$ToStringTestAnnotation", 
ClassInfo.of(ToStringTestAnnotation.class).toString());
-               
+
                // Record
                assertEquals("public static record 
org.apache.juneau.commons.reflect.ClassInfo_Test$ToStringTestRecord", 
ClassInfo.of(ToStringTestRecord.class).toString());
-               
+
                // Test existing classes with different modifiers
                assertEquals("public static class 
org.apache.juneau.commons.reflect.ClassInfo_Test$H_Public", hPublic.toString());
                assertEquals("static class 
org.apache.juneau.commons.reflect.ClassInfo_Test$H_Package", 
hPackage.toString());
                assertEquals("protected static class 
org.apache.juneau.commons.reflect.ClassInfo_Test$H_Protected", 
hProtected.toString());
                assertEquals("private static class 
org.apache.juneau.commons.reflect.ClassInfo_Test$H_Private", 
hPrivate.toString());
                assertEquals("public abstract class 
org.apache.juneau.commons.reflect.ClassInfo_Test$H_AbstractPublic", 
hAbstractPublic.toString());
-               
+
                // Test standard library classes
                assertEquals("public final class java.lang.String", 
ClassInfo.of(String.class).toString());
                assertEquals("public interface java.util.List<E>", 
ClassInfo.of(java.util.List.class).toString());

Reply via email to