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

garydgregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-beanutils.git


The following commit(s) were added to refs/heads/master by this push:
     new 684d5057 Skip static methods in FluentPropertyBeanIntrospector and 
mapped lookup (#437)
684d5057 is described below

commit 684d5057f01aad3ececdb7638cf8b2e6dc72e13e
Author: Naveed Khan <[email protected]>
AuthorDate: Sun Aug 23 13:35:41 2026 +0000

    Skip static methods in FluentPropertyBeanIntrospector and mapped lookup 
(#437)
    
    * skip static methods in FluentPropertyBeanIntrospector and mapped lookup
    
    * Fix comment on static method introspection
    
    ---------
    
    Co-authored-by: Gary Gregory <[email protected]>
---
 .../beanutils2/FluentPropertyBeanIntrospector.java |  7 ++++-
 .../beanutils2/MappedPropertyDescriptor.java       |  3 +-
 .../FluentPropertyBeanIntrospectorTest.java        | 33 ++++++++++++++++++++++
 .../commons/beanutils2/MappedPropertyTest.java     | 10 +++++++
 .../commons/beanutils2/MappedPropertyTestBean.java |  8 ++++++
 5 files changed, 59 insertions(+), 2 deletions(-)

diff --git 
a/src/main/java/org/apache/commons/beanutils2/FluentPropertyBeanIntrospector.java
 
b/src/main/java/org/apache/commons/beanutils2/FluentPropertyBeanIntrospector.java
index e40f09ef..61e2f6e7 100644
--- 
a/src/main/java/org/apache/commons/beanutils2/FluentPropertyBeanIntrospector.java
+++ 
b/src/main/java/org/apache/commons/beanutils2/FluentPropertyBeanIntrospector.java
@@ -20,6 +20,7 @@ import java.beans.IntrospectionException;
 import java.beans.Introspector;
 import java.beans.PropertyDescriptor;
 import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
 import java.util.Objects;
 
 import org.apache.commons.logging.Log;
@@ -56,7 +57,7 @@ import org.apache.commons.logging.LogFactory;
  * <p>
  * This class is more tolerant with regards to the return type of a set 
method. It basically iterates over all methods of a class and filters them for a
  * configurable prefix (the default prefix is {@code set}). It then generates 
corresponding {@code PropertyDescriptor} objects for the methods found which use
- * these methods as write methods.
+ * these methods as write methods. Static methods are ignored, as they are by 
default ignored in introspection.
  * </p>
  * <p>
  * An instance of this class is intended to collaborate with a {@link 
DefaultBeanIntrospector} object. So best results are achieved by adding this 
instance as
@@ -128,6 +129,10 @@ public class FluentPropertyBeanIntrospector implements 
BeanIntrospector {
     @Override
     public void introspect(final IntrospectionContext icontext) throws 
IntrospectionException {
         for (final Method m : icontext.getTargetClass().getMethods()) {
+            // Static methods are not property accessors; default 
introspection skips them as well.
+            if (Modifier.isStatic(m.getModifiers())) {
+                continue;
+            }
             if (m.getName().startsWith(getWriteMethodPrefix())) {
                 final String propertyName = propertyName(m);
                 final PropertyDescriptor pd = 
icontext.getPropertyDescriptor(propertyName);
diff --git 
a/src/main/java/org/apache/commons/beanutils2/MappedPropertyDescriptor.java 
b/src/main/java/org/apache/commons/beanutils2/MappedPropertyDescriptor.java
index 012a3fbd..dafba2fe 100644
--- a/src/main/java/org/apache/commons/beanutils2/MappedPropertyDescriptor.java
+++ b/src/main/java/org/apache/commons/beanutils2/MappedPropertyDescriptor.java
@@ -181,7 +181,8 @@ public class MappedPropertyDescriptor extends 
PropertyDescriptor {
         }
 
         final Method method = MethodUtils.getMatchingAccessibleMethod(clazz, 
methodName, parameterTypes);
-        if (method != null) {
+        // skip static methods, as internalGetMethod does.
+        if (method != null && !Modifier.isStatic(method.getModifiers())) {
             return method;
         }
 
diff --git 
a/src/test/java/org/apache/commons/beanutils2/FluentPropertyBeanIntrospectorTest.java
 
b/src/test/java/org/apache/commons/beanutils2/FluentPropertyBeanIntrospectorTest.java
index c89a86e4..1cc6ae13 100644
--- 
a/src/test/java/org/apache/commons/beanutils2/FluentPropertyBeanIntrospectorTest.java
+++ 
b/src/test/java/org/apache/commons/beanutils2/FluentPropertyBeanIntrospectorTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.commons.beanutils2;
 
+import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -45,6 +46,23 @@ class FluentPropertyBeanIntrospectorTest {
         }
     }
 
+    public static final class StaticSetterBean {
+        private static String staticValue;
+
+        public static void setStaticOnly(final String value) {
+            staticValue = value;
+        }
+
+        public static StaticSetterBean setStaticProperty(final String value) {
+            staticValue = value;
+            return new StaticSetterBean();
+        }
+
+        public String getStaticProperty() {
+            return staticValue;
+        }
+    }
+
     /**
      * Puts all property descriptors into a map so that they can be accessed 
by property name.
      *
@@ -119,4 +137,19 @@ class FluentPropertyBeanIntrospectorTest {
 
         assertNull(props.get("uRI"), "Should not find mis-capitalized 
property");
     }
+
+    /**
+     * Tests that static methods are not treated as write methods.
+     */
+    @Test
+    void testIntrospectionStaticMethods() throws Exception {
+        final PropertyUtilsBean pu = new PropertyUtilsBean();
+        pu.addBeanIntrospector(new FluentPropertyBeanIntrospector());
+        final Map<String, PropertyDescriptor> props = 
createDescriptorMap(pu.getPropertyDescriptors(StaticSetterBean.class));
+        assertNull(props.get("staticOnly"), "Property created from static 
method");
+        final PropertyDescriptor pd = fetchDescriptor(props, "staticProperty");
+        assertNotNull(pd.getReadMethod(), "No read method for staticProperty");
+        assertNull(pd.getWriteMethod(), "Static method used as write method");
+        assertFalse(pu.isWriteable(new StaticSetterBean(), "staticProperty"), 
"staticProperty is writeable");
+    }
 }
diff --git 
a/src/test/java/org/apache/commons/beanutils2/MappedPropertyTest.java 
b/src/test/java/org/apache/commons/beanutils2/MappedPropertyTest.java
index 425aa0b9..f6d898bc 100644
--- a/src/test/java/org/apache/commons/beanutils2/MappedPropertyTest.java
+++ b/src/test/java/org/apache/commons/beanutils2/MappedPropertyTest.java
@@ -225,6 +225,16 @@ class MappedPropertyTest {
         assertThrows(IntrospectionException.class, () -> new 
MappedPropertyDescriptor(property, clazz));
     }
 
+    /**
+     * Test static mapped accessors are ignored
+     */
+    @Test
+    void testStaticMapped() {
+        final String property = "staticMapped";
+        final Class<?> clazz = MappedPropertyTestBean.class;
+        assertThrows(IntrospectionException.class, () -> new 
MappedPropertyDescriptor(property, clazz));
+    }
+
     /**
      * Test 'protected' method in parent
      */
diff --git 
a/src/test/java/org/apache/commons/beanutils2/MappedPropertyTestBean.java 
b/src/test/java/org/apache/commons/beanutils2/MappedPropertyTestBean.java
index cdd81641..69d7f56c 100644
--- a/src/test/java/org/apache/commons/beanutils2/MappedPropertyTestBean.java
+++ b/src/test/java/org/apache/commons/beanutils2/MappedPropertyTestBean.java
@@ -29,6 +29,14 @@ public class MappedPropertyTestBean {
     private final Map<Object, Object> map = new HashMap<>();
     private final Map<Object, Object> myMap = new HashMap<>();
 
+    public static String getStaticMapped(final String key) {
+        return "static-" + key;
+    }
+
+    public static void setStaticMapped(final String key, final String value) {
+        // empty
+    }
+
     public Long getDifferentTypes(final String key) {
         return Long.valueOf(((Number) map.get(key)).longValue());
     }

Reply via email to