From b787a68f2050df179f7036b209aa741230a02477 Mon Sep 17 00:00:00 2001 From: Chris Beams Date: Mon, 13 Feb 2012 13:50:38 +0100 Subject: [PATCH] Avoid 'type mismatch' errors in ExtendedBeanInfo Prior to this commit, ExtendedBeanInfo would add non-indexed write methods without consideration for the presence of indexed read/write methods, which is invalid per the JavaBeans spec and per the behavior of java.beans.Introspector. That is, a method with the signature void setFoo(Foo foo) Should never be registered as a write method if the following method signature is also present in the class void setFoo(int i, Foo foo) In most cases, this oversight caused no problems, but in certain situations where a bean actually contains such a mismatch of methods, "type mismatch" errors were thrown when ExtendedBeanInfo attempted the illegal addition against the underlying property descriptor. The implementation is now more careful about checking the parameter type of write methods -- if the property descriptor in question is an IndexedPropertyDescriptor, i.e. has an indexed write method, then any non-indexed write method candidate must have a single *array* parameter, which conforms to the spec and to Introspector behavior. Issue: SPR-8937 --- .../beans/ExtendedBeanInfo.java | 4 ++- .../beans/ExtendedBeanInfoTests.java | 30 +++++++++++++------ 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/ExtendedBeanInfo.java b/org.springframework.beans/src/main/java/org/springframework/beans/ExtendedBeanInfo.java index 3b0dd4ccbd..ef9a3a9414 100644 --- a/org.springframework.beans/src/main/java/org/springframework/beans/ExtendedBeanInfo.java +++ b/org.springframework.beans/src/main/java/org/springframework/beans/ExtendedBeanInfo.java @@ -219,7 +219,9 @@ class ExtendedBeanInfo implements BeanInfo { } } // update the existing descriptor's write method - if (writeMethod != null) { + if (writeMethod != null + && !(existingPD instanceof IndexedPropertyDescriptor && + !writeMethod.getParameterTypes()[0].isArray())) { existingPD.setWriteMethod(writeMethod); } diff --git a/org.springframework.beans/src/test/java/org/springframework/beans/ExtendedBeanInfoTests.java b/org.springframework.beans/src/test/java/org/springframework/beans/ExtendedBeanInfoTests.java index 8111fdb237..ea4e783305 100644 --- a/org.springframework.beans/src/test/java/org/springframework/beans/ExtendedBeanInfoTests.java +++ b/org.springframework.beans/src/test/java/org/springframework/beans/ExtendedBeanInfoTests.java @@ -742,16 +742,28 @@ public class ExtendedBeanInfoTests { assertThat(hasWriteMethodForProperty(ebi, "targetMethod"), is(false)); } - static class X { - public boolean isTargetMethod() { - return false; + @Test + public void cornerSpr8937() throws IntrospectionException { + @SuppressWarnings("unused") class A { + public void setAddress(String addr){ } + public void setAddress(int index, String addr) { } + public String getAddress(int index){ return null; } + } + + { // baseline. ExtendedBeanInfo needs to behave exactly like the following + BeanInfo bi = Introspector.getBeanInfo(A.class); + assertThat(hasReadMethodForProperty(bi, "address"), is(false)); + assertThat(hasWriteMethodForProperty(bi, "address"), is(false)); + assertThat(hasIndexedReadMethodForProperty(bi, "address"), is(true)); + assertThat(hasIndexedWriteMethodForProperty(bi, "address"), is(true)); + } + { + ExtendedBeanInfo bi = new ExtendedBeanInfo(Introspector.getBeanInfo(A.class)); + assertThat(hasReadMethodForProperty(bi, "address"), is(false)); + assertThat(hasWriteMethodForProperty(bi, "address"), is(false)); + assertThat(hasIndexedReadMethodForProperty(bi, "address"), is(true)); + assertThat(hasIndexedWriteMethodForProperty(bi, "address"), is(true)); } } - static class Y extends X { - @Override - public boolean isTargetMethod() { - return false; - } - } }