diff --git a/src/main/java/org/apache/commons/beanutils2/FluentPropertyBeanIntrospector.java b/src/main/java/org/apache/commons/beanutils2/FluentPropertyBeanIntrospector.java index e40f09ef4..61e2f6e77 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.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 @@ *
* 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. *
*
* 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 String getWriteMethodPrefix() {
@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 012a3fbd6..dafba2fe5 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 @@ private static Method getMethod(final Class> clazz, final String methodName, f
}
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 c89a86e43..1cc6ae139 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 @@ public void setURI(final URI theURI) {
}
}
+ 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 @@ void testIntrospectionCaps() throws Exception {
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