From 7993d8306f9e84116dd65f8e9fb3de02b277296d Mon Sep 17 00:00:00 2001 From: risingcult Date: Wed, 19 Nov 2025 09:57:08 +0500 Subject: [PATCH 1/2] fix(core): handle overloaded typical Java methods in annotation scan --- .../annotation/AnnotationScannerUtil.java | 11 ++++-- .../annotation/AnnotationScannerUtilTest.java | 39 +++++++++++++++++++ 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/common/annotation/AnnotationScannerUtil.java b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/common/annotation/AnnotationScannerUtil.java index 906e69d98..9ab4ff924 100644 --- a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/common/annotation/AnnotationScannerUtil.java +++ b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/common/annotation/AnnotationScannerUtil.java @@ -83,10 +83,13 @@ private static boolean isNotHidden(AnnotatedElement element) { return Objects.isNull(AnnotationUtil.findFirstAnnotation(Hidden.class, element)); } - private static final Set typicalJavaMethods = - Set.of("clone", "equals", "finalize", "getClass", "hashCode", "notify", "notifyAll", "toString", "wait"); - private static boolean isNotTypicalJavaMethod(Method method) { - return !typicalJavaMethods.contains(method.getName()); + return !isDeclaredOnObject(method); + } + + private static boolean isDeclaredOnObject(Method method) { + return Arrays.stream(Object.class.getDeclaredMethods()) + .anyMatch(objectMethod -> objectMethod.getName().equals(method.getName()) + && Arrays.equals(objectMethod.getParameterTypes(), method.getParameterTypes())); } } diff --git a/springwolf-core/src/test/java/io/github/springwolf/core/asyncapi/scanners/common/annotation/AnnotationScannerUtilTest.java b/springwolf-core/src/test/java/io/github/springwolf/core/asyncapi/scanners/common/annotation/AnnotationScannerUtilTest.java index a3a9350a9..4f4aa7b08 100644 --- a/springwolf-core/src/test/java/io/github/springwolf/core/asyncapi/scanners/common/annotation/AnnotationScannerUtilTest.java +++ b/springwolf-core/src/test/java/io/github/springwolf/core/asyncapi/scanners/common/annotation/AnnotationScannerUtilTest.java @@ -155,6 +155,30 @@ void getAllMethods() throws Exception { ClassWithMethodAnnotation.class.getDeclaredMethod("hiddenAnnotatedMethod"), null)); } + @Test + void methodsWithTypicalNamesButDifferentSignaturesAreNotIgnored() throws Exception { + List> methods = AnnotationScannerUtil.findAnnotatedMethods( + ClassWithTypicalJavaMethodNames.class, MethodAnnotation.class) + .toList(); + + Method equalsWithCustomSignature = + ClassWithTypicalJavaMethodNames.class.getDeclaredMethod("equals", String.class); + Method equalsWithObjectSignature = + ClassWithTypicalJavaMethodNames.class.getDeclaredMethod("equals", Object.class); + Method waitWithCustomSignature = + ClassWithTypicalJavaMethodNames.class.getDeclaredMethod("wait", String.class); + + assertThat(methods) + .hasSize(2) + .contains(new MethodAndAnnotation<>( + equalsWithCustomSignature, equalsWithCustomSignature.getAnnotation(MethodAnnotation.class))) + .contains(new MethodAndAnnotation<>( + waitWithCustomSignature, waitWithCustomSignature.getAnnotation(MethodAnnotation.class))) + .doesNotContain(new MethodAndAnnotation<>( + equalsWithObjectSignature, + equalsWithObjectSignature.getAnnotation(MethodAnnotation.class))); + } + class ClassWithMethodAnnotation { @MethodAnnotation void annotatedMethod() {} @@ -165,6 +189,21 @@ void nonAnnotatedMethod() {} @Hidden void hiddenAnnotatedMethod() {} } + + class ClassWithTypicalJavaMethodNames { + + @MethodAnnotation + public void wait(String str) {} + + @MethodAnnotation + public void equals(String str) {} + + @Override + @MethodAnnotation + public boolean equals(Object obj) { + return super.equals(obj); + } + } } @Retention(RetentionPolicy.RUNTIME) From 6f39ddd06ea1a7fceb62850e8f79b922c4358eb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20M=C3=BCller?= Date: Fri, 21 Nov 2025 17:13:03 +0100 Subject: [PATCH 2/2] refactor(core): use ReflectionsUtils from Spring to find user declared methods when scanning a class for methods Co-authored-by: Timon Back --- .../annotation/AnnotationScannerUtil.java | 20 +------------------ .../annotation/AnnotationScannerUtilTest.java | 10 +++++----- 2 files changed, 6 insertions(+), 24 deletions(-) diff --git a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/common/annotation/AnnotationScannerUtil.java b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/common/annotation/AnnotationScannerUtil.java index 9ab4ff924..4b2f094f0 100644 --- a/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/common/annotation/AnnotationScannerUtil.java +++ b/springwolf-core/src/main/java/io/github/springwolf/core/asyncapi/scanners/common/annotation/AnnotationScannerUtil.java @@ -57,8 +57,7 @@ public static Stream> findAnnotate methodAnnotationClass.getName()); Stream methods = Arrays.stream(ReflectionUtils.getAllDeclaredMethods(clazz)) - .filter(AnnotationScannerUtil::isMethodInSourceCode) - .filter(AnnotationScannerUtil::isNotTypicalJavaMethod) + .filter(ReflectionUtils.USER_DECLARED_METHODS::matches) .filter(AnnotationScannerUtil::isNotHidden); if (methodAnnotationClass == AllMethods.class) { @@ -72,24 +71,7 @@ public static Stream> findAnnotate .map(annotation -> new MethodAndAnnotation<>(method, annotation))); } - /** - * Check that a method was written by a developer and not generated by the compiler. - */ - private static boolean isMethodInSourceCode(Method method) { - return !method.isSynthetic(); - } - private static boolean isNotHidden(AnnotatedElement element) { return Objects.isNull(AnnotationUtil.findFirstAnnotation(Hidden.class, element)); } - - private static boolean isNotTypicalJavaMethod(Method method) { - return !isDeclaredOnObject(method); - } - - private static boolean isDeclaredOnObject(Method method) { - return Arrays.stream(Object.class.getDeclaredMethods()) - .anyMatch(objectMethod -> objectMethod.getName().equals(method.getName()) - && Arrays.equals(objectMethod.getParameterTypes(), method.getParameterTypes())); - } } diff --git a/springwolf-core/src/test/java/io/github/springwolf/core/asyncapi/scanners/common/annotation/AnnotationScannerUtilTest.java b/springwolf-core/src/test/java/io/github/springwolf/core/asyncapi/scanners/common/annotation/AnnotationScannerUtilTest.java index 4f4aa7b08..4c481799c 100644 --- a/springwolf-core/src/test/java/io/github/springwolf/core/asyncapi/scanners/common/annotation/AnnotationScannerUtilTest.java +++ b/springwolf-core/src/test/java/io/github/springwolf/core/asyncapi/scanners/common/annotation/AnnotationScannerUtilTest.java @@ -163,20 +163,20 @@ void methodsWithTypicalNamesButDifferentSignaturesAreNotIgnored() throws Excepti Method equalsWithCustomSignature = ClassWithTypicalJavaMethodNames.class.getDeclaredMethod("equals", String.class); - Method equalsWithObjectSignature = + Method equalsWithObjectSignatureOverride = ClassWithTypicalJavaMethodNames.class.getDeclaredMethod("equals", Object.class); Method waitWithCustomSignature = ClassWithTypicalJavaMethodNames.class.getDeclaredMethod("wait", String.class); assertThat(methods) - .hasSize(2) + .hasSize(3) .contains(new MethodAndAnnotation<>( equalsWithCustomSignature, equalsWithCustomSignature.getAnnotation(MethodAnnotation.class))) .contains(new MethodAndAnnotation<>( waitWithCustomSignature, waitWithCustomSignature.getAnnotation(MethodAnnotation.class))) - .doesNotContain(new MethodAndAnnotation<>( - equalsWithObjectSignature, - equalsWithObjectSignature.getAnnotation(MethodAnnotation.class))); + .contains(new MethodAndAnnotation<>( + equalsWithObjectSignatureOverride, + equalsWithObjectSignatureOverride.getAnnotation(MethodAnnotation.class))); } class ClassWithMethodAnnotation {