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());
}