diff --git a/spring-beans/src/main/java/org/springframework/beans/ExtendedBeanInfo.java b/spring-beans/src/main/java/org/springframework/beans/ExtendedBeanInfo.java index c383a52b5b..856e62c031 100644 --- a/spring-beans/src/main/java/org/springframework/beans/ExtendedBeanInfo.java +++ b/spring-beans/src/main/java/org/springframework/beans/ExtendedBeanInfo.java @@ -31,6 +31,7 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; +import java.util.Collections; import java.util.Comparator; import java.util.Enumeration; import java.util.List; @@ -116,6 +117,14 @@ class ExtendedBeanInfo implements BeanInfo { matches.add(method); } } + // sort non-void returning write methods to guard against the ill effects of + // non-deterministic sorting of methods returned from Class#getDeclaredMethods + // under JDK 7. See http://bugs.sun.com/view_bug.do?bug_id=7023180 + Collections.sort(matches, new Comparator() { + public int compare(Method m1, Method m2) { + return m2.toString().compareTo(m1.toString()); + } + }); return matches; } @@ -261,7 +270,7 @@ class SimpleNonIndexedPropertyDescriptor extends PropertyDescriptor { public SimpleNonIndexedPropertyDescriptor(String propertyName, Method readMethod, Method writeMethod) throws IntrospectionException { - super(propertyName, readMethod, writeMethod); + super(propertyName, null, null); this.setReadMethod(readMethod); this.setWriteMethod(writeMethod); this.propertyType = findPropertyType(readMethod, writeMethod); @@ -350,7 +359,7 @@ class SimpleIndexedPropertyDescriptor extends IndexedPropertyDescriptor { Method indexedReadMethod, Method indexedWriteMethod) throws IntrospectionException { - super(propertyName, readMethod, writeMethod, indexedReadMethod, indexedWriteMethod); + super(propertyName, null, null, null, null); this.setReadMethod(readMethod); this.setWriteMethod(writeMethod); this.propertyType = findPropertyType(readMethod, writeMethod); @@ -495,7 +504,7 @@ class PropertyDescriptorUtils { // copy all attributes (emulating behavior of private FeatureDescriptor#addTable) Enumeration keys = source.attributeNames(); while (keys.hasMoreElements()) { - String key = (String)keys.nextElement(); + String key = keys.nextElement(); target.setValue(key, source.getValue(key)); } diff --git a/spring-beans/src/test/java/org/springframework/beans/ExtendedBeanInfoTests.java b/spring-beans/src/test/java/org/springframework/beans/ExtendedBeanInfoTests.java index 5e05fc91db..b0343230e8 100644 --- a/spring-beans/src/test/java/org/springframework/beans/ExtendedBeanInfoTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/ExtendedBeanInfoTests.java @@ -23,6 +23,7 @@ import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.Method; +import java.math.BigDecimal; import org.junit.Test; @@ -582,6 +583,20 @@ public class ExtendedBeanInfoTests { } } + /** + * Prior to SPR-10111 (a follow-up fix for SPR-9702), this method would throw an + * IntrospectionException regarding a "type mismatch between indexed and non-indexed + * methods" intermittently (approximately one out of every four times) under JDK 7 + * due to non-deterministic results from {@link Class#getDeclaredMethods()}. + * See http://bugs.sun.com/view_bug.do?bug_id=7023180 + * @see #cornerSpr9702() + */ + @Test + public void cornerSpr10111() throws Exception { + new ExtendedBeanInfo(Introspector.getBeanInfo(BigDecimal.class)); + } + + @Test public void subclassWriteMethodWithCovariantReturnType() throws IntrospectionException { @SuppressWarnings("unused") class B { @@ -692,7 +707,7 @@ public class ExtendedBeanInfoTests { for (PropertyDescriptor pd : ebi.getPropertyDescriptors()) { if (pd.getName().equals("foo")) { - assertThat(pd.getWriteMethod(), is(C.class.getMethod("setFoo", int.class))); + assertThat(pd.getWriteMethod(), is(C.class.getMethod("setFoo", String.class))); return; } } @@ -730,7 +745,7 @@ public class ExtendedBeanInfoTests { assertThat(hasReadMethodForProperty(ebi, "dateFormat"), is(false)); assertThat(hasWriteMethodForProperty(ebi, "dateFormat"), is(true)); assertThat(hasIndexedReadMethodForProperty(ebi, "dateFormat"), is(false)); - assertThat(hasIndexedWriteMethodForProperty(ebi, "dateFormat"), is(true)); + assertThat(hasIndexedWriteMethodForProperty(ebi, "dateFormat"), is(trueUntilJdk17())); } @Test @@ -941,4 +956,5 @@ public class ExtendedBeanInfoTests { assertThat(hasIndexedWriteMethodForProperty(bi, "address"), is(true)); } } + }