0

I've defined a class SomeClass with a method

class SomeClass implements Serializable {

    void someMethod(String var1, String var2, String... vars) {
        ...
    }
}

which I'm using in a declarative pipeline as follows:

SomeClass instance = new SomeClass(this)

pipeline {

    environment {
        VAR1 = "var1"
        VAR2 = sh(returnStdout: true, script: "echo var2").trim()
        VAR3 = "var3"
    }

    stages {
        stage("Stage X") {
            steps {
                script {
                    instance.someMethod("${VAR1}", "${VAR2}", "${VAR3}")
                }
            }
        }
    }
}

which fails due to

hudson.remoting.ProxyException: groovy.lang.MissingMethodException: No signature of method: org.jenkinsci.plugins.docker.workflow.SomeClass.someMethod() is applicable for argument types: (org.codehaus.groovy.runtime.GStringImpl, org.codehaus.groovy.runtime.GStringImpl, org.codehaus.groovy.runtime.GStringImpl) values: [var1, var2, var3]

If I change the invocation to instance.someMethod(VAR1.toString(), VAR2.toString(), VAR3.toString()) it fails due to

hudson.remoting.ProxyException: groovy.lang.MissingMethodException: No signature of method: org.jenkinsci.plugins.docker.workflow.SomeClass.someMethod() is applicable for argument types: (java.lang.String, java.lang.String, java.lang.String) values: [var1, var2, var3]

Afaik at least one of them should work. I think Groovy should be capable of making both work, but that's a second step. How can I invoke the method with the given arguments?

Kalle Richter
  • 8,008
  • 26
  • 77
  • 177
  • 1
    I suspect the issue isn't the parameters, but that it can't see the method at all. Is SomeClass in groovy? Are you sure it's on the classpath? Are you sure the code you're editing is the one on the classpath? – tim_yates Dec 30 '19 at 18:43
  • Additionally you are passing in variables with empty/null values as the parameters to the method, which may be problematic in this case. – Matthew Schuchard Dec 30 '19 at 18:56
  • Agree with Tim above, tried in various ways and permutations (all versions of java from 1.6 to 13, groovy 2.3.x, 2.4.x, 2.5.x etc) to reproduce this in pure groovy and no luck. I would guess this is caused by some strange visibility / classloader thing in the jenkins pipeline construct. What happens if you instantiate the class inside the `script {...}` block right above the calling line? – Matias Bjarland Dec 30 '19 at 20:52

2 Answers2

0

You can pass script object to the method. You can find information here and here.

Code below print variable:

SomeClass instance = new SomeClass()

pipeline {
    agent any

    environment {
        VAR1 = "var1"
        VAR2 = sh(returnStdout: true, script: "echo var2").trim()
        VAR3 = "var3"
    }

    stages {
        stage("Stage X") {
            steps {
                script {
                    instance.someMethod(this, "${VAR1}", "${VAR2}", "${VAR3}")
                    //instance.someMethod("${VAR1}", "${VAR2}", "${VAR3}")
                }
            }
        }
    }
}

class SomeClass implements Serializable {
    void someMethod(def script, String var1, String var2, String... vars) {
        script.echo "someMethod: ${var1}"
    }
}
Sers
  • 12,047
  • 2
  • 12
  • 31
0

The reason was a type in instance when invoking instance.someMethod. Sorry for not doing a clean copy and paste from the reproducer. I'm surprised by the exception, though - very misleading to say the method doesn't exist if the instance it's called on doesn't even exist.

Kalle Richter
  • 8,008
  • 26
  • 77
  • 177