Permalink
Browse files

Compensate for changes in JDK 7 Introspector

Prior to JDK 7, java.beans.Introspector registered indexed write methods
irrespective of return type, for example either of the following methods
were legal

    void setFoo(int i, Foo foo)
    Object setFoo(int i, Foo foo)

This was considered a bug and disallowed starting with JDK 7, such that
only the former signature is a candidate.

Supporting non-void returning setter methods is exactly what
ExtendedBeanInfo was designed to do, and prior to this commit, the
implementation of ExtendedBeanInfo assumed this (somewhat surprising)
behavior from the underlying Introspector, and because it worked out of
the box, took no extra steps to recognize and register these methods.
For this reason, non-void returning indexed write methods were not
registered under JDK 7+, causing test failures in ExtendedBeanInfoTests.

Now the implementation is careful to detect these methods without any
assumption about Introspector behavior, such that they are registered in
exactly the same fashion across JDK versions.

Issue: SPR-9014
  • Loading branch information...
1 parent b787a68 commit 0a5392e37d268d4df9526216531a6655e52b9f38 @cbeams cbeams committed Feb 13, 2012
@@ -131,19 +131,13 @@ public ExtendedBeanInfo(BeanInfo delegate) throws IntrospectionException {
Method indexedReadMethod = ipd.getIndexedReadMethod();
Method indexedWriteMethod = ipd.getIndexedWriteMethod();
// has the setter already been found by the wrapped BeanInfo?
- if (indexedWriteMethod != null
- && indexedWriteMethod.getName().equals(method.getName())) {
- // yes -> copy it, including corresponding getter method (if any -- may be null)
- this.addOrUpdatePropertyDescriptor(pd, propertyName, readMethod, writeMethod, indexedReadMethod, indexedWriteMethod);
- continue ALL_METHODS;
- }
- // has a getter corresponding to this setter already been found by the wrapped BeanInfo?
- if (indexedReadMethod != null
- && indexedReadMethod.getName().equals(getterMethodNameFor(propertyName))
- && indexedReadMethod.getReturnType().equals(method.getParameterTypes()[1])) {
- this.addOrUpdatePropertyDescriptor(pd, propertyName, readMethod, writeMethod, indexedReadMethod, method);
- continue ALL_METHODS;
+ if (!(indexedWriteMethod != null
+ && indexedWriteMethod.getName().equals(method.getName()))) {
+ indexedWriteMethod = method;
}
+ // yes -> copy it, including corresponding getter method (if any -- may be null)
+ this.addOrUpdatePropertyDescriptor(pd, propertyName, readMethod, writeMethod, indexedReadMethod, indexedWriteMethod);
+ continue ALL_METHODS;
}
// the INDEXED setter method was not found by the wrapped BeanInfo -> add a new PropertyDescriptor
// for it. no corresponding INDEXED getter was detected, so the 'indexed read method' parameter is null.
@@ -293,6 +287,16 @@ private void addOrUpdatePropertyDescriptor(PropertyDescriptor pd, String propert
writeMethod, propertyName, ex.getMessage()));
// fall through -> add property descriptor as best we can
}
+ if (pd instanceof IndexedPropertyDescriptor) {
+ ((IndexedPropertyDescriptor)pd).setIndexedReadMethod(indexedReadMethod);
+ try {
+ ((IndexedPropertyDescriptor)pd).setIndexedWriteMethod(indexedWriteMethod);
+ } catch (IntrospectionException ex) {
+ logger.debug(format("Could not add indexed write method [%s] for property [%s]. Reason: %s",
+ indexedWriteMethod, propertyName, ex.getMessage()));
+ // fall through -> add property descriptor as best we can
+ }
+ }
this.propertyDescriptors.add(pd);
}
}
@@ -34,6 +34,7 @@
import org.junit.Test;
import org.springframework.beans.ExtendedBeanInfo.PropertyDescriptorComparator;
+import org.springframework.core.JdkVersion;
import org.springframework.util.ClassUtils;
import test.beans.TestBean;
@@ -429,11 +430,12 @@ public void indexedReadAndNonStandardIndexedWrite() throws IntrospectionExceptio
}
BeanInfo bi = Introspector.getBeanInfo(C.class);
- BeanInfo ebi = new ExtendedBeanInfo(Introspector.getBeanInfo(C.class));
assertThat(hasIndexedReadMethodForProperty(bi, "foos"), is(true));
// interesting! standard Inspector picks up non-void return types on indexed write methods by default
- assertThat(hasIndexedWriteMethodForProperty(bi, "foos"), is(true));
+ assertThat(hasIndexedWriteMethodForProperty(bi, "foos"), is(trueUntilJdk17()));
+
+ BeanInfo ebi = new ExtendedBeanInfo(Introspector.getBeanInfo(C.class));
assertThat(hasIndexedReadMethodForProperty(ebi, "foos"), is(true));
assertThat(hasIndexedWriteMethodForProperty(ebi, "foos"), is(true));
@@ -456,13 +458,12 @@ public void indexedReadAndNonStandardWriteAndNonStandardIndexedWrite() throws In
assertThat(hasIndexedReadMethodForProperty(bi, "foos"), is(true));
assertThat(hasWriteMethodForProperty(bi, "foos"), is(false));
// again as above, standard Inspector picks up non-void return types on indexed write methods by default
- assertThat(hasIndexedWriteMethodForProperty(bi, "foos"), is(true));
+ assertThat(hasIndexedWriteMethodForProperty(bi, "foos"), is(trueUntilJdk17()));
BeanInfo ebi = new ExtendedBeanInfo(Introspector.getBeanInfo(C.class));
assertThat(hasIndexedReadMethodForProperty(bi, "foos"), is(true));
assertThat(hasWriteMethodForProperty(bi, "foos"), is(true));
- // again as above, standard Inspector picks up non-void return types on indexed write methods by default
assertThat(hasIndexedWriteMethodForProperty(bi, "foos"), is(true));
assertThat(hasIndexedReadMethodForProperty(ebi, "foos"), is(true));
@@ -550,17 +551,17 @@ public void reproSpr8522() throws IntrospectionException {
assertThat(hasReadMethodForProperty(bi, "dateFormat"), is(false));
assertThat(hasWriteMethodForProperty(bi, "dateFormat"), is(false));
assertThat(hasIndexedReadMethodForProperty(bi, "dateFormat"), is(false));
- assertThat(hasIndexedWriteMethodForProperty(bi, "dateFormat"), is(true));
+ assertThat(hasIndexedWriteMethodForProperty(bi, "dateFormat"), is(trueUntilJdk17()));
ExtendedBeanInfo ebi = new ExtendedBeanInfo(bi);
assertThat(hasReadMethodForProperty(bi, "dateFormat"), is(false));
- assertThat(hasWriteMethodForProperty(bi, "dateFormat"), is(true));
+ assertThat(hasWriteMethodForProperty(bi, "dateFormat"), is(false));
assertThat(hasIndexedReadMethodForProperty(bi, "dateFormat"), is(false));
- assertThat(hasIndexedWriteMethodForProperty(bi, "dateFormat"), is(true));
+ assertThat(hasIndexedWriteMethodForProperty(bi, "dateFormat"), is(trueUntilJdk17()));
assertThat(hasReadMethodForProperty(ebi, "dateFormat"), is(false));
- assertThat(hasWriteMethodForProperty(ebi, "dateFormat"), is(true));
+ assertThat(hasWriteMethodForProperty(ebi, "dateFormat"), is(false));
assertThat(hasIndexedReadMethodForProperty(ebi, "dateFormat"), is(false));
assertThat(hasIndexedWriteMethodForProperty(ebi, "dateFormat"), is(true));
}
@@ -663,6 +664,10 @@ private boolean hasIndexedReadMethodForProperty(BeanInfo beanInfo, String proper
return false;
}
+ private boolean trueUntilJdk17() {
+ return JdkVersion.getMajorJavaVersion() < JdkVersion.JAVA_17;
+ }
+
@Test
public void reproSpr8806() throws IntrospectionException {

0 comments on commit 0a5392e

Please sign in to comment.