Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Closures in JenkinsFile groovy - callbacks or delegate

I want to be able to add a callback as a parameter in a Jenkins Groovy script. I think a closure is what I need, but I don't know how to do it. Here is the output I want:

enter
hello
exit

JenkinsFile:

def rootDir = pwd()
def tools = load "${rootDir}\\patchBuildTools.groovy"
mainMethod(tools.testCl("hello"))

patchBuildTools.groovy

def mainMethod(Closure test) {
    println "enter"
    test()
    println "exit"
}


def testCl(String message) {
    println message
}

This gives me an out put of :

hello
enter
java.lang.NullPointerException: Cannot invoke method call() on null object

Is it possible to get the call order I want?

Update - based on the answer

JenkinsFile:

def rootDir = pwd()
def tools = load "${rootDir}\\patchBuildTools.groovy"
mainMethod("enter", "exit")
{
  this.testCl("hello")
}

patchBuildTools.groovy

def mainMethod(String msg1, String ms2, Closure test) {
  println msg1
  test()
  println ms2
}



def testCl(String message) {
    println message
}
like image 544
pogorman Avatar asked May 18 '18 15:05

pogorman


People also ask

How do closures work in Groovy?

A closure is an anonymous block of code. In Groovy, it is an instance of the Closure class. Closures can take 0 or more parameters and always return a value. Additionally, a closure may access surrounding variables outside its scope and use them — along with its local variables — during execution.

What is Groovy delegate?

The delegate of a closure is an object that is used to resolve references that cannot be resolved within the body of the closure itself. If your example was written like this instead: def say = { def m = 'hello' println m } say.delegate = [m:2] say() It prints 'hello', because m can be resolved within the closure.

How do I return a Groovy closure?

We can even return closures from methods or other closures. We can use the returned closure to execute the logic from the closure with the explicit call() method or the implicit syntax with just the closure object followed by opening and closing parentheses ( () ).

Is Jenkinsfile written in Groovy?

The Jenkinsfile is written using the Groovy Domain-Specific Language and can be generated using a text editor or the Jenkins instance configuration tab. The Declarative Pipelines is a relatively new feature that supports the concept of code pipeline.


1 Answers

You might have misunderstood how closures work - a closure is an anonymous function which you can pass to another function and execute.

Having said that, in your example you are passing the result of testCl(), which is a String, to mainMethod(). This is wrong, because mainMethod expects a Closure and not a String as the passed argument.

I am not sure what you are trying to achieve, but here is how you could use a Closure:

Jenkinsfile

def rootDir = pwd()
def tools = load "${rootDir}\\patchBuildTools.groovy"
mainMethod() {
    // everything you put here is the closure that will be passed
    // as the argument "body" in the mainMethod() (inside patchBuildTools.groovy)
    echo "hello world from Closure"
}    

patchBuildTools.groovy

def mainMethod(Closure body) {
    println "enter"
    body() // executes the closure passed with mainMethod() from the Jenkinsfile.
    println "exit"
}

Result

enter
hello world from Closure
exit
like image 183
tftd Avatar answered Nov 15 '22 07:11

tftd