Gradle Goodness: Getting Project Information Into Rule Based Model Configuration

Rule based model configuration in Gradle allows us to have a graph of objects with dependencies that are resolved by Gradle. To make this work Gradle needs to know about the object in this model space. The model space is populated with objects of our own and with objects from Gradle. At time of writing this blog post we can not interact with the Gradle Project object in our rule based model configuration. It is not officially part of the model space. Probably in the future this might change and will the Project object managed by Gradle be part of the model space. Which means we can use then a Project object as input parameter for any rule methods we have. For now the official way to pass project information to the rule based model space is via the model configuration block in our build script. The model configuration block can be used to set properties on objects with values from our Project object.

In the following example we have VersionFile object that is part of the model space.

The rules to create the VersionFile object and to use this object to add a new task are defined in the file VersionFileTaskRules:

The custom task is not very exiting:

If we want to set the version property with the project.version value we use the model configuration in our build script:

We run the model task to see that our VersionFile object has the right property values:

Because the Project object is not part of the managed model space, we can not give the version property of VersionFile a default value that is the project.version property value. In our example we can give the version property of the VersionFileTask a default value that is project.version. So if the we don’t use the model configuration block the version value of the Project object is used in the task. Unfortunately we cannot see this default from the model task.

There are some internal objects created by Gradle that represent the project build directory and the Project object. The build directory can be accessed as input argument using the syntax @Path('buildDir') File and the project as ProjectIdentifier. But these are for internal use and can be removed or changed without warning. So to have a set of rules for the model space that will be useable in future Gradle versions we must not rely on those objects.

Another workaround, which might not work in the future, would be to rely on the ExtensionContainer object that is available in the model space. Gradle adds this as a hidden object, so also here we need to keep in mind this solution might not work in future Gradle versions. We could write an extension that wraps the Project object and add it to the ExtensionContainer. Next we use the ExtensionContainer as input argument for a rule method to get the extension with the wrapper Project object. The create the extension we use a custom Gradle plugin:

In our build file we apply the plugin and do not use the model configuration:

When we run the model task we see the setVersionFileDefaults method is used to set VersionFile properties:

Written with Gradle 3.2.

Original blog post

This entry was posted in Coding, Gradle and tagged by mrhaki. Bookmark the permalink.

About mrhaki

My name is Hubert A. Klein Ikkink also known as mrhaki. I work at the great IT company JDriven. Here I work on projects with Groovy & Grails, Gradle and Spring. At JDriven we focus on SpringSource technologies. All colleagues want to learn new technologies, support craftmanship and are very eager to learn. This is truly a great environment to work in. You can contact me via Google+ or @mrhaki.

Leave a Reply

Your email address will not be published. Required fields are marked *