Jenkins: Check whether a DSL method exists
Tags: automation, cpsscript, groovy, jenkins
Published: 2020-11-17 15:59:31

---
title: Jenkins: Check whether a DSL method exists
published: true
date: 2020-11-10 15:00:00 UTC
tags: Automation,CpsScript,Groovy,Jenkins
canonical_url: https://gerg.dev/2020/11/jenkins-check-whether-a-dsl-method-exists/
---

Occasionally when working with Jenkinsfiles, you’ll run into a `NoSuchMethodError` because of calling a function that Jenkins’s doesn’t know about:

```
java.lang.NoSuchMethodError: **No such DSL method 'someFunc'** found among [...]
```

There are number of reasons that this can happen, such as a required plugin not being installed, or the [shared library](https://www.jenkins.io/doc/book/pipeline/shared-libraries/) that defines the function isn’t loaded.

Lately I have been working a lot with shared libraries and building up functionality that is designed for multiple people to use, without necessarily knowing the technical details of each product. I occasionally want to check if a function is available before running some code to avoid the `NoSuchMethodError`, but I don’t want to block everything if it isn’t available. This allows making libraries more robust by not failing when an optional dependency is missing.

So, how do we check if a DSL method exists before calling it?

Based on the stacktrace that came with the error, I ended up poking around [the source code for the CpsScript class](https://github.com/jenkinsci/workflow-cps-plugin/blob/master/src/main/java/org/jenkinsci/plugins/workflow/cps/CpsScript.java) to see how it detected this problem. It turns out that in a pipeline script we can use the `this` object to get the bindings available on the script itself, and check whether a given method exists. This is all you need:

```
this.getBinding().hasVariable('foobar')
```

That expression will evaluate to `true` if `foobar` exists, and `false` if it doesn’t.

For convenience, if we’re doing this multiple times, we can write a simple function in the pipeline itself:

```
boolean dslMethodExists(String name) {
    return this.getBinding().hasVariable(name)   
}

if (dslMethodExists('foobar')) {
    foobar()
}
```

If you wanted to take advantage of this across multiple Jenkinsfiles, the function can go into a shared library function. However, in that context `this` will no longer point to the pipeline script being executed. We can still do the check by passing a reference to the current script directly:

```
// vars/dslMethodExists.groovy in a shared library

import org.jenkinsci.plugins.workflow.cps.CpsScript

boolean call(CpsScript script, String name) {
    return script.getBinding().hasVariable(name)
}
```

I’m importing the `CpsScript` class just so I can declare its type in the function signature; it’s good practice to avoid `def`, and it helps future developers know what class they’re working with explicitly.

Then, as long as that shared library is loaded, you can call that function in your pipelines, or even in other shared library functions:

```
if (dslMethodExists('foobar')) {
    foobar()
}
```

And that’s all there is to it. I don’t guarantee that this is the best way to check for a DSL method—as I said I went poking around in the source code to find this—but it works. I googled this enough times, without finding an answer, that when I finally figured it out I thought I should put it up here in the hopes it’ll help someone else.