How do you use a conventionMapping to do the following?

I have a plugin where I need to optionally pass a reference to a custom configuration as an optional property on the jar task. (By default I use “configurations.provided” to populate the Jar but I need to be able to use some other configuration configured by the plugin user.) My first thought was to use a conventionMapping to set the default value but I can’t seem to get it to set the value (see error message below). Amongst other things the property needs to be used to set a dependent tasks inputs.files.

Here is my failure with the conventionMapping and my work around. Any suggestions on the best way to do this.

apply plugin: CqProvidedPlugin
class CqProvidedPlugin implements Plugin<Project> {
    void apply(Project project) {
        project.configure(project) {
            apply plugin: 'java'
            jar {
                dependsOn 'extractPackage'
                classifier = 'provided'
                conventionMapping.configure = { configurations.provided }
                manifest {
                    attributes 'Implementation-Title': 'Compile time only package of provided public interface classes.'
                }
            }
            task('extractPackage') {
                group ''
                description ''
                File extractJarDir = file("${buildDir}/tmp/extractedArchives")
                File extractClassDir = file("${buildDir}/classes/main")
                inputs.files jar.convention
                outputs.files fileTree(extractClassDir)
                doLast {
                    extractBundles(extractJarDir, extractClassDir, jar.configuration)
                }
            }
...

gives me the error message:

FAILURE: Build failed with an exception.

  • Where: Script ‘C:\Users\fstaats\Desktop\feature-build-automation\gradle\cqProvided.gradle’ line: 18

  • What went wrong: A problem occurred evaluating script. > You can’t map a property that does not exist: propertyName=configuration

  • Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

Total time: 18.119 secs

I tried several ways to “create” the property on the jar task but none seemed to work when using a predefined task like “jar”. My current work around is the following:

apply plugin: CqProvidedPlugin class CqProvidedPlugin implements Plugin {

void apply(Project project) {

project.configure(project) {

apply plugin: ‘java’

jar {

dependsOn ‘extractPackage’

classifier = ‘provided’

manifest {

attributes ‘Implementation-Title’: ‘Compile time only package of provided public interface classes.’

}

}

task(‘extractPackage’) {

group ‘’

description ‘’

File extractJarDir = file("${buildDir}/tmp/extractedArchives")

File extractClassDir = file("${buildDir}/classes/main")

outputs.files fileTree(extractClassDir)

doLast {

extractBundles(extractJarDir, extractClassDir, jar.configuration)

}

}

// TODO: Find a cleaner way to do this with a Convention object and a conventionMapping

gradle.taskGraph.whenReady {

if (!jar.hasProperty(‘configuration’)) {

jar.setProperty(‘configuration’, configurations.provided)

}

// We set the inputs here as the plugin user sets the inputs and it is too late to set in doLast()

tasks.extractPackage.inputs.files jar.configuration

} … </code

I’d avoid convention mappings at this time whenever possible as they are an internal mechanism and potentially subject to change.

In this case, I’d introduce an extension and some indirection to achieve this:

class CqProvidedExtension {
    FileCollection jarSource
}
  class CqProvidedPlugin implements Plugin {
  void apply(Project project) {
    project.extensions.add("cqProvided", new CqProvidedExtension())
    // for milestone-9 and up
    // project.extensions.create("cqProvided", CqProvidedExtension)
       // default
    project.cqProvided.jarSource = configurations.provided
      jar.from { project.cqProvided.jarSource }
  }
}

The use of ‘jar.from { }’ allows this to be evaluated lazily, allowing the user to change ‘project.cqProvided.jarSource’.