Gradle 5.0 - @Field variable "visibility" issue

Using Gradle 5.0, I’ve come across an issue where variable(s) declared with @Field annotation @Field def varname = "<value>" (groovy.transform.Field package) - cannot be used to retrieve its value (value is “invisible” - in a sense). Apparently, Gradle 5.0 automatically defines variables declared with @Field as write-only values, raising following error when such variable is used in a “read” mode (when its value is being read/retrieved):

Cannot get the value of write-only property '<varname>' for script of type <typename>

I have created a very simple test script (that does nothing other than to test this particular behavior), and using that script - demonstrated that same script succeeds (works as expected) using Gradle 4.7 and 4.9, but fails using Gradle 5.0.

Here’s build.gradle:

buildscript {
	dependencies {
		classpath group: 'com.idexx.instruments', name: 'NativeCommon', version: '2.11.0.2'
	}
}

apply plugin: 'com.idexx.instruments.nativecommon'

apply from: 'test.gradle'

… and here’s content of test.gradle:

    import groovy.transform.Field;

    @Field def deployRoot = "/deploy"

    print "\$this.deployRoot 1: ${this.deployRoot}\n"
    print "\$deployRoot 1: ${deployRoot}\n\n"

    def proc(buildtype, flavor) {
    	print "\$this.deployRoot 2: ${this.deployRoot}\n"
    	print "\$deployRoot 2: ${deployRoot}\n"
    	print "\$buildtype 2: ${buildtype}\n"
    	print "\$flavor 2: ${flavor}\n\n"
    	
    	def closure1 = {
    		print "\$this.deployRoot 3: ${this.deployRoot}\n"
    		print "\$deployRoot 3: ${deployRoot}\n"
    		print "\$buildtype 3: ${buildtype}\n"
    		print "\$flavor 3: ${flavor}\n\n"
    		
    		def closure2 = {
    			print "\$this.deployRoot 4: ${this.deployRoot}\n"
    			print "\$deployRoot 4: ${deployRoot}\n"
    			print "\$buildtype 4: ${buildtype}\n"
    			print "\$flavor 4: ${flavor}\n\n"
    		}
    		
    		closure2()
    	}
    	
    	closure1()
    }

    model {
      tasks {
    	  def buildtype = "x64"
    	  def flavor = "gen5"
    	  
    	  print "\$this.deployRoot 1.1: ${this.deployRoot}\n"
    	  print "\$deployRoot 1.1: ${deployRoot}\n"
    	  print "\$buildtype 1.1: ${buildtype}\n"
    	  print "\$flavor 1.1: ${flavor}\n\n"
    	  
    	  proc(buildtype, flavor)
      }
    }

When ‘build’ is executed using Gradle 4.7 or 4.9 - build succeeds, and variables are printed:

    ./gradlew build

    > Configure project :

    $this.deployRoot 1: /deploy
    $deployRoot 1: /deploy

    $this.deployRoot 1.1: /deploy
    $deployRoot 1.1: /deploy
    $buildtype 1.1: x64
    $flavor 1.1: gen5

    $this.deployRoot 2: /deploy
    $deployRoot 2: /deploy
    $buildtype 2: x64
    $flavor 2: gen5

    $this.deployRoot 3: /deploy
    $deployRoot 3: /deploy
    $buildtype 3: x64
    $flavor 3: gen5

    $this.deployRoot 4: /deploy
    $deployRoot 4: /deploy
    $buildtype 4: x64
    $flavor 4: gen5

    BUILD SUCCESSFUL in 0s

    Publishing build scan...

    https://gradle.is.idexx.com/s/n7ay6rxv6pq6u

When same build is executed using 5.0 - it fails:

    ./gradlew build

    > Configure project :

    $this.deployRoot 1: /deploy
    $deployRoot 1: /deploy

    FAILURE: Build failed with an exception.

    * Where:

    Script '/Users/vpogrebi/workspace/GRADLE-5.0-TEST/tarball.gradle' line: 38

    * What went wrong:

    A problem occurred configuring root project 'GRADLE-5.0-TEST'.

    > Exception thrown while executing model rule: tasks { ... } @ test.gradle line 34, column 3

    > Cannot get the value of write-only property 'deployRoot' for script of type tarball_9hwxnyg54b3wd07obhfi83pg1.

    * Try:

    Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

    * Get more help at https://help.gradle.org

    Deprecated Gradle features were used in this build, making it incompatible with Gradle 6.0.

    Use '--warning-mode all' to show the individual deprecation warnings.

    See https://docs.gradle.org/5.0/userguide/command_line_interface.html#sec:command_line_warnings

    BUILD FAILED in 0s

    Publishing build scan...

    https://gradle.is.idexx.com/s/5topxtmmkvpom

I was able to resolve this issue - using global variable declaration (project.ext) instead of @Field annotation:

project.ext.varname = <value>

… but using global variables is not a good practice, and I could not find any other, better solution

Does anyone know what causes this behavior, and how to fix it (without resorting to project.ext)? I did not find anything that would explain this behavior, and suggest a fix for it - within Gradle 5.0 upgrade documentation.

2 Likes

Thanks so much for posting this. I’m also experiencing this issue. @vpogrebi have you had any luck finding a workaround?

Edit: I have made a stackoverflow question and GitHub issue for this post.