Skip to content

Commit

Permalink
Compensate for changes in JDK 7 Introspector
Browse files Browse the repository at this point in the history
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
cbeams committed Feb 13, 2012
1 parent b787a68 commit 0a5392e
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -429,11 +430,12 @@ class C {
}

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));
Expand All @@ -456,13 +458,12 @@ class C {
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));
Expand Down Expand Up @@ -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));
}
Expand Down Expand Up @@ -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 {
Expand Down

0 comments on commit 0a5392e

Please sign in to comment.