diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/support/ReflectivePropertyAccessor.java b/spring-expression/src/main/java/org/springframework/expression/spel/support/ReflectivePropertyAccessor.java index 621db0ec37..3409bd47f9 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/support/ReflectivePropertyAccessor.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/support/ReflectivePropertyAccessor.java @@ -282,13 +282,19 @@ public class ReflectivePropertyAccessor implements PropertyAccessor { } /** - * Find a getter method for the specified property. A getter is defined as a method whose name start with the prefix - * 'get' and the rest of the name is the same as the property name (with the first character uppercased). + * Find a getter method for the specified property. */ protected Method findGetterForProperty(String propertyName, Class clazz, boolean mustBeStatic) { Method[] ms = clazz.getMethods(); + String propertyWriteMethodSuffix; + if (propertyName.length() > 1 && Character.isUpperCase(propertyName.charAt(1))) { + propertyWriteMethodSuffix = propertyName; + } + else { + propertyWriteMethodSuffix = StringUtils.capitalize(propertyName); + } // Try "get*" method... - String getterName = "get" + StringUtils.capitalize(propertyName); + String getterName = "get" + propertyWriteMethodSuffix; for (Method method : ms) { if (method.getName().equals(getterName) && method.getParameterTypes().length == 0 && (!mustBeStatic || Modifier.isStatic(method.getModifiers()))) { @@ -296,7 +302,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor { } } // Try "is*" method... - getterName = "is" + StringUtils.capitalize(propertyName); + getterName = "is" + propertyWriteMethodSuffix; for (Method method : ms) { if (method.getName().equals(getterName) && method.getParameterTypes().length == 0 && boolean.class.equals(method.getReturnType()) && diff --git a/spring-expression/src/test/java/org/springframework/expression/spel/support/ReflectionHelperTests.java b/spring-expression/src/test/java/org/springframework/expression/spel/support/ReflectionHelperTests.java index 42cdc2b401..2bc87f90fb 100644 --- a/spring-expression/src/test/java/org/springframework/expression/spel/support/ReflectionHelperTests.java +++ b/spring-expression/src/test/java/org/springframework/expression/spel/support/ReflectionHelperTests.java @@ -318,7 +318,17 @@ public class ReflectionHelperTests extends ExpressionTestCase { // Assert.assertEquals(0,rpr.read(ctx,t,"field3").getValue()); Assert.assertEquals(false,rpr.read(ctx,t,"property4").getValue()); Assert.assertTrue(rpr.canRead(ctx,t,"property4")); - + + // repro SPR-9123, ReflectivePropertyAccessor JavaBean property names compliance tests + Assert.assertEquals("iD",rpr.read(ctx,t,"iD").getValue()); + Assert.assertTrue(rpr.canRead(ctx,t,"iD")); + Assert.assertEquals("id",rpr.read(ctx,t,"id").getValue()); + Assert.assertTrue(rpr.canRead(ctx,t,"id")); + Assert.assertEquals("ID",rpr.read(ctx,t,"ID").getValue()); + Assert.assertTrue(rpr.canRead(ctx,t,"ID")); + // note: "Id" is not a valid JavaBean name, nevertheless it is treated as "id" + Assert.assertEquals("id",rpr.read(ctx,t,"Id").getValue()); + Assert.assertTrue(rpr.canRead(ctx,t,"Id")); } @Test @@ -406,6 +416,9 @@ public class ReflectionHelperTests extends ExpressionTestCase { String property2; String property3 = "doodoo"; boolean property4 = false; + String iD = "iD"; + String id = "id"; + String ID = "ID"; public String getProperty() { return property; } public void setProperty(String value) { property = value; } @@ -415,6 +428,12 @@ public class ReflectionHelperTests extends ExpressionTestCase { public String getProperty3() { return property3; } public boolean isProperty4() { return property4; } + + public String getiD() { return iD; } + + public String getId() { return id; } + + public String getID() { return ID; } } static class Super {