[ https://issues.apache.org/jira/browse/GROOVY-9662?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17209668#comment-17209668 ]
Eric Milles edited comment on GROOVY-9662 at 10/7/20, 5:09 PM: --------------------------------------------------------------- The difference in behavior comes from the static compiler using more of the declared delegation metadata. {{grails.plugin.json.builder.StreamingJsonBuilder.StreamingJsonDelegate #cloneDelegateAndGetContent}} and {{#curryDelegateAndGetContent}} uses {{groovy.lang.DelegatesTo}} to indicate the type of the closure's delegate, but does not correctly indicate the resolve strategy. {code:java} // "strategy = Closure.DELEGATE_FIRST" was added to match how the closure is actually invoked private static void curryDelegateAndGetContent(Writer w, @DelegatesTo(value = StreamingJsonDelegate.class, strategy = Closure.DELEGATE_FIRST) Closure c, Object o, boolean first, JsonGenerator generator) { StreamingJsonDelegate delegate = new StreamingJsonDelegate(w, first, generator); Closure curried = c.curry(o); curried.setDelegate(delegate); curried.setResolveStrategy(Closure.DELEGATE_FIRST); curried.call(); } {code} If I propagate the resolve strategy to all callers of this method (in [^StreamingJsonBuilder.java], [^JsonViewWritableScript.groovy], JsonView, etc.) the test case works as expected. was (Author: emilles): The difference in behavior comes from the static compiler using more of the declared delegation metadata. {{grails.plugin.json.builder.StreamingJsonBuilder.StreamingJsonDelegate #cloneDelegateAndGetContent}} and {{#curryDelegateAndGetContent}} uses {{groovy.lang.DelegatesTo}} to indicate the type of the closure's delegate, but does not correctly indicate the resolve strategy. {code:java} // "strategy = Closure.DELEGATE_FIRST" was added to match how the closure is actually invoked private static void curryDelegateAndGetContent(Writer w, @DelegatesTo(value = StreamingJsonDelegate.class, strategy = Closure.DELEGATE_FIRST) Closure c, Object o, boolean first, JsonGenerator generator) { StreamingJsonDelegate delegate = new StreamingJsonDelegate(w, first, generator); Closure curried = c.curry(o); curried.setDelegate(delegate); curried.setResolveStrategy(Closure.DELEGATE_FIRST); curried.call(); } {code} If I propagate the resolve strategy to all callers of this method (in [^StreamingJsonBuilder.java], JsonViewWriteableSript, JsonView, etc.) the test case works as expected. > Groovy 3.0.5: Closure delegate is not working properly > ------------------------------------------------------ > > Key: GROOVY-9662 > URL: https://issues.apache.org/jira/browse/GROOVY-9662 > Project: Groovy > Issue Type: Bug > Affects Versions: 3.0.2, 3.0.3, 3.0.4, 3.0.5 > Reporter: Puneet Behl > Assignee: Eric Milles > Priority: Major > Attachments: JsonViewWritableScript.groovy, StreamingJsonBuilder.java > > > In Grails Views, we are using closures to generate JSON using > `StreamingJsonBuilder`. The HAL implementation for an entity now generates an > incorrect JSON after updating to Groovy 3. > > Here is the problem code snipped from Grails Views: > {code:java} > jsonDelegate.call(LINKS_ATTRIBUTE) { > call(SELF_ATTRIBUTE) { > call HREF_ATTRIBUTE, viewHelper.link(resource: object, method: > HttpMethod.GET, absolute: true) > call HREFLANG_ATTRIBUTE, locale.toString() > call TYPE_ATTRIBUTE, contentType > } > Set<Link> links = getLinks(object) > for (link in links) { > call(link.rel) { > call HREF_ATTRIBUTE, link.href > call HREFLANG_ATTRIBUTE, link.hreflang?.toString() ?: > locale.toString() > def linkType = link.contentType > if (linkType) { > call TYPE_ATTRIBUTE, linkType > } > } > } > } > {code} > > Although the `resolveStatergy` for the closures is `DELEGATE_FIRST` but I > believe that is not working correctly because it works if I change the above > to: > {code:java} > delegate.call (... > {code} > > To reproduce the issue please checkout > https://github.com/grails/grails-views/commits/bugs/groovy-9962 > -- This message was sent by Atlassian Jira (v8.3.4#803005)