I am trying out an approach in which the caller receives a closure as a return value from a function so that the context can be preserved for further call chaining. I tried the below as a test and it didn't work:
def prep() {
return [run: {-> echo "Hello Closure"}]
}
pipeline {
agent "any"
stages {
stage("Init") {
steps {
script {
p = prep()
p.run()
}
}
}
}
}
The error I see in the console log is:
hudson.remoting.ProxyException: groovy.lang.MissingMethodException: No signature of method: java.util.LinkedHashMap.run() is applicable for argument types: () values: []
Possible solutions: min(groovy.lang.Closure), put(java.lang.Object, java.lang.Object), put(java.lang.Object, java.lang.Object), find(), any(), grep()
at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onMethodCall(SandboxInterceptor.java:131)
at org.kohsuke.groovy.sandbox.impl.Checker$1.call(Checker.java:155)
at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:159)
at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.methodCall(SandboxInvoker.java:17)
at WorkflowScript.run(WorkflowScript:14)
at ___cps.transform___(Native Method)
...
When I tried to return the closure directly instead of a map it worked fine:
def prep() {
return {-> echo "Hello Closure"}
...
p = prep()
...
Also, if I extract the map element first, it works fine (when I called the local variable as run, I got the script security error: Scripts not permitted to use method java.lang.Runnable run):
And this works too:
but this is not elegant. Is this a bug or expected behavior? The below equivalent worked fine in script console:
def prep() {
return [run: {-> print("Hello Closure")}]
}
prep().run()