avatarAndrew MacMurray

Summary

The provided content is a comprehensive guide for beginners on using Gradle, a build automation tool for JVM languages, with a focus on understanding its configuration and integration with IntelliJ IDEA.

Abstract

The article "A beginners guide to Gradle" introduces Gradle as a versatile build automation tool, often utilized for JVM languages like Java, Groovy, or Scala. It emphasizes the tension between learning a build system and application development, aiming to provide enough knowledge to use Gradle comfortably and productively. The guide walks through setting up a new Gradle project in IntelliJ, explaining the structure and significance of the build.gradle file, which is written in Groovy. It covers Groovy basics, such as its concise syntax and closures, to demystify the build.gradle script. The core concepts of Gradle, including Projects, Tasks, and Properties, are detailed, showcasing how Gradle allows for code as configuration. The article also touches on customizing tasks and creating new ones, concluding with resources for further learning.

Opinions

  • The author expresses a love-hate relationship with build tools, particularly highlighting the complexity of Webpack.
  • Gradle is presented as a powerful tool that can be intimidating at first due to its complexity, but it is manageable with some foundational knowledge.
  • The Groovy language is seen as more user-friendly than Java for writing Gradle build scripts due to its concise syntax and features like closures.
  • The author suggests that there is a balance to be struck between understanding a build system like Gradle and focusing on application development.
  • The guide positions Gradle's build.gradle file as a central and powerful aspect of project configuration, which can be greatly customized.
  • Learning Groovy basics is recommended to better understand and effectively write Gradle build scripts.
  • The article implies that the Java plugin for Gradle significantly enhances the build process by adding useful default tasks.
  • Customizing tasks and creating new ones is encouraged to tailor the build process to specific project needs.
  • The author acknowledges the vastness of the Gradle API but emphasizes that a foundational understanding can make navigating the documentation easier.

A beginners guide to Gradle

I have a love hate relationship with build tools — my first exposure to a build tool was Webpack for JavaScript. It’s extremely powerful, and I got pretty far with some default configuration. But editing the webpack.config.js used to make my stomach turn — things would break, and trying to understand why was a rabbit hole (mainly due to my lack of knowledge about it). There’s a tension between learning enough of how a build system works and getting on with writing your application. So let’s dive into enough of Gradle to get comfortable and productive.

What is Gradle?

Gradle is a build automation tool often used for JVM languages such as Java, Groovy or Scala. Gradle can be configured to run Tasks which do things like compile jars, run tests, create documentation and much more.

Starting a new project with Gradle using InteliJ

When creating a new project with intelij you can select the gradle option from the left and choose which language you’d like to use with it

After creating your project, InteliJ will create a build.gradle file with some helpful defaults for that language, so let’s have a look at the build.gradle file. I’ll be using Java in the examples but the same concepts apply for other languages.

The build.gradle file is where all the magic happens. This is the default java one created by InteliJ:

But what does it all mean? And where does this syntax come from?

Groovy 101

Gradle build scripts are written in Groovy, a JVM language similar to Java but with a more concise syntax — let’s learn just enough to have a better understanding of what’s going on:

The Groovy console

You can try out groovy scripts using the groovy console in InteliJ under tools -> groovy console

Valid Java is valid Groovy

In the console area we can type in any valid Java code:

Pressing play (the green button) we’ll see the output in a window underneath

One thing to note already is that we don’t need a surrounding class and main method to execute our code 👍. But we can go further. Groovy automatically imports System.out so we can omit that:

Parens for single argument method calls and semicolons are also optional in Groovy so we can reduce System.out.println("hello groovy"); to:

snazzy ✨

Groovy Closures

Understanding Groovy Closures will demystify a lot of what’s going on in build.gradle

If you’ve used Java 8’s lambdas, groovy closures will feel familiar — they effectively let you treat methods as regular values (so they can be used as arguments to other methods). Let’s have a look at an example:

In the groovy console we can define a class like this:

Let’s add a method that takes a closure:

We can “run” whatever code is in the closure with closure.call(), but how would we use this? We’ll create an instance of MyClass and call doSomething like so:

Which outputs:

Does this look familiar now?

dependencies is a method which takes a “runnable” block of code (a closure). Inside that block we’ve called the the testCompile method with group: 'junit' etc as an argument (the group, name, version section is actually short hand for a groovy map, essentially a list of key value pairs).

The Core of Gradle: Projects and Tasks

Now we have a better understanding of how groovy syntax works let’s take a deeper look at the build.gradle file.

The build.gradle file has a one to one relationship with something called the project object: It’s an object representing information about our project. If you’ve used Maven before (another popular build tool Gradle aims to be compatible with) you’ll recognise this idea from the pom.xml file (project-object-model), this is roughly equivalent to build.gradle.

Each project is made up of a collection of Tasks: these are atomic units of work that represent the things that need to be done to build our project.

Gradle has a number of default Tasks on the project object model — we can have a look at these by running the task:

> gradle tasks

In a blank build.gradle file (i.e. if you deleted everything from the one InteliJ made) would output this:

The tasks task shows all the Tasks available on a project. The real magic starts to happen at this line:

Applying the Java plugins adds a bunch of extra tasks we can use. Running gradle tasks now includes these lines:

These are some helpful default tasks that many Java projects are likely to use.

The key takeaway here is that we can modify the project object model via the build.gradle script — Gradle is code as configuration.

Check out the full docs for the Java plugin here.

Properties

As well as Tasks, our project object also has “properties” that represent information about our project. These can be simple properties such as the version or the sourceCompatibility, you can see these being modified here:

Or they can be more complex properties that are modified by methods that take Closures. A piece of magic that confused me when I started using Gradle was the sourceSets property — this gets added by the Java plugin. The sourceSets property defines where Gradle should look for your source code (plus a couple of other snazzy things you can check out here). By default Gradle follows the Maven convention of putting your Java source code in src/main/java and tests in src/test/java.

But say we want to locate our java source code in my-java-directory (I wouldn’t recommend this in a real project), or maybe we’re working on a legacy project; we can point Gradle at a different directory like this:

Just like Tasks we can see a full list of properties for our project by running the task (be warned, it can be pretty large).

> gradle properties

Customising Tasks

We can do the same customising magic with Tasks too. When building my Tic Tac Toe command line application I was looking for some way of running it conveniently from Gradle — the application plugin had a handy task called run.

However, it needed to be configured to point System.in as its standardInput. Adding this line let me reconfigure the run task:

Another thing this highlights is that Tasks can also have their own properties which we’re able to configure.

Making a new Task

We can also create our own custom tasks, either from scratch or more often from extending existing Tasks. The run task from above actually extends a lower level Task type called JavaExec. We could have defined the same Task as above like this:

This adds a customRun task to the project object which we can use:

> gradle customRun

And would have the same effect as the run task from before.

Conclusion

The Gradle api is HUGE and quite overwhelming at first. This post only scratches the surface but hopefully it demystifies some of the syntax and concepts in Gradle to make understanding the docs a little easier.

There are some excellent guides on the Gradle website for more specific cases. This online course from Lynda.com (Gradle for Java Developers) was particularly helpful for me for getting a better idea of what was going on.

Gradle
Java
Apprenticeship
Build Tool
Recommended from ReadMedium