[ 
https://issues.apache.org/jira/browse/GROOVY-8186?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16009898#comment-16009898
 ] 

Paul King edited comment on GROOVY-8186 at 5/15/17 1:21 AM:
------------------------------------------------------------

For case (1), which is when the builder class and buildee class are in the same 
compilation unit, you are correct that JavaBean properties aren't considered, 
just standard Groovy properties. We probably should change this. I suspect what 
we do for {{@ToString}}, where the underlying transform calls 
{{BeanUtils.getAllProperties}} to get the complete set of properties, is the 
way to go.

For case (2), it isn't really Groovy vs Java but whether the class is 
pre-compiled or not. When pre-compiled, {{@Builder}} uses standard JavaBean 
introspection to find the properties. If the parameter type of the setter 
doesn't match with the return type of the getter, the property is deemed 
read-only from a JavaBean perspective (and there just happens to be a 
setter-like named method also existing with a different parameter type):
{code}
def personClass = new GroovyShell().evaluate '''
class GroovyPerson {
    private Set<String> pets
    //Collection<String> getPets() { pets }
    Set<String> getPets() { pets }
    //void setPets(Set<String> pets) {
    void setPets(Collection<String> pets) {
        this.pets = pets == null ? Collections.emptySet() : new 
LinkedHashSet<String>(pets)
    }
}
GroovyPerson
'''
java.beans.Introspector.getBeanInfo(personClass).propertyDescriptors.each { pd 
->
    if (!['class', 'metaClass'].contains(pd.name))
        println "$pd.name $pd.propertyType.name $pd.writeMethod"
}
{code}
The null {{writeMethod}} indicates a read-only property. Uncomment either of 
the commented out lines (and remove the appropriate existing line) to see the 
property reappear.
I suspect we don't want to change that but I haven't checked what case (1) does 
in that situation yet - if we were to fix it as per above.


was (Author: paulk):
For case (1), which is when the builder class and buildee class are in the same 
compilation unit, you are correct that JavaBean properties aren't considered, 
just standard Groovy properties. We probably should change this. I suspect what 
we do for {{@ToString}}, where the underlying transform calls 
{{BeanUtils.getAllProperties}} to get the complete set of properties, is the 
way to go.

For case (2), it isn't really Groovy vs Java but whether the class is 
pre-compiled or not. When pre-compiled, {{@Builder}} uses standard JavaBean 
introspection to find the properties. If the parameter type of the setter 
doesn't match with the return type of the getter, the property is deemed 
read-only from a JavaBean perspective (and there just happens to be a 
setter-like named method also existing with a different parameter type):
{code}
def personClass = new GroovyShell().evaluate '''
class GroovyPerson {
    private Set<String> pets
    //Collection<String> getPets() { pets }
    Set<String> getPets() { pets }
    //void setPets(Set<String> pets) {
    void setPets(Collection<String> pets) {
        this.pets = pets == null ? Collections.emptySet() : new 
LinkedHashSet<String>(pets)
    }
}
GroovyPerson
'''
java.beans.Introspector.getBeanInfo(personClass).propertyDescriptors.each { pd 
->
    if (!['class', 'metaClass'].contains(pd.name))
        println "$pd.name $pd.propertyType.name $pd.writeMethod"
}
{code}
The null {{writeMethod}} indicates a read-only property. Uncomment either of 
the commented out lines to see the property reappear.
I suspect we don't want to change that but I haven't checked what case (1) does 
in that situation yet.

> Builder ExternalStrategy constructors have trouble with private fields
> ----------------------------------------------------------------------
>
>                 Key: GROOVY-8186
>                 URL: https://issues.apache.org/jira/browse/GROOVY-8186
>             Project: Groovy
>          Issue Type: Bug
>    Affects Versions: 2.4.x, 2.5.x
>            Reporter: Jason Terhune-Wold
>            Priority: Minor
>
> An undocumented feature of @Builder is that the builder's constructor can set 
> default values for the fields. See 
> http://stackoverflow.com/questions/35066664/default-values-in-groovy-builder-ast
> I tried creating an ExternalStrategy @Builder annotation for 
> [BaseClientDetails|http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/client/BaseClientDetails.html]
>  with a constructor that set a default scope. I received a 
> MissingMethodException exception, which I thought was odd.
> I added some tests to BuilderTransformTest that demonstrate apparent problems 
> using the external builder in two situations:
> 1) A groovy class with private fields and manually defined setters.
> 2) A java class with a private Set field and a setter that takes a Collection
> The tests are here: 
> https://github.com/jterhune/groovy/commit/5b2eb74cc8184235b5235b7fd4c80b241799bbc5
> I noticed this in 2.4.x. My tests fail in the 2.5.x branch also.



--
This message was sent by Atlassian JIRA
(v6.3.15#6346)

Reply via email to