|
Hi Virtualeyes,
I think if you're just doing to do a println, a System.out.println would work. Haven't tested it though! Erik On Aug 21, 2011, at 12:32 AM, virtualeyes wrote: > def save() { > def entity = new Node(params) // entity is def'd, so local scope > if(entity.save(flush:true)) { > withFormat { > println entity // works, toString() invoked > html { > println entity // error, java.lang.NoSuchMethodError (at withFormat & > html lines) > } > } > } > } > > the only way to get things working is to create an instance level variable > and this.foo it; otherwise nested withFormat closure has no knowledge of > outer scope. This may be old hat Groovy for some, but was a bit of a > surprise for me. Is there a way around this? I'd prefer not to have to work > outside the nested closure if possible. > > -- > View this message in context: http://grails.1312388.n4.nabble.com/withFormat-is-blind-when-I-am-def-tp3757733p3757733.html > Sent from the Grails - user mailing list archive at Nabble.com. > > --------------------------------------------------------------------- > To unsubscribe from this list, please visit: > > http://xircles.codehaus.org/manage_email > > --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
Need more than println, that's just to show the issue.
Basically one needs to refer to an instance variable inside of nested closures -- minor hassle, but obviously work aroundable. Interestingly, experimenting I tried: html { obj->println obj }(entity) invoking the closure immediately; it works, but the caveat is that actually it does not, since after your invoking of the closure, grails follows, calling html {} without args ;-( Would be nice to pass args to nested withFormat closures; then you wouldn't be forced assign instance variable(s) |
|
In reply to this post by Erik Pragt
hey Virtualeyes!
just a blind guess as I won't test it now: Is it possible grails is expecting _only_ HTML in a withFormat html() block ... so it doesn't know of any println ? anyway it says missingMethodException not MissingPropertyException so it's not about entity but println try html { [node:entity] } and access the var "node" in your gsp cheers, Joehannes 2011/8/21 Erik Pragt <[hidden email]> Hi Virtualeyes, |
|
yes, a "blind" guess indeed ;-)
Mos def the problem is with local variables defined outside of nested closures. My use case is performing a REST redirect uri: to the show action of given controller, which in this case should be "/node/1" doing: redirect uri: "/node/"+entity.nid breaks with mme, while printing entity.nid outside closure scope correctly print 1 creating an instance variable, entityID, solves the problem. this.entityID = entity.nid withFormat { html { redirect uri: "/node/"+entityID } } Moral of the story is: when you def, withFormat goes blind. |
|
In reply to this post by Erik Pragt
Is this related to callable.resolveStrategy = Closure.DELEGATE_ONLY?
http://www.grails.org/doc/latest/ref/Controllers/withFormat.html http://groovy.codehaus.org/api/groovy/lang/Closure.html#DELEGATE_ONLY // MimeTypesGrailsPlugin.groovy private addWithFormatMethod(controllers) { controllers*.metaClass*.withFormat = { Closure callable -> def formats = [:] try { callable.delegate = new FormatInterceptor() callable.resolveStrategy = Closure.DELEGATE_ONLY callable.call() formats = callable.delegate.formatOptions } finally { callable.delegate = delegate callable.resolveStrategy = Closure.OWNER_FIRST } //(...) class FormatInterceptor { def formatOptions = new ListOrderedMap() Object invokeMethod(String name,args) { if (args.size() > 0 && (args[0] instanceof Closure || args[0] instanceof Map)) { formatOptions[name] = args[0] } else { formatOptions[name] = null } } } virtualeyes wrote: > def save() { > def entity = new Node(params) // entity is def'd, so local scope > if(entity.save(flush:true)) { > withFormat { > println entity // works, toString() invoked > html { > println entity // error, java.lang.NoSuchMethodError (at withFormat & > html lines) > } > } > } > } > > the only way to get things working is to create an instance level variable > and this.foo it; otherwise nested withFormat closure has no knowledge of > outer scope. This may be old hat Groovy for some, but was a bit of a > surprise for me. Is there a way around this? I'd prefer not to have to work > outside the nested closure if possible. > > > --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
BTW, I was not able to reproduce the issue in a simple test app
using Grails 1.3.7. // TestController.groovy package test.xyz class TestController { def index = { //def entity = new Node(params) // entity is def'd, so local scope //if(entity.save(flush:true)) { def entity = new Object() if (true) { withFormat { println entity // works, toString() invoked html { println entity // error, java.lang.NoSuchMethodError (at withFormat & html lines) } } } } } Then I accessed http://localhost:8080/test-xyz/test/index And I got the following output java.lang.Object@1786b2ca java.lang.Object@1786b2ca This Groovy script is also producing the same result: http://groovyconsole.appspot.com/script/541001 Best regards, Daniel. Daniel Henrique Alves Lima wrote: > Is this related to callable.resolveStrategy = Closure.DELEGATE_ONLY? > > http://www.grails.org/doc/latest/ref/Controllers/withFormat.html > http://groovy.codehaus.org/api/groovy/lang/Closure.html#DELEGATE_ONLY > > // MimeTypesGrailsPlugin.groovy > > private addWithFormatMethod(controllers) { > controllers*.metaClass*.withFormat = { Closure callable -> > def formats = [:] > try { > callable.delegate = new FormatInterceptor() > callable.resolveStrategy = Closure.DELEGATE_ONLY > callable.call() > formats = callable.delegate.formatOptions > } > finally { > callable.delegate = delegate > callable.resolveStrategy = Closure.OWNER_FIRST > } > > //(...) > > class FormatInterceptor { > def formatOptions = new ListOrderedMap() > Object invokeMethod(String name,args) { > if (args.size() > 0 && (args[0] instanceof Closure || args[0] > instanceof Map)) { > formatOptions[name] = args[0] > } > else { > formatOptions[name] = null > } > } > } > > > > virtualeyes wrote: >> def save() { >> def entity = new Node(params) // entity is def'd, so local scope >> if(entity.save(flush:true)) { >> withFormat { >> println entity // works, toString() invoked >> html { println entity // error, >> java.lang.NoSuchMethodError (at withFormat & >> html lines) >> } >> } >> } >> } >> >> the only way to get things working is to create an instance level >> variable >> and this.foo it; otherwise nested withFormat closure has no knowledge of >> outer scope. This may be old hat Groovy for some, but was a bit of a >> surprise for me. Is there a way around this? I'd prefer not to have >> to work >> outside the nested closure if possible. >> >> >> --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
In reply to this post by Daniel Henrique Alves Lima-2
Yes, Daniel, that would explain it, thanks.
Working around it is not a huge deal, really only bit by it in a successful save block, so can live with it, rest'ing is more important. |
|
But I couldn't reproduce the issue:
http://grails.1312388.n4.nabble.com/Re-withFormat-is-blind-when-I-am-def-tp3758517p3758885.html virtualeyes wrote: > Yes, Daniel, that would explain it, thanks. > > Working around it is not a huge deal, really only bit by it in a successful > save block, so can live with it, rest'ing is more important. > > --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
hmmm, I'm on 2.0, but I wonder if you change index = {...} to index() {...} if you'll be able to reproduce.
Could be groovy specific where variable scope is different between closures & methods with nested closures. The docs on withFormat also imply that one should use this.foo to define a variable that will be used within nested closures. Let me know if everything works as is on 1.3.7 when action is a method & not a closure.... Thanks |
|
Just confirmed on 2.0, if controller action is defined as a closure, then locally scoped variables defined outside of a withFormat block are available within nested closures (html, json, xml, etc.).
Change controller action to a method (recommended approach for 2.0 apparently) and attempt to access locally scoped variables within nested closures blows up with an MME. |
|
For 1.3.7, replacing a closure by a method will result in a 404 error.
Using 1.3.7 source code in the Groovy web console, it doesn't really matter if you're invoking a method or a closure: http://groovyconsole.appspot.com/edit/541001 I think the issue that you're seing might be a bug. To be sure, check the implementation of withFormat for 2.0.0. Best regards, Daniel. virtualeyes wrote: > Just confirmed on 2.0, if controller action is defined as a closure, then > locally scoped variables defined outside of a withFormat block are available > within nested closures (html, json, xml, etc.). > > Change controller action to a method (recommended approach for 2.0 > apparently) and attempt to access locally scoped variables within nested > closures blows up with an MME. > > -- > View this message in context: http://grails.1312388.n4.nabble.com/Re-withFormat-is-blind-when-I-am-def-tp3758517p3758991.html > Sent from the Grails - user mailing list archive at Nabble.com. > > --------------------------------------------------------------------- > To unsubscribe from this list, please visit: > > http://xircles.codehaus.org/manage_email > > > --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
2.0.0 is using AST to add withFormat (MimeTypesTransformer.java). I
don't have any idea how runtime MP differs from compile-time MP :-) Daniel Henrique Alves Lima wrote: > For 1.3.7, replacing a closure by a method will result in a 404 error. > Using 1.3.7 source code in the Groovy web console, it doesn't really > matter if you're invoking a method or a closure: > http://groovyconsole.appspot.com/edit/541001 > I think the issue that you're seing might be a bug. To be sure, check > the implementation of withFormat for 2.0.0. > > Best regards, > > Daniel. > > virtualeyes wrote: >> Just confirmed on 2.0, if controller action is defined as a closure, >> then >> locally scoped variables defined outside of a withFormat block are >> available >> within nested closures (html, json, xml, etc.). >> >> Change controller action to a method (recommended approach for 2.0 >> apparently) and attempt to access locally scoped variables within nested >> closures blows up with an MME. >> --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
In reply to this post by virtualeyes
On 21/08/2011 15:58, virtualeyes wrote:
> Interestingly, experimenting I tried: > html { obj->println obj }(entity) > > invoking the closure immediately; it works, but the caveat is that actually > it does not, since after your invoking of the closure, grails follows, > calling html {} without args ;-( > > Would be nice to pass args to nested withFormat closures; then you wouldn't > be forced assign instance variable(s) html { obj -> println obj }.curry(entity) Ian -- Ian Roberts | Department of Computer Science [hidden email] | University of Sheffield, UK --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
Brilliant, did not think of that.
Of course, blows up in 2.0 with MME, this is looking like a bug: When your action (save, list, show...) is a method and not a closure, not only will withFormat go blind to action method's local variable scope, defining a simple closure will also MME. def save() { def c = {println "hello"} // MME here def entity = new Node(params).save(flush:true) // local scope .... withFormat { html { println entity } } // MME again here when referencing def'd instance } |
|
JIRA it.
virtualeyes wrote: > Brilliant, did not think of that. > > Of course, blows up in 2.0 with MME, this is looking like a bug: > > When your action (save, list, show...) is a method and not a closure, not > only will withFormat go blind to action method's local variable scope, > defining a simple closure will also MME. > > def save() { > def c = {println "hello"} // MME here > def entity = new Node(params).save(flush:true) // local scope > .... > withFormat { html { println entity } } // MME again here when > referencing def'd instance > } > > -- > View this message in context: http://grails.1312388.n4.nabble.com/Re-withFormat-is-blind-when-I-am-def-tp3758517p3759936.html > Sent from the Grails - user mailing list archive at Nabble.com. > > --------------------------------------------------------------------- > To unsubscribe from this list, please visit: > > http://xircles.codehaus.org/manage_email > > > --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
| Powered by Nabble | Edit this page |
