Migrating to Gradle: unedifact module

04 Apr 2011 - Daniel Bevenius

This is just a short blog about migrating to Gradle. First up is the unedifact module. The following were the immediate benifits as we see them:

  • Simpler versioning of the projects which was a hassle previously as we were using Maven inheritance.

  • Less files to maintain.

  • Easier to work around specific issues since we have access to the Groovy programming language.

  • Now we have project dependencies between the modules which means that we no longer have to build in a specific order, for example first install the mapping project before installing the binding project.

Background

The unedifact module is used to generate the mappings and bindings for various unedifact specifications. For each specification there is a subfolder that is named after the spec.

settings.gradle

This file is where we list all the projects that are to be included in this build. As described in the background section each specification is in a subfolder of the root directory unedifact. But these subfolders are them selves not project but contain projects. For example, a spec folder can contain a ‘mapping’ project, a ‘binding’ project, and a ‘test’ project.

We opted to use the following settings.xml to avoid having to manually update this file when new spec are added:

projectDir = rootProject.getProjectDir().getAbsolutePath()
specsPattern = ~/[\w][\d][\d][\w]/

new File(projectDir).eachFileMatch(specsPattern) { specDir ->
    specDir.eachFileMatch(~/(mapping|binding|test)/) { subModule ->
        moduleName = ":${specDir.getName()}/${subModule.getName()}"
        include moduleName
    }
}

build.gradle

This is where the main part of the configuration is done, well at the moment everything is done in this root build.gradle, but there is nothing stopping subprojects from adding their own build.gradle file and overriding or adding functionality. We have configuration parts that are common to all project and subproject and also configuration sections that are specific for the ‘mapping’, ‘binding’, and ‘test’ projects.

There are project dependencies between the ‘mapping’ project and the ‘binding’ project since the ‘binding’ project uses the mappings generated by the ‘mapping’ project. The ‘test’ project, if it exists, depends on either the ‘mapping’ project only or both the ‘mapping’ and the ‘binding’ project.

To build you can simply run ‘gradle’ from any of the subproject and it will build its dependencies:

> gradle

This will run a default task which we have set to ‘build’, so this is the same as running:

gradle build

Adding a new specification

To do this need to create a directory named after the specification. Then create the mapping directory and put the specification zip file in the root of that directory. Run ‘gradle projects’ to see that you newly added project was added:

> gradle projects
------------------------------------------------------------
Root Project - Smooks Unedifact project
------------------------------------------------------------

Root project 'unedifact' - Smooks Unedifact project
+--- Project ':d00a/binding'
+--- Project ':d00a/mapping'
+--- Project ':d00b/binding'
...

Building is done in the same way as described earlier in this post.

Uploading to Nexus

To deploy artifacts first create a gradle.properties in the root project directory:

milynUser=yourUserName
milynPassword=yourPassword

Uploading to nexus is now done like this

> gradle uploadArchives

Conclusion

While I’m still in the process of learning Gradle and Groovy I feel that most things can be worked around by being able to actually write code, and not having to use xml is very refreshing. One thing that I added was the task completion which worked like a charm. I added the following tasks to it:

tasks='clean compile dists javadoc jar test war build tasks comparePoms install properties projects uploadArchives'

This will enable task completion so that you can simply type the first few letters of a task and it will complete bash will complete the name for you, like you can do with git.

Next step is to migrate the main Smooks code base to Gradle