1

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时会被抛出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 的动态方法没有通过传递的闭包或类似的东西正确附加

4

1 回答 1

3

看起来正在发生的事情是关闭代表迷路了。代表是 groovy 闭包如何工作的重要组成部分。每个闭包都有一个与之关联的委托对象,并且闭包中调用的任何方法都可以在委托上调用。确切的顺序可以使用Closure.setResolveStrategy自定义,但默认是先尝试所有者(声明闭包的地方)的方法,然后是委托。您始终可以在闭包内显式引用委托delegate

委托是提供那些神奇的动态方法的主要机制,例如setHeaders(). 当 HttpBuilder 调用您传入的闭包时,它会设置显式闭包的委托,但stmts()会被跳过。您需要做的就是将委托传递给stmts(). 尝试这样的事情:

def withMyRest(Closure stmts) {
    withRest(uri: serverBaseURL) {
        headers = requestHeaders
        stmts.delegate = delegate
        stmts()
    }
}
于 2011-12-20T18:08:15.313 回答