Groovy 为什么可以';我不能用自己的方法包装withRest()并在其中运行闭包吗?

Groovy 为什么可以';我不能用自己的方法包装withRest()并在其中运行闭包吗?,groovy,griffon,httpbuilder,Groovy,Griffon,Httpbuilder,Griffon的HTTPBuilder插件很棒,它很好地简化了我的服务器调用。然而,唯一的问题是,我不想在所有地方重复相同的设置代码 我想做的是用相同的连接设置包装一组服务器调用和其他代码,这样我就只在一个地方拥有它 举个例子,这就是我所拥有的: def persistCurrentSession() { withRest(uri: serverBaseURL) { headers = requestHeaders post(path: "${sessi

Griffon的HTTPBuilder插件很棒,它很好地简化了我的服务器调用。然而,唯一的问题是,我不想在所有地方重复相同的设置代码

我想做的是用相同的连接设置包装一组服务器调用和其他代码,这样我就只在一个地方拥有它

举个例子,这就是我所拥有的:

def persistCurrentSession() {
    withRest(uri: serverBaseURL) {
        headers = requestHeaders

        post(path: "${sessionBaseURL}${currentSession.id}",
                body: currentSession,
                requestContentType: groovyx.net.http.ContentType.JSON)
    }
}

def refreshCurrentSession() {
    withRest(uri: serverBaseURL) {
        headers = requestHeaders

        currentSession = get(path: "${sessionBaseURL}${currentSession.id}").responseData.sessionInstance
    }
}
这就是我想做的:

def persistCurrentSession() {
    withMyRest {
        post(path: "${sessionBaseURL}${currentSession.id}",
                body: currentSession,
                requestContentType: groovyx.net.http.ContentType.JSON)
    }
}

def refreshCurrentSession() {
    withMyRest {
        currentSession = get(path: "${sessionBaseURL}${currentSession.id}").responseData.sessionInstance
    }
}

def withMyRest(Closure stmts) {
    withRest(uri: serverBaseURL) {
        headers = requestHeaders
        stmts()
    }
}
根据我对Groovy和闭包的了解,这应该是闭包的一个很好的用途,因为它将常见的“设置/分解资源”代码删除到一个地方,并允许将重点放在服务器调用的内容上

问题在于,似乎没有正确添加动态方法,因为当我以我想要的方式运行代码时,
MissingMethodException
s在调用
stmts()
时被抛出:

2011-12-20 11:12:40,097 [pool-2-thread-1] ERROR griffon.util.GriffonExceptionHandler - Uncaught Exception
org.codehaus.groovy.runtime.InvokerInvocationException: groovy.lang.MissingMethodException: No signature of method: client.MyAppServerService.post() is applicable for argument types: (java.util.LinkedHashMap) values: [[path:http://localhost:8080/Server/session/4, ...]]
Possible solutions: wait(), wait(long), print(java.lang.Object), use([Ljava.lang.Object;), is(java.lang.Object), split(groovy.lang.Closure)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:97)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1053)
    at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:1071)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:883)
    at groovy.lang.Closure.call(Closure.java:410)
    at groovy.lang.Closure.call(Closure.java:404)
    at groovy.lang.Closure.run(Closure.java:488)
    at org.codehaus.griffon.runtime.util.AbstractUIThreadHandler$1.run(AbstractUIThreadHandler.java:41)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
    at java.util.concurrent.FutureTask.run(FutureTask.java:166)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
    at java.lang.Thread.run(Thread.java:722)
Caused by: groovy.lang.MissingMethodException: No signature of method: client.MyAppServerService.post() is applicable for argument types: (java.util.LinkedHashMap) values: [[path:http://localhost:8080/Server/session/4, ...]]
Possible solutions: wait(), wait(long), print(java.lang.Object), use([Ljava.lang.Object;), is(java.lang.Object), split(groovy.lang.Closure)
    at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:55)
    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:78)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
    at client.MyAppServerService$_persistCurrentSession_closure2.doCall(MyAppServerService.groovy:49)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSite.invoke(PogoMetaMethodSite.java:226)
    at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:52)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
    at client.MyAppServerService$_persistCurrentSession_closure2.doCall(MyAppServerService.groovy)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1053)
    at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:1071)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:883)
    at groovy.lang.Closure.call(Closure.java:410)
    at groovy.lang.Closure.call(Closure.java:404)
    at java_util_concurrent_Callable$call.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:112)
    at client.MyAppServerService$_withMyRest_closure4.doCall(MyAppServerService.groovy:71)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSite.invoke(PogoMetaMethodSite.java:226)
    at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:52)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
    at client.MyAppServerService$_withMyRest_closure4.doCall(MyAppServerService.groovy)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1053)
    at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:1071)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:883)
    at groovy.lang.Closure.call(Closure.java:410)
    at groovy.lang.Closure.call(Closure.java:404)
    at java_util_concurrent_Callable$call.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
    at java_util_concurrent_Callable$call.call(Unknown Source)
    at griffon.plugins.rest.RestConnector.doWithBuilder(RestConnector.groovy:90)
    at griffon.plugins.rest.RestConnector.this$2$doWithBuilder(RestConnector.groovy)
    at griffon.plugins.rest.RestConnector$this$2$doWithBuilder.callCurrent(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46)
    at griffon.plugins.rest.RestConnector$this$2$doWithBuilder.callCurrent(Unknown Source)
    at griffon.plugins.rest.RestConnector.withRest(RestConnector.groovy:67)
    at griffon.plugins.rest.RestConnector$withRest.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
    at griffon.plugins.rest.RestConnector$withRest.call(Unknown Source)
    at griffon.plugins.rest.RestConnector$_enhance_closure5.doCall(RestConnector.groovy:49)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod.invoke(ClosureMetaMethod.java:80)
    at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoMetaMethodSiteNoUnwrapNoCoerce.invoke(PogoMetaMethodSite.java:308)
    at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:52)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:145)
    at client.MyAppServerService.withMyRest(MyAppServerService.groovy:68)
    at client.MyAppServerService$withMyRest.callCurrent(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
    at client.MyAppServerService.persistCurrentSession(MyAppServerService.groovy:48)
    at client.MyAppServerService$persistCurrentSession.callCurrent(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:137)
    at client.MyAppServerService.closeSession(MyAppServerService.groovy:41)
    at client.MyAppServerService$closeSession.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:112)
    at client.StartController$_closure1_closure2.doCall(StartController.groovy:20)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSite.invoke(PogoMetaMethodSite.java:226)
    at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:52)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
    at client.StartController$_closure1_closure2.doCall(StartController.groovy)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    ... 14 more

我相信有更好的方法来做我想做的事情,但即便如此,我认为我想做的事情应该是可行的。我对Groovy还是一个新手,但是我已经对作用域规则进行了很多次研究,我所能想到的是,HTTPBuilder的动态方法没有通过传递的闭包正确地连接,或者类似的东西。看起来发生的事情是闭包委托丢失了。委托是groovy闭包工作方式的重要组成部分。每个闭包都有一个与之关联的委托对象,在闭包中调用的任何方法都可以在委托上调用。可以使用自定义确切的顺序,但默认的顺序是首先在所有者(声明闭包的地方)上尝试该方法,然后在委托上尝试。始终可以使用
delegate
在闭包中显式引用委托

委托是提供像
setHeaders()
这样神奇的动态方法的主要机制。当HttpBuilder调用传入的闭包时,它会设置显式闭包的委托,但会跳过
stmts()。您只需将委托传递给
stmts()
。试着这样做:

def withMyRest(Closure stmts) {
    withRest(uri: serverBaseURL) {
        headers = requestHeaders
        stmts.delegate = delegate
        stmts()
    }
}

就在钱上。你必须按照ataylor的建议将代理链接起来。是的,这正是我所需要的。谢谢