[Pipeline Shared Libraries] acme.foo = "5" documented example doesn't work

139 views
Skip to first unread message

Rob Oxspring

unread,
Oct 27, 2016, 8:50:37 AM10/27/16
to Jenkins Users
Hi,

I've been trying to use a shared library script with properties according to the following but am having no luck.

To reproduce I've installed a totally clean Jenkins LTS with recommend plugins and added a $JENKINS_HOME/workflow-libs/vars/acme.groovy containing 
def setFoo(v) {
    this.foo = v;
}
def getFoo() {
    return this.foo;
}
def say(name) {
    echo "Hello world, ${name}"
}

I have a Pipeline job configured with the following script:
echo "myjob"

acme.foo = "5";
echo acme.foo; // print 5
acme.say "Joe" // print "Hello world, Joe"

And when I run it I get the following result:
[Pipeline] echo
myjob
[Pipeline] End of Pipeline
groovy.lang.MissingPropertyException: No such property: acme for class: groovy.lang.Binding
    at groovy.lang.Binding.getVariable(Binding.java:63)
    at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetProperty(SandboxInterceptor.java:224)
    at org.kohsuke.groovy.sandbox.impl.Checker$4.call(Checker.java:241)
    at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:238)
    at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.getProperty(SandboxInvoker.java:24)
    at com.cloudbees.groovy.cps.impl.PropertyAccessBlock.rawGet(PropertyAccessBlock.java:20)
    at WorkflowScript.run(WorkflowScript:3)
    at ___cps.transform___(Native Method)
    at com.cloudbees.groovy.cps.impl.PropertyishBlock$ContinuationImpl.get(PropertyishBlock.java:74)
    at com.cloudbees.groovy.cps.LValueBlock$GetAdapter.receive(LValueBlock.java:30)
    at com.cloudbees.groovy.cps.impl.PropertyishBlock$ContinuationImpl.fixName(PropertyishBlock.java:66)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
    at com.cloudbees.groovy.cps.impl.ConstantBlock.eval(ConstantBlock.java:21)
    at com.cloudbees.groovy.cps.Next.step(Next.java:58)
    at com.cloudbees.groovy.cps.Continuable.run0(Continuable.java:154)
    at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.access$001(SandboxContinuable.java:18)
    at org.jenkinsci.plugins.workflow.cps.SandboxContinuable$1.call(SandboxContinuable.java:33)
    at org.jenkinsci.plugins.workflow.cps.SandboxContinuable$1.call(SandboxContinuable.java:30)
    at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.GroovySandbox.runInSandbox(GroovySandbox.java:108)
    at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.run0(SandboxContinuable.java:30)
    at org.jenkinsci.plugins.workflow.cps.CpsThread.runNextChunk(CpsThread.java:163)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:324)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.access$100(CpsThreadGroup.java:78)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:236)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:224)
    at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:63)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:112)
    at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:28)
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Finished: FAILURE

I did wonder whether to "def foo" in order to create the property but that just results in an infinite recursion as this.foo = v within setFoo() gets interpreted as a recursive call to setFoo() itself.

Any clues where I'm going wrong?

Thanks,

Rob

Michael Lasevich

unread,
Oct 27, 2016, 5:51:09 PM10/27/16
to Jenkins Users
You are not doing anything wrong. CPS is just broken in this scenario. You cannot have both a field and a getter/setter at the same time with matching names - it gets confused and goes into infinite loop. Change 'this.foo' to 'this._foo' and it will start working (and you can still use "acme.foo" to call setter/getter versions. It is vert annoying and cost me days of scratching my head until I realized what was going on.

For what its worth, Groovy itself supports this, but something in CPS/Pipelines breaks that support.

-M
Reply all
Reply to author
Forward
0 new messages