-
Bug
-
Resolution: Unresolved
-
Major
-
None
Still trying to figure out how to describe this exactly. =)
There are two cases that are related that I can reproduce. First, in a single Jenkinsfile:
class C { int x = 33 int getX() { 2 * this.@x } } class D extends C { int getY() { 2 * getX() } } new D().y
This results in groovy.lang.MissingFieldException: No such field: x for class: D, with the following stacktrace:
at groovy.lang.MetaClassImpl.getAttribute(MetaClassImpl.java:2823) at groovy.lang.MetaClassImpl.getAttribute(MetaClassImpl.java:3759) at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.getGroovyObjectField(ScriptBytecodeAdapter.java:356) at com.cloudbees.groovy.cps.sandbox.DefaultInvoker.getAttribute(DefaultInvoker.java:53) at com.cloudbees.groovy.cps.impl.AttributeAccessBlock.rawGet(AttributeAccessBlock.java:20) at C.getX(Script1.groovy:1) at D.getY(Script1.groovy:1) at Script1.run(Script1.groovy:1)
The second I can't reproduce in a single Jenkinsfile - each of the inheriting classes need to be in a shared library, and it needs multiple levels of inheritance.
class BaseAction { String someActionValue = "thevalue" }
class ChildAction extends BaseAction { def doSomething() { return "in ChildAction: " + someActionValue } }
class GrandChildAction extends ChildAction { def doSomething() { return "in GrandChildAction: " + someActionValue } }
With the Jenkinsfile:
@Library("config@master") _ import ChildAction import GrandChildAction println new ChildAction().doSomething() println new GrandChildAction().doSomething()
This results in groovy.lang.MissingFieldException: No such field: someActionValue for class: GrandChildAction with the following stacktrace:
at groovy.lang.MetaClassImpl.getAttribute(MetaClassImpl.java:2846) at groovy.lang.MetaClassImpl.getAttribute(MetaClassImpl.java:3782) at org.codehaus.groovy.runtime.InvokerHelper.getAttribute(InvokerHelper.java:147) at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.getField(ScriptBytecodeAdapter.java:306) at com.cloudbees.groovy.cps.sandbox.DefaultInvoker.getAttribute(DefaultInvoker.java:48) at com.cloudbees.groovy.cps.impl.AttributeAccessBlock.rawGet(AttributeAccessBlock.java:20) at GrandChildAction.doSomething(/private/var/folders/pr/24nv8g910wg8vr4b4c33q34r0000gn/T/jenkinsTests.tmp/jenkins6831451434103658873test/jobs/p/builds/1/libs/config/src/GrandChildAction.groovy:4) at WorkflowScript.run(WorkflowScript:5)
I left a comment detailing my investigation into this so far over on JENKINS-50736:
What's actually happening is that we're actually calling (via some layers of abstraction) InvokerHelper.getAttribute(object, name), which ends up getting the MetaBeanProperty for that object/name combo. And the field field of that MetaBeanProperty is null. This is the same behavior you get in vanilla Groovy if you do this.@someField in the subclass. So the problem seems to be that you can't actually call InvokerHelper.getAttribute(object, name) for a field on a superclass, and our hacks to avoid recursion hell with getter methods (which I think was intended primarily to deal with explicit getters, not autogenerated getters, but don't quote me on that) will end up doing that.
How to fix this? Well, I've got a couple hacks I've tried that seem to "fix" this for some value of "fixed" - most notably changing DefaultInvoker#getAttribute(lhs, name) to catch MissingFieldException when it shows up and try forcing a MetaClass#getAttribute call with InvokerHelper.getMetaClass(lhs.getClass().getSuperclass()), recursing on until we get to Object.class. But that feels really really dirty, so I'm trying to think of something better.
So at a minimum, we're not properly handling references to fields as attribute expressions (i.e., this.@foo) in a superclass, even if the child class never actually references the field-as-attribute directly, just via a superclass method (note that it doesn't have to be in a getter method like getX to blow up - I used a different method name and it still went kerplooie).
Needs more thought and explanation, but I wanted to give this a separate JIRA for clarity.
- relates to
-
JENKINS-50736 Calling another vars step in inheritance context fails with MissingMethodException
-
- Open
-