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
commit 3e1923bad3c249569817634d261b22d37451f45f Author: Gary Gregory <[email protected]> AuthorDate: Sun Aug 23 09:46:58 2026 -0400 Skip static methods in FluentPropertyBeanIntrospector and mapped lookup Add missing unit tests that could have been in PR #437. The tests explicitly cover the mixed static/instance accessor cases that were missing: Mapped property with a static getter but instance setter: read method is ignored, write method is used. Mapped property with an instance getter but static setter: read method is used, write method is ignored. Fluent introspector with a static and an instance setter for the same property name: the instance setter is chosen and the property remains writable. --- .../FluentPropertyBeanIntrospectorTest.java | 32 ++++++++++++++++ .../commons/beanutils2/MappedPropertyTest.java | 44 +++++++++++++++++----- .../commons/beanutils2/MappedPropertyTestBean.java | 22 +++++++++-- 3 files changed, 85 insertions(+), 13 deletions(-) diff --git a/src/test/java/org/apache/commons/beanutils2/FluentPropertyBeanIntrospectorTest.java b/src/test/java/org/apache/commons/beanutils2/FluentPropertyBeanIntrospectorTest.java index 1cc6ae13..fac98bcd 100644 --- a/src/test/java/org/apache/commons/beanutils2/FluentPropertyBeanIntrospectorTest.java +++ b/src/test/java/org/apache/commons/beanutils2/FluentPropertyBeanIntrospectorTest.java @@ -46,6 +46,23 @@ class FluentPropertyBeanIntrospectorTest { } } + public static final class MixedSetterBean { + public static void setMixed(final Integer v) { + // static setter should be ignored + } + + private String value; + + public String getMixed() { + return value; + } + + public MixedSetterBean setMixed(final String v) { + this.value = v; + return this; + } + } + public static final class StaticSetterBean { private static String staticValue; @@ -138,6 +155,21 @@ class FluentPropertyBeanIntrospectorTest { assertNull(props.get("uRI"), "Should not find mis-capitalized property"); } + /** + * Tests that an instance setter is used when a static setter with the same name exists. + */ + @Test + void testIntrospectionMixedStaticInstanceSetter() throws Exception { + final PropertyUtilsBean pu = new PropertyUtilsBean(); + pu.addBeanIntrospector(new FluentPropertyBeanIntrospector()); + final Map<String, PropertyDescriptor> props = createDescriptorMap(pu.getPropertyDescriptors(MixedSetterBean.class)); + final PropertyDescriptor pd = fetchDescriptor(props, "mixed"); + assertNotNull(pd.getReadMethod(), "No read method for mixed"); + assertNotNull(pd.getWriteMethod(), "Instance setter should be found"); + assertFalse(java.lang.reflect.Modifier.isStatic(pd.getWriteMethod().getModifiers()), "Write method should not be static"); + assertTrue(pu.isWriteable(new MixedSetterBean(), "mixed"), "mixed should be writeable"); + } + /** * Tests that static methods are not treated as write methods. */ diff --git a/src/test/java/org/apache/commons/beanutils2/MappedPropertyTest.java b/src/test/java/org/apache/commons/beanutils2/MappedPropertyTest.java index f6d898bc..f5a561c5 100644 --- a/src/test/java/org/apache/commons/beanutils2/MappedPropertyTest.java +++ b/src/test/java/org/apache/commons/beanutils2/MappedPropertyTest.java @@ -111,6 +111,18 @@ class MappedPropertyTest { assertNotNull(desc.getMappedWriteMethod(), "Setter is missing"); } + /** + * Test instance getter is used but static setter is ignored + */ + @Test + void testInstanceGetterStaticSetter() throws Exception { + final String property = "instanceGetterStaticSetter"; + final Class<?> clazz = MappedPropertyTestBean.class; + final MappedPropertyDescriptor desc = new MappedPropertyDescriptor(property, clazz); + assertNotNull(desc.getMappedReadMethod(), "Instance getter should be found"); + assertNull(desc.getMappedWriteMethod(), "Static setter should be ignored"); + } + /** * Test Interface with mapped property */ @@ -225,16 +237,6 @@ 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 */ @@ -256,4 +258,26 @@ class MappedPropertyTest { assertNotNull(desc.getMappedReadMethod(), "Getter is missing"); assertNotNull(desc.getMappedWriteMethod(), "Setter is missing"); } + + /** + * Test static getter is ignored but instance setter is used + */ + @Test + void testStaticGetterInstanceSetter() throws Exception { + final String property = "staticGetterInstanceSetter"; + final Class<?> clazz = MappedPropertyTestBean.class; + final MappedPropertyDescriptor desc = new MappedPropertyDescriptor(property, clazz); + assertNull(desc.getMappedReadMethod(), "Static getter should be ignored"); + assertNotNull(desc.getMappedWriteMethod(), "Instance setter should be found"); + } + + /** + * 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)); + } } diff --git a/src/test/java/org/apache/commons/beanutils2/MappedPropertyTestBean.java b/src/test/java/org/apache/commons/beanutils2/MappedPropertyTestBean.java index 69d7f56c..a28cf111 100644 --- a/src/test/java/org/apache/commons/beanutils2/MappedPropertyTestBean.java +++ b/src/test/java/org/apache/commons/beanutils2/MappedPropertyTestBean.java @@ -26,21 +26,33 @@ import java.util.Map; public class MappedPropertyTestBean { - private final Map<Object, Object> map = new HashMap<>(); - private final Map<Object, Object> myMap = new HashMap<>(); - + public static String getStaticGetterInstanceSetter(final String key) { + return null; + } public static String getStaticMapped(final String key) { return "static-" + key; } + public static void setInstanceGetterStaticSetter(final String key, final String value) { + // static setter should be ignored + } + public static void setStaticMapped(final String key, final String value) { // empty } + private final Map<Object, Object> map = new HashMap<>(); + + private final Map<Object, Object> myMap = new HashMap<>(); + public Long getDifferentTypes(final String key) { return Long.valueOf(((Number) map.get(key)).longValue()); } + public String getInstanceGetterStaticSetter(final String key) { + return (String) map.get(key); + } + public String getInvalidGetter(final String key, final String other) { return (String) map.get(key); } @@ -104,4 +116,8 @@ public class MappedPropertyTestBean { map.put(key, value); } + public void setStaticGetterInstanceSetter(final String key, final String value) { + map.put(key, value); + } + }
