Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support injection against setter methods with non-void return types [SPR-8079] #12734

Closed
spring-projects-issues opened this issue Mar 22, 2011 · 1 comment
Labels
type: enhancement A general enhancement
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Mar 22, 2011

Chris Beams opened SPR-8079 and commented

The JavaBeans specification considers property 'write methods' (setters) to be those:

  1. starting with the string 'set', followed by the capitalized name of the property. (setFoo(Foo), setBar(Bar))
  2. accepting a single argument that matches the return type of the 'read method' (getter), if any. (public Foo getFoo(), public void setFoo(Foo)
  3. 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.


Issue Links:

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Nov 25, 2012

Chris Beams commented

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

1 participant