groovyjenkins-pipelinejenkins-shared-libraries

Possibility to disable the property syntax for accessing a getter in groovy?


Let's I have a groovy class like:

class SomeClass {
    String myProperty = 'foo'
}

Usually in groovy is will be totally valid to access the value using the property name or the getter - which usually gives the same result for SomeClass:

SomeClass someClass = new SomeClass()
assert someClass.myProperty == 'foo'
assert someClass.getMyProperty() == 'foo'

However - due to a flaw in the Jenkins Pipeline implementation - sometimes(!) you are forced to use the getter - as the plain property access will not work (when using some class hierarchy), see: JENKINS-47143. Bad thing is that the same code may work for some jobs while it doesn't for others:

SomeClass someClass = new SomeClass()
assert someClass.myProperty == 'foo' // sometimes throws 'property not found' error
assert someClass.getMyProperty() == 'foo'

Now I already have couple of unit tests for our Jenkins shared library - but what is missing would be a way to detect a property access, in short: A way to prohibit the property access so the unit tests will already complain in advance.


Solution

  • The following code:

    class SomeClass { 
      String myProperty = 'foo'
    }
    
    SomeClass.metaClass.getProperty = { String name -> 
      throw new RuntimeException("tried to get property ${name}, property access only allowed via getXX() methods")
    }
    
    def s = new SomeClass()
    
    println(s.myProperty)       // a
    println(s.getMyProperty())  // b
    
    

    will throw an exception for line a but not throw an exception for line b. I suspect this will not be possible if SomeClass was written in java, but assuming a groovy class this could be a way to accomplish what you want.

    Running the above will result in:

    ā”€āž¤ groovy solution.groovy
    Caught: java.lang.RuntimeException: tried to get property myProperty, property access only allowed via getXX() methods
    java.lang.RuntimeException: tried to get property myProperty, property access only allowed via getXX() methods
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    ...