How to return 'configurations.runtime.artifacts.files' from a method?

Context: I have a task that works fine:

task copyArtifactJars(type: Copy) {
    from(configurations.runtime.artifacts.files)
    into signdir
  }

But, I want to have the files list come from a method so I can process the list before returning it.

If I simply change the above task to be:

task copyArtifactJars(type: Copy) {
    from(getRuntimeArtifacts())
    into signdir
  }
  def getRuntimeArtifacts() { configurations.runtime.artifacts.files }

then it no longer works, complaining: groovy.lang.MissingPropertyException: Could not find property ‘runtime’ on configuration container.

Is this because the configurations.runtime expression is getting evaluated during the Configuration phase, and that expression isn’t valid yet?

So I tried delaying evaluation by wrapping the returned expression in a closure, but then I got the exception: org.gradle.api.GradleException: Could not determine the dependencies of task ‘:foo:copyArtifactJars’.

How can I calculate a processed list of artifacts for my Copy Task?

Thanks, Neil

Update:

Actually, after wrapping the returned expression in a closure (trying to delay evaluation), I got the exception:

org.gradle.api.GradleException: Could not determine the dependencies of task ‘:foo:copyArtifactJars’. but it has a cause of: Caused by: groovy.lang.MissingPropertyException: Could not find property ‘runtime’ on configuration container.

If I declare the @InputFiles another way will that stop the closure from getting evaluated early?

The configuration ‘runtime’ is introduced by the Java plugin. You will need to apply that plugin or define your own configuration.

The groovy plugin is applied - that supplies ‘runtime’, right?

I’m trying to understand:

  • why using configurations.runtime works when supplied to the from, but doesn’t work when returned from a method

  • how to fix it (and I describe some attempts to fix it above)

P.S. Your book is very good, btw. Thank you.

That’s right. The Groovy plugin applies the Java plugin.

For me your code works. This is what I have:

apply plugin: 'groovy'
  ext.signdir = 'signing'
  task copyArtifactJars(type: Copy) {
    from(getRuntimeArtifacts())
    into signdir
}
    def getRuntimeArtifacts() {
     configurations.runtime.artifacts.files
 }

Hmm… interesting.

My real project has several subprojects in a single build.gradle file.

The copyArtifactJars task is in one of the subprojects, but I can’t put the method in the subproject with it (because of the nesting in the build.gradle file).

Is that why it doesn’t work for me - subprojects in a single build file?

My guess is that you are not applying the Groovy plugin to that specific project. I’d need to see the full build script to identify what’s wrong.

This is my subprojects block:

subprojects {
  apply plugin: 'groovy'
    repositories {
    mavenCentral()
  }
    dependencies {
    compile group: 'org.codehaus.groovy', name: 'groovy-all', version: '2.2.2'
    compile files("${System.properties['java.home']}/lib/ext/jfxrt.jar")
 // todo in Java 7 it is in /lib - push the calculation into a method
    testCompile group: 'org.spockframework', name: 'spock-core', version: '0.7-groovy-2.0'
  }
}

This applies the Groovy plugin to all of my subprojects, right?

Yeah, that should do it. Could you please provide an isolated build script that reproduces your issue? At the moment I can’t see what’s wrong.