Polish ExtendedBeanInfo and tests
ExtendedBeanInfo - Reduce log messages from warn to debug - Remove now-incorrect comment indicating underlying property descriptors are never modified (they actually are as of SPR-8806) ExtendedBeanInfoTests - Consolidate SPR-8949 tests - Eliminate compiler warnings Issue: SPR-8949, SPR-8806
This commit is contained in:
@@ -75,12 +75,6 @@ class ExtendedBeanInfo implements BeanInfo {
|
|||||||
public ExtendedBeanInfo(BeanInfo delegate) throws IntrospectionException {
|
public ExtendedBeanInfo(BeanInfo delegate) throws IntrospectionException {
|
||||||
this.delegate = delegate;
|
this.delegate = delegate;
|
||||||
|
|
||||||
// PropertyDescriptor instances from the delegate object are never added directly, but always
|
|
||||||
// copied to the local collection of #propertyDescriptors and returned by calls to
|
|
||||||
// #getPropertyDescriptors(). this algorithm iterates through all methods (method descriptors)
|
|
||||||
// in the wrapped BeanInfo object, copying any existing PropertyDescriptor or creating a new
|
|
||||||
// one for any non-standard setter methods found.
|
|
||||||
|
|
||||||
ALL_METHODS:
|
ALL_METHODS:
|
||||||
for (MethodDescriptor md : delegate.getMethodDescriptors()) {
|
for (MethodDescriptor md : delegate.getMethodDescriptors()) {
|
||||||
Method method = md.getMethod();
|
Method method = md.getMethod();
|
||||||
@@ -282,7 +276,7 @@ class ExtendedBeanInfo implements BeanInfo {
|
|||||||
}
|
}
|
||||||
this.propertyDescriptors.add(pd);
|
this.propertyDescriptors.add(pd);
|
||||||
} catch (IntrospectionException ex) {
|
} catch (IntrospectionException ex) {
|
||||||
logger.warn(format("Could not create new PropertyDescriptor for readMethod [%s] writeMethod [%s] " +
|
logger.debug(format("Could not create new PropertyDescriptor for readMethod [%s] writeMethod [%s] " +
|
||||||
"indexedReadMethod [%s] indexedWriteMethod [%s] for property [%s]. Reason: %s",
|
"indexedReadMethod [%s] indexedWriteMethod [%s] for property [%s]. Reason: %s",
|
||||||
readMethod, writeMethod, indexedReadMethod, indexedWriteMethod, propertyName, ex.getMessage()));
|
readMethod, writeMethod, indexedReadMethod, indexedWriteMethod, propertyName, ex.getMessage()));
|
||||||
// suppress exception and attempt to continue
|
// suppress exception and attempt to continue
|
||||||
@@ -293,7 +287,7 @@ class ExtendedBeanInfo implements BeanInfo {
|
|||||||
try {
|
try {
|
||||||
pd.setWriteMethod(writeMethod);
|
pd.setWriteMethod(writeMethod);
|
||||||
} catch (IntrospectionException ex) {
|
} catch (IntrospectionException ex) {
|
||||||
logger.warn(format("Could not add write method [%s] for property [%s]. Reason: %s",
|
logger.debug(format("Could not add write method [%s] for property [%s]. Reason: %s",
|
||||||
writeMethod, propertyName, ex.getMessage()));
|
writeMethod, propertyName, ex.getMessage()));
|
||||||
// fall through -> add property descriptor as best we can
|
// fall through -> add property descriptor as best we can
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -698,17 +698,31 @@ public class ExtendedBeanInfoTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* java.beans.Introspector returns the "wrong" declaring class for overridden read
|
|
||||||
* methods, which in turn violates expectations in {@link ExtendedBeanInfo} regarding
|
|
||||||
* method equality. Spring's {@link ClassUtils#getMostSpecificMethod(Method, Class)}
|
|
||||||
* helps out here, and is now put into use in ExtendedBeanInfo as well
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
public void demonstrateCauseSpr8949() throws IntrospectionException {
|
public void cornerSpr8949() throws IntrospectionException {
|
||||||
BeanInfo info = Introspector.getBeanInfo(B.class);
|
class A {
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public boolean isTargetMethod() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (PropertyDescriptor pd : info.getPropertyDescriptors()) {
|
class B extends A {
|
||||||
|
@Override
|
||||||
|
public boolean isTargetMethod() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BeanInfo bi = Introspector.getBeanInfo(B.class);
|
||||||
|
|
||||||
|
/* first, demonstrate the 'problem':
|
||||||
|
* java.beans.Introspector returns the "wrong" declaring class for overridden read
|
||||||
|
* methods, which in turn violates expectations in {@link ExtendedBeanInfo} regarding
|
||||||
|
* method equality. Spring's {@link ClassUtils#getMostSpecificMethod(Method, Class)}
|
||||||
|
* helps out here, and is now put into use in ExtendedBeanInfo as well
|
||||||
|
*/
|
||||||
|
for (PropertyDescriptor pd : bi.getPropertyDescriptors()) {
|
||||||
if ("targetMethod".equals(pd.getName())) {
|
if ("targetMethod".equals(pd.getName())) {
|
||||||
Method readMethod = pd.getReadMethod();
|
Method readMethod = pd.getReadMethod();
|
||||||
assertTrue(readMethod.getDeclaringClass().equals(A.class)); // we expected B!
|
assertTrue(readMethod.getDeclaringClass().equals(A.class)); // we expected B!
|
||||||
@@ -717,11 +731,8 @@ public class ExtendedBeanInfoTests {
|
|||||||
assertTrue(msReadMethod.getDeclaringClass().equals(B.class)); // and now we get it.
|
assertTrue(msReadMethod.getDeclaringClass().equals(B.class)); // and now we get it.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
// and now demonstrate that we've indeed fixed the problem
|
||||||
public void cornerSpr8949() throws IntrospectionException {
|
|
||||||
BeanInfo bi = Introspector.getBeanInfo(B.class);
|
|
||||||
ExtendedBeanInfo ebi = new ExtendedBeanInfo(bi);
|
ExtendedBeanInfo ebi = new ExtendedBeanInfo(bi);
|
||||||
|
|
||||||
assertThat(hasReadMethodForProperty(bi, "targetMethod"), is(true));
|
assertThat(hasReadMethodForProperty(bi, "targetMethod"), is(true));
|
||||||
@@ -731,13 +742,13 @@ public class ExtendedBeanInfoTests {
|
|||||||
assertThat(hasWriteMethodForProperty(ebi, "targetMethod"), is(false));
|
assertThat(hasWriteMethodForProperty(ebi, "targetMethod"), is(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
static class A {
|
static class X {
|
||||||
public boolean isTargetMethod() {
|
public boolean isTargetMethod() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class B extends A {
|
static class Y extends X {
|
||||||
@Override
|
@Override
|
||||||
public boolean isTargetMethod() {
|
public boolean isTargetMethod() {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
Reference in New Issue
Block a user