Gradle Tutorial

There are many automate build tools used these days for building, testing, publishing deployment and packaging software. Apache ant, Maven and Gradle are the most popular automate build tools.

Gradle is a build automation tool that help the developers eliminating the needs of doing a lot of unnecessary efforts. Standard directory preparation, compilation, packaging and generating the required artifacts and others, all of these tasks and more would waste a lot of time and cause an effective impact of deliverable.

Like Ant and Maven, the understanding of concept, determining the lifecycle and phases of Gradle tool and managing the required libraries and dependencies are the most important knowledge that developers look for learning a build tool. This has video tutorial at the end of the post, that will help you to learn Gradle through video explanation. This tutorial would explain the following concepts:

  1. What is Gradle?
  2. How to Install Gradle?
  3. Basic Example using Gradle Script
  4. Dependency management using Gradle
  5. Gradle Tasks

Lets continue read this tutorial and provide your valuable comments about Gradle. Happy reading!!

1. What is Gradle?

Gradle is a build automation tool, combines the power and flexibility of Ant with the dependency management and conventions of Maven into a more effective way to build. This is a new build tool and becomes more popular among the developers. Powered by a Groovy DSL , Gradle provides a declarative way to describe all kinds of builds through sensible defaults. For example, Spring IO fully supports this build tool for their projects along with Mavan tool. The most important points that featured by Gradle are:

  1. A very general flexible purpose build tool like Ant
  2. Very powerful support for multi-project builds
  3. Very powerful dependency management
  4. Full support for your existing Maven infrastructure
  5. Support for Ant tasks and builds
  6. Groovy-based build script
  7. A rich domain model for describing your build

More explanation about these features are explained in the following sections.

2. How to install Gradle?

This section describes the detailed steps to install the Gradle build tool in your machine:

  • Download latest Gradle 2.0 binaries.
  • Copy downloaded file and extract it into your local directory. For this tutorial we’ve used D:\Gradle\gradle-2.0.
  • Add Gradle in to environment variables as mentioned in the below screenshot.

Gradle - Add System Variable

  • Open your command line and type gradle -version to get version of Gradle that is installed on your system.

Gradle - Print Out Gradle Version By this time you have installed the build tool and ready for the use. At this time of writing this tutorial, the latest release is Gradle 2.0.

3. Gradle Build Scripts Basics and Hello World

Let’s make the most simplest Gradle build file that would help us understand the basics. You can print hello, world message using one task and using two different tasks as well.

  • Create an empty file called build.gradle and define the first task you would want to execute using build. It’s recommended to put all these files inside an empty folder.
  • Define a task to print out the hello world message.

build.gradle

task helloWorld << {
println 'hello, world'}

build.gradle

task hello << {
println 'hello, '}
task world(dependsOn:hello) << {
println 'world'}
  • Navigate into folder that contains the build.gradle file and execute gradle -q <<taskName>>.

Gradle - Execute Task

Gradle - Execute Task Depends On Other

Gradle - Files Defined Here’s the detailed explanation for the scenario executed:

  • The build file isn’t required to include anything, and doesn’t rely on any external dependencies.
  • The execution of two build files cause “hello world” message to be displayed into your console.
  • The second file define the “world” task as a dependent one, so the execution of it would directly cause the task “hello” to get executed. This is simple example for how to use “dependsOn” for executing the tasks.

Now, it’s time to build Java program by using Gradle build. Create project structure that looks like below: Gradle - Create Project Structure

  • Type apply plugin : ‘java’ inside your build.gradle file that located at the same level of your src directory.
  • Create your own HelloWorld.java file that contains simple main method to get the Hello World ! message to be displayed.
  • From your command console, just run gradle build.

Gradle - Gradle Build Result

  • Notice the new build directory generated automatically after running the command “gradle build”. It contains classes followed by your package, dependency cache and other directories.  This is the result of the conventions of Gradle’s Java plug in. We didn’t have to make a single entry or write a line of configuration.
  • Navigate into your package to see your compiled HelloWorld.class. Type java -cp build/classes/main/ net.javabeat.gradle.example.HelloWorld.

Gradle - Running Java Application

4. Dependency Management in Gradle

Dependencies are those classes, files and JARs required for getting your project built and deployed successfully and ready to serve client requests. Typically, we have two types of dependencies; those incoming things your project needs to build and run are called dependencieswhile those things your project has produced as outgoings are called publications.

  • Dependency Resolution:
    • Gradle allows you to tell it what dependencies of your project are, so that it can take care of finding and making them available in your build. The process of finding dependencies, downloading them from different repositories or located them in the local directories or bring them from building another project in the same multi-project build called dependency resolution.
  • Transitive Dependencies:
    • In general, dependencies are also need other dependencies, Gradle is also responsible of find those transitive dependencies  and make them available.
  • Publication:
    • Publication processes are also maintained by the Gradle. You are declaring your publications and Gradle take care of publishing them into your desired location. Desired locations can take form of local directory, remote repositories (Maven and lvy) or direct consuming through multi-project build procedure.

Let’s look at the most simplest declarations for dependencies. HelloWorld class is supposed to use Apache POI 3.10-FINAL version for creating an excel document. Create a build.gradle file: build.gradle

apply plugin : 'java'
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
compile 'org.apache.poi:poi:3.10-FINAL'}
  • Gradle provides you a huge number of plugins that can be used. Plugin Java defines a set of tasks from which compileJava that’s responsible of compiling your sources. Already Java plugin has defined set of configurations needed implicitly.
  • For referencing dependencies, repositories should be defined. For example, MavenLocal repository refers your local repository that’s defined beneath your home directory/.m2/reposirory. The  dependencies that are not located inside your local repository, they will be downloaded from the maven central one.
  • For defining your dependencies,dependencies closure is used. Java plugins defines a number of standard configurations; compileruntime, testCompile & testRuntime are all defined the scopes of your dependencies. Compile defines required dependencies to compile project source, runtime defines required dependencies at runtime and so on.
  • Execute gradle build will cause the gradle to search mentioned dependencies inside your local and downloading them in case they are not found. After Apache Poi downloaded the tasks of Java plugin will be executed.

Gradle - Downloading Poi Dependency Gradle - Java Plugin Tasks Are Executed Automatically

  • Gradle will maintain each downloaded dependency inside its local cache either the dependency itself has downloaded from the maven central repository or fetched from local one.

Gradle - Apache Poi has been downloaded into your gradle cache

  • HelloWorld class has been changed to contain creation of Excel workbook.

HelloWorld.java

package net.javabeat.gradle.example;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

public class HelloWorld {
	public static final void main(String [] args) throws Exception{
		System.out.println("Hello World !");
		HSSFWorkbook book = new HSSFWorkbook();
		System.out.println("Excel Book Created :: "+book);
	}
}
  • Executing your application will be done using a new Gradle plugin called “application”.
  • Each Gradle plugin has provided list of tasks that can be listed using gradle tasks.

build.gradle

apply plugin : 'java'
apply plugin:'application'

mainClassName = "net.javabeat.gradle.example.HelloWorld"

repositories {
	mavenLocal()
	mavenCentral()
}

dependencies {
	compile 'org.apache.poi:poi:3.10-FINAL'
}

Gradle - Application Plugin Listed Tasks

  • As two plugins were provided, Java & Application, all of listed tasks are figured can be used with the gradle command directly.
  • Executing of your Java application can be done by typing gradle run.

Gradle - Running Application With Dependency Respective

5. Gradle Tasks

Tasks are a fundamental unit of build activity, they are named collections of build instructions that Gradle executes as it performs a build. In the previous scenarios mentioned above, we’ve used tasks in two ways; direct task definition like HelloWorld task or call a pre-defined task given by certain plugin like compileJava. To declare a task all you need is a task name, following is the simple task added into build file. build.gradle

apply plugin : 'java'
apply plugin:'application'

mainClassName = "net.javabeat.gradle.example.HelloWorld"

task hello

repositories {
	mavenLocal()
	mavenCentral()
}

dependencies {
	compile 'org.apache.poi:poi:3.10-FINAL'
}

Gradle - Hello Task Definition

  • Define hello task is simple as type task keyword followed with the task name.
  • Execute gradle tasks will print out all tasks your build file contains including those defined by plugins used. As your custom tasks are listed under Other tasks like hello.

If you are executing your hello task using gradle hello command, you wouldn’t see any result as it doesn’t define any action. Using of left-shift << operator for assigning the action into certain task it will make your task able to execute specific action like print message. Look at the below example: build.gradle

apply plugin : 'java'
apply plugin:'application'

mainClassName = "net.javabeat.gradle.example.HelloWorld"

task hello << {
	println 'Hello World !'
}

repositories {
	mavenLocal()
	mavenCentral()
}

dependencies {
	compile 'org.apache.poi:poi:3.10-FINAL'
}

Gradle - Hello Task Action Execution Result

  • By using left shift operator you can define your desired action.
  • Executing your “hello task” would print out the hello message you’ve provided.
  • Your desired action is enclosed with two curly braces, these braces often called Task Closure.

Gradle defines two phases; configuration and execution are mainly the phases that execute configuration task and action task respectively. We’ve defined an action tasks, but we never looked at the configuration one. Following simple example that provides you a mix between action and configuration tasks. build.gradle

apply plugin : 'java'
apply plugin:'application'

mainClassName = "net.javabeat.gradle.example.HelloWorld"

task hello

hello << {
	println 'Action Time'
	print 'Hello'
}

hello << {
	println ' World !'
}

hello {
	println 'Configuration Time !'
}

repositories {
	mavenLocal()
	mavenCentral()
}

dependencies {
	compile 'org.apache.poi:poi:3.10-FINAL'
}

Gradle - Hello Action And Configuration Tasks Here’s the detailed explanation when you are working with action and configuration tasks.

  • Output of the execution action task is appended like you see in Hello World ! message.
  • Configuration tasks are defined using the same way you did for action tasks. One major difference here, is that the configuration task has eliminated the left shift operator as you can see.
  • Configuration block is the right place where you can setup variables and data structures will be needed by the task action when it runs later on in the build.

Gradle is creating an internal object model of your build before executing it. Every task you declare is a task object within the overall project. A task object has properties and methods like any other object. By default each new task receives the type of DefaultTask. Let’s look at the main methods Default Task provides:

  • dependsOn(task): adds a task as a dependency of the calling task.
  • doFirst(closure): adds a block of executable code to the beginning of a task’s action.
  • doLast(closure): adds a block of executable code to the end of a task’s action.
  • onlyIf(closure): allows you to express a predicate which determines whether a task should be executed. The value of the predicate is the value of the closure.

Here’s below a simple example for how can leverage all of these inherited methods in your build. build.gradle

apply plugin : 'java'
apply plugin:'application'

mainClassName = "net.javabeat.gradle.example.HelloWorld"

task preHello
task hello (dependsOn:preHello)

preHello << {
	println 'Action Time'
}
preHello.doFirst{
	println 'Do First'
}

preHello.doLast {
	println 'Do Last'
}

hello  << {
	print 'Hello'
}

hello << {
	println ' World !'
}

hello {
	println 'Configuration Time !'
}

repositories {
	mavenLocal()
	mavenCentral()
}

dependencies {
	compile 'org.apache.poi:poi:3.10-FINAL'
}

Gradle - Leverage DefaultTask Inherited Methods Actually, DefaultTask has also defined a set of properties can be used by your own custom tasks, here’s the provided properties:

  • didWork: Is a boolean property provides you an indicator for certain task has been completed successfully. didWork property can be accessed by using tasks.<<task-name>>.didWork expression.
  • enabled: Is a boolean property provides you an indicator whether certain task would be executing. Accessing of enabled indicator can be done through using  tasks.<<task-name>>.enabled expression.
  • path: Is a string property containing fully qualified path of a task. If you’ve wrote tasks.<<task-name>>.path inside your build file, you would be getting a colon followed by your written task name like :task-name which gives you an indicator for this task is defined in the top-level build file. Since Gradle supports dependent sub-projects, or nested builds and in case your typed task existed in a nested build called nested.gradle then the path of it will be :nested:task-name.
  • logger: Is a reference of implicit logger object. Logging is a common requirements for various types of frameworks and platforms. For those are familiar with, DEBUG, INFO, LIFECYCLE, WARN, QUIET and ERROR are those levels supported by Gradle. For logging messages you should use logger.<<LOGGING-LEVEL>> ‘<<Messages>>’ expression.
  • logging: Is a property gives you access to the log level setting by which you can specify all of those logging messages that would be shown. Following example, a debug logging level has been specified before further using of logger.debug expression.
  • description: Is just a meta-data human-readable property that used for describe the purpose of certain task. Description property has been defined at the declaration of task. Following expression task <<Your-Task>>(description:’<<Your-Description>>’) <<{ … } used for leverage description property.
  • temporaryDir: Is a property used for references Temporal File Object that’s pointing to a temporary directory corresponds to the build file. If you’ve typed expression like println tasks.compileJava.temporaryDir as example, D:\Gradle\HelloWorld\build\tmp\compileJava path will be shown.

Following is simple example to leverage the above properties inside your build file: build.gradle

apply plugin : 'java'
apply plugin:'application'

mainClassName = "net.javabeat.gradle.example.HelloWorld"

task preHello
task hello (dependsOn:preHello)
task notifyMe(dependsOn:compileJava) << {
	logging.level = 'DEBUG'
	if(tasks.compileJava.didWork){
		logger.debug 'Compilation finsihed sucessfully'
	}
}

preHello << {
	println 'Action Time'
}
preHello.doFirst{
	println 'Do First'
}

preHello.doLast {
	println 'Do Last'
}

hello  << {
	print 'Hello'
}

hello << {
	println ' World !'
}

hello {
	println 'Configuration Time !'
}

repositories {
	mavenLocal()
	mavenCentral()
}

dependencies {
	compile 'org.apache.poi:poi:3.10-FINAL'
}

Gradle - Leverage DefaultTask Inherited Properties Here’s the points you should take care of:

  • The compileJava didWork flag has never been flagged to true if your classes are compiled before, so execute gradle clean for cleaning all of your compiled classes.
  • NotifyMe task has used didWork flag upon compileJava in order to determine whether the task has accomplished.
  • Once compileJava task has been done, the flag of didWork will be set to true and so the logger will be able to logging your desired message.
  • Configuration phase has been executed before phase of execution so that it enable you of configuring some variables, resources and so on.

Besides the DefaultTask that we’ve explored, we have set of different task types you may need to be aware of:

  • Copy: It copies files from one place into another.
  • Jar: It creates a Jar file from your sources. Java Plugin used already provides one.
  • JavaExec: It runs Java class with main() method. Application Plugin used already provides one.

6. Gradle Build Phases

Gradle executes a build by running through three distinct phases:

  • Initializationis the first executed phase in which Gradle determines the projects that will be participated in the build. Settings.gradle build file is used for initialization phase configuration.
  • Configurationis the second executed phase in which the build file’s tasks are assembled into an internal object model, usually called DAG (Directed Acyclic Graph). For all of those tasks that are tagged as Configuration Tasks (Refer above) will usually get executed at this phase.
  • Executionis the last executed phase that gets called for executing build tasks in the order arranged by their dependencies relationship. For all of those tasks that are tagged as Execution Tasks (Refer above) will usually get executed at this phase.

We’ve explored execution and configuration phases earlier, this time we will take a look at the Initialization phase. As we’ve introduced about settings file is used for defining all of those user-defined actions. Following sample shows you the impact of defining  a file. settings.gradle

println 'This message will be printed out as a part of initialization phase'

Gradle - Initialization Phase

  • Initialization phase has associated with the settings.gradle file.
  • build.gradle script file has never been changed from the last one provided here.

7. Summary

Gradle is a build tool, this tutorial intended for provide you an excellent guidance one how to use Gradle and for what you need to use this build tool. Everything important about this build tool is either be covered completely or mentioned partially for your knowledge. Gradle phases, tasks, methods, properties and others are fully used through sections on this tutorial. For more explanation on the every concepts, you could refer the Gradle official documentation / reference tutorials that would provide more insights.

8. Gradle Video Tutorial

9. Download Source Code

Comments

comments

Speak Your Mind

*