Petar Tahchiev opened SPR-16978 and commented
Hello,
consider the following setup:
// code from spring-security
public interface UserDetails extends Serializable {
Collection<? extends GrantedAuthority> getAuthorities();
String getPassword();
String getUsername();
boolean isAccountNonExpired();
boolean isAccountNonLocked();
boolean isCredentialsNonExpired();
boolean isEnabled();
}
public interface MyUserDetails extends UserDetails {
Locale getLocale();
void setLocale(final Locale locale);
/* setters for super properties */
void setUsername(String username);
void setPassword(String password);
}
public interface CustomerDetails extends MyUsersDetails {
String getPhone();
void setPhone(String phone);
}
Now invoke BeanUtils.getPropertyDescriptor(CustomerDetails.class, "username"); and you will see that the returned PropertyDescriptor has correct writeMethod but the readMethod is null. As a result, if I try to submit a CustomerDetails form in spring-mvc
I get this error:
2018-06-26 18:13:33,604 org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/storefront].[dispatcherServlet] [https-jsse-nio-127.0.0.1-8112-exec-5] ERROR: Servlet.service() for servlet [dispatcherServlet] in context with path [/storefront] threw exception [Request processing failed; nested exception is java.lang.IllegalArgumentException: Method must not be null] with root cause
java.lang.IllegalArgumentException: Method must not be null
at org.springframework.util.Assert.notNull(Assert.java:193)
at org.springframework.core.MethodParameter.<init>(MethodParameter.java:120)
at org.springframework.core.MethodParameter.<init>(MethodParameter.java:106)
at org.springframework.data.web.MapDataBinder$MapPropertyAccessor.setPropertyValue(MapDataBinder.java:193)
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValue(AbstractPropertyAccessor.java:67)
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:97)
at org.springframework.validation.DataBinder.applyPropertyValues(DataBinder.java:839)
at org.springframework.validation.DataBinder.doBind(DataBinder.java:735)
at org.springframework.web.bind.WebDataBinder.doBind(WebDataBinder.java:197)
at org.springframework.validation.DataBinder.bind(DataBinder.java:720
I believe this is because in CachedIntrospectionResults a look goes through all super interfaces:
while (clazz != null && clazz != Object.class) {
Class<?>[] ifcs = clazz.getInterfaces();
for (Class<?> ifc : ifcs) {
if (!ClassUtils.isJavaLanguageInterface(ifc)) {
for (PropertyDescriptor pd : getBeanInfo(ifc).getPropertyDescriptors()) {
until Object is reached and for each finds the property descriptor. However when it reaches MyUserDetails it finds the setter method and creates a PropertyDescriptor with null read method which is wrong because the read method is defined in the parent interface.
Affects: 5.0.7
Issue Links:
Referenced from: commits bf5fe46
Petar Tahchiev opened SPR-16978 and commented
Hello,
consider the following setup:
Now invoke
BeanUtils.getPropertyDescriptor(CustomerDetails.class, "username");and you will see that the returnedPropertyDescriptorhas correctwriteMethodbut thereadMethodis null. As a result, if I try to submit aCustomerDetailsform in spring-mvcI get this error:
I believe this is because in
CachedIntrospectionResultsa look goes through all super interfaces:until
Objectis reached and for each finds the property descriptor. However when it reachesMyUserDetailsit finds the setter method and creates aPropertyDescriptorwith null read method which is wrong because the read method is defined in the parent interface.Affects: 5.0.7
Issue Links:
Referenced from: commits bf5fe46