You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The JavaBeans specification considers property 'write methods' (setters) to be those:
starting with the string 'set', followed by the capitalized name of the property. (setFoo(Foo), setBar(Bar))
accepting a single argument that matches the return type of the 'read method' (getter), if any. (public Foo getFoo(), public void setFoo(Foo)
having a void return type.
These requirements are reflected in the implementation of the static java.beans.Introspector#getBeanInfo(Class) method, which Spring uses to determine what properties are available for injection (see org.springframework.beans.CachedIntrospectionResults.
The third constraint above poses a problem in certain cases, particularly where a 'builder-style' API is being used -- one that allows for method chaining setters by returning the this reference of the builder object.
Such builder-style objects are convenient for use when configuring Spring beans programmatically within @Configuration class @Bean methods, for example, but if one attempts to use them as <bean/> definitions within a Spring XML file, the container will throw a NotWritablePropertyException. This is not because Spring is incapable of calling the non-standard setter style, but rather because Introspector#getBeanInfo() never notices the non-standard setter in the first place, and any subsequent call to BeanInfo#getPropertyDescriptors() will fail to report its existence.
For this reason, we will introduce a decorator for the BeanInfo object returned from Introspector#getBeanInfo() that takes one more pass against the specified class, looking for any setter methods with non-void return types. Calls to the decorated BeanInfo type will faithfully report these methods, and Spring's injection facilities will operate normally from there.
It is important that:
this work play nicely with the existing decoration approach in GenericTypeAwarePropertyDescriptor.
non-void returning setter methods are detected even if there is no matching getter method declared. This is a common scenario within framework classes.
While this is a generally useful addition to the framework, it is getting priority now in order to support the work described in #12076 -- specifically #12721, which deals with refactoring Spring's *SessionFactoryBean types to extend the new @Configuration-friendly *SessionFactoryBuilder types. When doing this, the signature of the FactoryBeans' setter methods changes to non-void return types and causes the issue described above. Implementing this new feature will eliminate this problem.
A general note to watchers of ExtendedBeanInfo-related issues: #14663 is a major refactoring of ExtendedBeanInfo and overall support for non-void returning setter methods.
If you have submitted a reproduction project with this issue, we have run it through its paces against these new changes, but we would like to ask you to do the same against your actual applications.
Please consider updating your dev or test builds to work against 3.1.4.BUILD-SNAPSHOT and/or 3.2.0.BUILD-SNAPSHOT to verify, and we would appreciate any feedback, even if it's to let us know that all is well. So that we can consolidate feedback, please add your comments to #14663, and mention the original issue(s) that you were watching.
Thanks!
Note also that testing against 3.1.4 is preferable to 3.2.0 because ExtendedBeanInfo is always in the code path in the latter, while in 3.2.0 we've optimized things such that ExtendedBeanInfo is only in play for bean classes that have one or more non-void returning setter methods.
Chris Beams opened SPR-8079 and commented
The JavaBeans specification considers property 'write methods' (setters) to be those:
setFoo(Foo)
,setBar(Bar)
)public Foo getFoo()
,public void setFoo(Foo)
void
return type.These requirements are reflected in the implementation of the static
java.beans.Introspector#getBeanInfo(Class)
method, which Spring uses to determine what properties are available for injection (seeorg.springframework.beans.CachedIntrospectionResults
.The third constraint above poses a problem in certain cases, particularly where a 'builder-style' API is being used -- one that allows for method chaining setters by returning the
this
reference of the builder object.Such builder-style objects are convenient for use when configuring Spring beans programmatically within
@Configuration
class@Bean
methods, for example, but if one attempts to use them as<bean/>
definitions within a Spring XML file, the container will throw aNotWritablePropertyException
. This is not because Spring is incapable of calling the non-standard setter style, but rather becauseIntrospector#getBeanInfo()
never notices the non-standard setter in the first place, and any subsequent call toBeanInfo#getPropertyDescriptors()
will fail to report its existence.For this reason, we will introduce a decorator for the
BeanInfo
object returned fromIntrospector#getBeanInfo()
that takes one more pass against the specified class, looking for any setter methods with non-void return types. Calls to the decoratedBeanInfo
type will faithfully report these methods, and Spring's injection facilities will operate normally from there.It is important that:
GenericTypeAwarePropertyDescriptor
.While this is a generally useful addition to the framework, it is getting priority now in order to support the work described in #12076 -- specifically #12721, which deals with refactoring Spring's
*SessionFactoryBean
types to extend the new@Configuration
-friendly*SessionFactoryBuilder
types. When doing this, the signature of the FactoryBeans' setter methods changes to non-void return types and causes the issue described above. Implementing this new feature will eliminate this problem.Issue Links:
@Bean
methodsThe text was updated successfully, but these errors were encountered: