In this tutorial, we will discuss about Gradle to understand how to build our project with it and make our work easier to do. Let’s get started.
Table of contents
- Introduction to gradle
- Setup gradle in our project
- Some tasks in Gradle
- Understanding build.gradle file
- How dependency resolution work
- Setup Gradle Tomcat plugin
- Build project with Gradle
- Run project with Gradle
- Updating claspath with the latest changes in build.gradle file
- Using JQuery in build.gradle
- Configuring the Main class of Jar file
- Wrapping up
Introduction to gradle
According to wikipedia.org
:
Gradle is an open-source build automation system that builds upon the concepts of Apache Ant and Apache Maven and introduces a Groovy-based domain-specific language (DSL) instead of the XML form used by Apache Maven for declaring the project configuration. Gradle uses a ```directed acyclic graph``` ("DAG") to determine the order in which tasks can be run.
Gradle was designed for multi-project builds, which can grow to be quite large. It supports incremental builds by intelligently determining which parts of the build tree are up to date; any task dependent only on those parts does not need to be re-executed.
In the next parts, we will delve into build.gradle
file to understand how to configure our project lonely.
Setup gradle in our project
-
First way: Download Gradle
We can download the lastest version of Gradle at link. After downloaded, we have
gradle-5.2.1-all.zip
file.Next, we need to create some environment variable for Gradle.
- Let’s pretend that we put gradle folder in
C:\gradle
. - Create system variables
GRADLE_HOME
withC:\gradle
, and addC:\gradle\bin
toPATH
.
- Let’s pretend that we put gradle folder in
-
Second way: Setup Buildship for Gradle plugin in Eclipse
Select
Help
–>Install New Software...
.Select
Add
button –> fill in some information:- Name: Buildship
- Location: http://download.eclipse.org/buildship/updates/e46/releases/1.0/1.0.19.v20160830-1454
Buildship
is an Eclipse plugin that allows us to build application and libraries using Gradle through our IDE. The basic functionality of Buildship is well-documented.Next, we can setup Buildship in eclipse.
Some tasks in Gradle
Tasks | Description |
---|---|
assemble | Assembles the outputs of this project. |
build | Assembles and tests this project. |
buildDependents | Assembles and tests this project and all projects that depend on it. |
buildNeeded | Assembles and tests this project and all projects it depends on. |
classes | Assembles main classes. |
jar | Assembles a jar archive containing the main classes. |
testClasses | Assembles test classes. |
war | Generate a war archive with all the compile classes, the web-app content and the libraries. |
tomcatJasper | Runs the JSP compiler and turns JSP pages into Java sources. |
tomcatRun | Uses our files and where they are and deploys them to Tomcat. |
tomcatRunWar | Assembles the webapp into a war and deploys it to Tomcat. |
tomcatStop | Stops Tomcat. |
Understanding build.gradle file
-
Declaring repositories
-
Declaring public-available repository
respositories { jcenter() mavenCentral() google() }
-
Declaring a custom respository with URL
Let’s pretend that our company will have a repository that use in local. In order to declare this repository in Gradle, we have:
Repositories with custom URLs can be specified as
Maven
orIvy
repositories by calling the corresponding methods available on theRepositoryHandler
API.respositories { maven { url 'http://repo.mycompany.com/maven2' } }
-
Declaring multiple repositories
This part will be used when some dependencies are only available in one repository but not the other.
repositories { jcenter() maven { url "https://maven.springframework.org/release" } maven { url "https://maven.restlet.com" } }
Note: The order of declaration determines how Gradle will check for dependencies at runtime. If Gradle finds a module descriptor in a particular repository, it will attempt to download all of the artifacts for that module from the same repository. You can learn more about the inner workings of
Gradle’s resolution mechanism
.
To get more information about declaring repositories, we can refer to the link.
-
-
Declaring dependencies
-
Declaring a concrete version of a dependency
plugins { id 'java-library' } repositories { mavenCentral() } dependencies { implementation 'org.springframework:spring-web:5.0.2.RELEASE' }
In the above example, we declared a compile-time dependency on the Spring web module by its coordinates:
org.springframework:spring-web:5.0.2.RELEASE
. Gradle resolves the module including its transitive dependencies from the Maven Central repository and uses it to compile Java source code. The version attribute of the dependency coordinates points to aconcrete version
indicating that the underlyingartifacts
do not change over time. The use of concrete versions ensure reproducibility for the aspect of dependency resolution. -
Declaring a dependency without version
A recommended practice for larger projects is to declare dependencies without versions and use
dependency constraints
for version declaration. The advantage is that dependency constraints allow you to manage versions of all dependencies, including transitive ones, in one place.dependencies { implementation 'org.springframework:spring-web' } dependencies { constraints { implementation 'org.springframework:spring-web:5.0.2.RELEASE' } }
-
Declaring a changing version
plugins { id 'java-library' } repositories { mavenCentral() maven { url 'https://repo.spring.io/snapshot/' } } dependencies { implementation 'org.springframework:spring-web:5.0.3.BUILD-SNAPSHOT' }
In Maven repositories, changing versions are commonly referred to as snapshot versions. Snapshot versions contain the suffix
-SNAPSHOT
. By default, Gradle caches changing versions of dependencies for 24 hours.
-
-
Declaring a project dependency
In a large project, we usually divide it into many components. Each component has a specific functionality. So, in order to link each module to the main project, Gradle has:
The following example declares the dependencies on the
utils
andapi
project from theweb-service
project. The methodProject.project(java.lang.String)
creates a reference to a specific subproject by path.project(':web-service') { dependencies { implementation project(':utils') implementation project(':api') } }
-
apply plugin: 'java'
When we want to create a Java project, we need to apply the Java plugin.
Below is the tasks of java plugin that need to know.
So, java plugin will add new conventions such as the default project layout, … or new tasks, and new properties to our build.
Consider the case where the Maven directory structure is used for Java sources and resources. These directories are:
- src/main/java
- src/main/resources
- src/test/java
- src/test/resources.
In the
build.gradle
, we have:apply plugin: 'java'
Running gradle build will result in:
> gradle build :compileJava :processResources :classes :jar :assemble :compileTestJava :processTestResources :testClasses :test :check :build BUILD SUCCESSFUL
The Java plugin emulates many of the expected Maven lifecycles as tasks in the directed acyclic graph of dependencies for the inputs and outputs of each task. For this simple case, the
build
task depends upon the outputs of thecheck
andassemble
tasks. Likewise,check
depends upontest
, andassemble
depends uponjar
.For projects that do not follow the Maven conventions, Gradle allows the directory structure to be configured. The following example would support a project that contains source files in
src/java
rather than thesrc/main/java
convention enforced by Maven.In
build.gradle
, we have:apply plugin: 'java' sourceSets.main.java.srcDirs = ['src/java']
or
sourceSets { main { java { srcDir 'src/java' } resources { srcDir 'src/resources' } } }
-
sourceSets {}
configures the source sets of this project. A
SourceSetContainer
manages a set ofSourceSet
objects.Refer: SourceDirectorySet
-
dependencies {}
configures dependencies for this project.
Refer: DependencyHandler
Configuration Extends Used by task Description compile compileJava These are the dependencies needed at compile time to compile the source files. runtime compile These are the dependencies for runtime of the application, but are not needed for compilation. testCompile compile compileTestJava These are all the dependencies to compile test source files. testRuntime testCompile test These are all the dependencies needed to run the tests. archives uploadArchives This contains artifacts, such as JAR files created by the project. default runtime This is the default configuration that contains all runtime dependencies. -
buildScript {}
configures the build script classpath
Refer: ScriptHandler
-
repositories {}
configure the repositories for this project.
Refer: RepositoryHandler
How dependency resolution work
Gradle takes your dependency declarations and repository definitions and attempts to download all of your dependencies by a process called dependency resolution. Below is a brief outline of how this process works.
-
Given a required dependency, Gradle attempts to resolve the dependency by searching for the module the dependency points at. Each repository is inspected in order. Depending on the type of repository, Gradle looks for metadata files describing the module (.module, .pom or ivy.xml file) or directly for artifact files.
-
If the dependency is declared as a dynamic version (like 1.+, [1.0,), [1.0, 2.0)), Gradle will resolve this to the highest available concrete version (like 1.2) in the repository. For Maven repositories, this is done using the maven-metadata.xml file, while for Ivy repositories this is done by directory listing.
-
If the module metadata is a POM file that has a parent POM declared, Gradle will recursively attempt to resolve each of the parent modules for the POM.
-
-
Once each repository has been inspected for the module, Gradle will choose the ‘best’ one to use. This is done using the following criteria:
-
For a dynamic version, a ‘higher’ concrete version is preferred over a ‘lower’ version.
-
Modules declared by a module metadata file (.module, .pom or ivy.xml file) are preferred over modules that have an artifact file only.
-
Modules from earlier repositories are preferred over modules in later repositories.
-
When the dependency is declared by a concrete version and a module metadata file is found in a repository, there is no need to continue searching later repositories and the remainder of the process is short-circuited.
-
-
All of the artifacts for the module are then requested from the same repository that was chosen in the process above.
The dependency resolution process is highly customizable to meet enterprise requirements.
Setup Gradle Tomcat plugin
Each time when we want to deploy our project on a server, we have to turn project into war file, and manually run it on server based on command line or something like that. I think that it is highly inconvenient.
So, to make it automatically, we need to install a Tomcat plugin to Eclipse. Therefore, when we build a project via Gradle task, our project will be deployed on a Tomcat server.
To install Gradle Tomcat plugin, we need insert some code into build.gradle
file:
apply plugin: 'com.bmuschko.tomcat'
apply plugin: 'eclipse-wtp'
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.bmuschko:gradle-tomcat-plugin:2.4.1'
}
}
dependencies {
def tomcatVersion = '8.0.46'
tomcat "org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}",
"org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}",
"org.apache.tomcat.embed:tomcat-embed-jasper:${tomcatVersion}"
api 'org.apache.commons:commons-math3:3.6.1'
}
tomcat {
httpPort = 8080
enableSSL = true
contextPath = '/library-spring'
}
Build project with Gradle
-
Gradle has two basic concepts: projects and tasks.
-
A project is either something we build (e.g. a jar file) or do (deploy our application to production environment). A project consists of one or more tasks.
-
A task is an atomic unit work which is performed our build (e.g. compiling our project or running tests).
–> Every
Gradle build
contains one or more projects.We can configure
Gradle build
with:build.gradle
: specifies a project and tasks.gradle.properties
: configure the properties of the build.settings.gradle
: is optional in a build which has only one project. If our Gradle build has more than one projects, it is mandatory because it describes which projects participate to our build. Every multi-project build must have a settings file in the root project of the project hierarchy.
-
-
First way: Use Gradle Tasks View
If you do not see the
Gradle Tasks
View, you can get it fromWindow
–>Show View
–>Other
–> Searchgradle
–> SelectGradle Tasks
.In
Gradle Tasks
View, selectbuild
tasks in folderbuild
, right click –>Run Gradle Tasks
.
Run project with Gradle
In Gradle Tasks
View, select our current project –> select web application
folder –> select tomcatRun
tasks –> right click –> Run Gradle Tasks
.
Updating claspath with the latest changes in build.gradle file
Eclipse does not automatically update the classpath
, if the build.gradle
file is updated. Select Gradle
–> Refresh Gradle Project
from the context menu of the project or from your build.gradle
file for that.
Using JQuery in build.gradle
```java
repositories {
ivy {
url 'https://ajax.googleapis.com/ajax/libs'
patternLayout {
artifact '[organization]/[revision]/[module](.[classifier]).[ext]'
}
}
}
configurations {
js
}
dependencies {
js 'jquery:jquery:3.2.1:min@js'
}
```
Configuring the Main class of Jar file
The Java plugin adds a jar task to our project, and every jar object has a manifest
property which is an instance of Manifest.
Using attributes()
method of the Manifest interface will configure the main class of the jar file.
We can refer to this link, to understand more deeper about configuring Manifest file.
apply plugin: 'java'
jar {
manifest {
attributes 'Main-Class': 'com.manhpd.tutorial.HelloWorld'
}
}
Wrapping up
- Understanding what we need to run project with Gradle.
Refer:
Plugins in Gradle
https://docs.gradle.org/2.4/userguide/plugins.html
Configure task build in Gradle
https://docs.gradle.org/2.4/userguide/tutorial_using_tasks.html
https://guides.gradle.org/building-java-web-applications/
https://github.com/bmuschko/gradle-tomcat-plugin
https://www.vogella.com/tutorials/EclipseGradle/article.html
https://www.tutorialspoint.com/gradle/gradle_eclipse_integration.htm
https://www.journaldev.com/7971/gradle
https://docs.gradle.org/current/userguide/declaring_repositories.html#declaring_repositories