Over a million developers have joined DZone.

Gradle Goodness: Creation Rules For Rule Based Model Configuration Using Model DSL

Continuing to work with rule-based model configuration, see how you can define a model block and a creation rule using Gradle.

· Java Zone

Navigate the Maze of the End-User Experience and pick up this APM Essential guide, brought to you in partnership with CA Technologies

In a previous post, we learned how to create a class that extends RuleSource with methods that define rules on how to create and change objects in the Gradle model space. With the model configuration block in a build file we can also define creation rules for Rule based model configuration.

In the following build file, we define a model block and define a creation rule for creating the object versionInfo of type VersionFile. Also, we add a new task to the tasks object of type ModelMap<Task>. To reference another object from the model space inside the Closure for a creation rule we use the syntax $.<objectName>:

// File: model.gradle
import mrhaki.gradle.VersionFile
import mrhaki.gradle.VersionFileTask

model {
    // Creation rule to create object
    // with name versionInfo (name of the method)
    // and type VersionFile.
    versionInfo(VersionFile) {
        // Set default value for version to project.version.
        version = project.version
        
        // Set default outputFile to 
        // file version.txt in build directory.
        outputFile = project.file("${buildDir}/version.txt")
    }
    
    // tasks is of type ModelMap<Task>.
    tasks {
        // Create task generationVersionFile 
        // with custom task type VersionFileTask.
        create('generateVersionFile', VersionFileTask) {
            // Set properties with values
            // from managed object versionInfo,
            // that we created with the creation rule
            // versionInfo(VersionFile).
            // We use the special $.<name> notation
            // to reference object from the model space.
            version = $.versionInfo.version
            outputFile = $.versionInfo.outputFile
        }
    }
}

The supporting VersionFile class is a Gradle managed object:

// File: buildSrc/src/main/groovy/mrhaki/gradle/VersionFile.groovy
package mrhaki.gradle

import org.gradle.model.Managed

@Managed
interface VersionFile {
    String getVersion() 
    void setVersion(final String version) 

    File getOutputFile() 
    void setOutputFile(final File outputFile) 
}

And the custom task is very straight forward for our example:

// File: buildSrc/src/main/groovy/mrhaki/gradle/VersionFileTask.groovy
package mrhaki.gradle

import org.gradle.api.DefaultTask
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction

/**
 * Simple task to save the value for the
 * {@link #version} property in a file.
 * The file is set with the {@link #outputFile}
 * property.
 */
class VersionFileTask extends DefaultTask {

    /**
     * Value for version to be saved.
     */
    @Input
    String version

    /**
     * Output file to store version value in.
     */
    @OutputFile
    File outputFile

    /**
     * Actual task actions to save the value
     * for {@link #version} in {@link #outputFile}.
     */
    @TaskAction
    void generateVersionFile() {
        outputFile.parentFile.mkdirs()
        outputFile.text = version
    }

}

We can use the model rules in our build script when we use apply from: 'model.gradle' in our build script. In our example we also add a model configuration block to configure the versionInfo object:

// File: build.gradle
apply from: 'model.gradle'

model {
    // Configuration rule for the versionInfo
    // object, that is created with the
    // creation rule from 'model.gradle'.
    versionInfo {
        version = '3.0.0.RELEASE'
    }   
}

Let's invoke the model task and check the output to see where are rules are applied:

$ gradle -q model
...
 tasks
      | Type:           org.gradle.model.ModelMap<org.gradle.api.Task>
      | Creator:        Project.<init>.tasks()
      | Rules:
         ⤷ tasks { ... } @ model.gradle line 18, column 5
...
    + generateVersionFile
          | Type:       mrhaki.gradle.VersionFileTask
          | Value:      task ':generateVersionFile'
          | Creator:    create(generateVersionFile, mrhaki.gradle.VersionFileTask) { ... } @ model.gradle line 21, column 9
          | Rules:
             ⤷ copyToTaskContainer
...
+ versionInfo
      | Type:           mrhaki.gradle.VersionFile
      | Creator:        versionInfo(mrhaki.gradle.VersionFile) { ... } @ model.gradle line 8, column 5
      | Rules:
         ⤷ versionInfo { ... } @ build.gradle line 47, column 5
    + outputFile
          | Type:       java.io.File
          | Value:      /Users/mrhaki/Projects/mrhaki.com/blog/posts/samples/gradle/versionrule/build/version.txt
          | Creator:    versionInfo(mrhaki.gradle.VersionFile) { ... } @ model.gradle line 8, column 5
    + version
          | Type:       java.lang.String
          | Value:      3.0.0.RELEASE
          | Creator:    versionInfo(mrhaki.gradle.VersionFile) { ... } @ model.gradle line 8, column 5
...
$

Written with Gradle 3.2.

Thrive in the application economy with an APM model that is strategic. Be E.P.I.C. with CA APM.  Brought to you in partnership with CA Technologies.

Topics:
gradle ,java ,rule based model configuration ,dsl

Published at DZone with permission of Hubert Klein Ikkink, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}