Skip to main content

Gradle : Next-gen build tool introduction

I've been recently reading about maven 3 and from a page to another I read a bit about gradle, and got interested in it, so I want to try it now and see how it feels and works in practice

so to get started you need to download gradle from here:
then add the path to gradle bin directory to the PATH system variable and go to CMD/shell then run:

> gradle

if it worked and you got build successful let's move to setup our project structure.

a word about gradle first, is that it promises to keep the great conventions Maven provided but with the flexibility ANT  had since Maven can give you a hard time if you need to customize something.
it's a convention over configuration, yet flexible.

so back to the track, what I want to do in this project is to setup a full spring-mvc rest API server, with multiple tiers (projects) that contains DAOs, Business Entities, Services, and REST tier.

o---[ REST ] -- uses --> [Services] -- uses --> [DAOs] --- > (DB)
           |                                 |                              |
    [                          Business Entitiess                          ]

this is a simple enterprise architecture to provide loosely coupled  tiers, to simulate a real project structure to test what gradle has to offer here.

In maven I would go and create a parent project then add these projects as modules, but when I need to build a project I'll have to build every thing which takes a lot of time.

ok so in gradle we have 3 options to structure our build files [build.gradle]
1) Individual : each sub project has it's own build file
2) Unified : one build file in the master project to build all sub projects
3) Hybrid: a build file in the master project that contains common build configurations and build files in each sub project that are specific for each build file

the Hybrid in my opinion gives you the best of the two worlds so i'll use it here, the other two approaches will implicitly be implemented.

A. Setting up the project structure 

Now the directory structure of our project, i'll go to file system and create the following JSON tree:

master-proj {
dao : { src :{ main : { java : {} , resources : {} } , test :{}} ,  build.gradle },
be : { source :{ code : { java : {} , res : {} }  ,  test :{} }, build.gradle },
bl : { src :{ main : { java : {} , resources : {} } , test :{}} ,  build.gradle },
rest :{ src :{ main : { java : {} , resources : {} } , test :{}} ,  build.gradle }

note: i'll be using git also in this tutorial to keep a reference for the code.

if you notice the 'be' src structure is different to test how easy it is to changed default project layout (src/main/java and src/main/resources) that follows maven conventions.

after creating this structure the content of build.gradle in the master project for now will only contain:
allProjects {
 apply plugin: 'java'
this tells gradle that all sub projects will use the java plugin without explicitly saying that in the sub projects build files

the contents of settings.gradle will be :
include 'dao', 'be', 'bl', 'rest' 

these are the names of the directories that contain the sub projects

navigate in cmd to master-proj directory and and run :
 > gradle build

what you will get is build directories inside each project like this:

Now let's go to be/build.gradle and add the following segment :

apply plugin: 'java'
sourceSets {
    main {
        java {
            srcDir 'source/code/java'
        resources {
            srcDir 'source/code/res'
This will tell gradle java plugin where to find our source code, i'll leave test directory for later.

add the following class in  be/source/code/java folder (don't forget to add the directories for the package) :

public class Person {
and in the be/source/code/res folder add an empty file call it :
 navigate to master-proj/be and run :

>gradle build
 go to master-proj\be\build, you will find more directories : (classes, dependency-cahce, resources)
open the compiler jar in lib to see it's contents:

so now we have something we can work with as start point.

now we want to import this to eclipse but we need to add eclipse config files ( .classpath, .project, .settings) gradle has a plugin for that and we can include it like the java plugin under our master project build file :

allprojects {
  apply plugin: 'java'
  apply plugin: 'eclipse' 

now while you are in in master-proj dir , run : 

gradle eclipse

now all your projects can be imported to eclipse to work with easier.

let's go ahead and do that:

it also figured out about our custom source directory in project 'be'

B. Dependency management

in our work we usually need the following types of dependencies:

1- 3rd party dependencies in runtime (spring jars)
2- 3rd party dependencies in compile time only ( javax.servlets )
3- 3rd party testing dependencies (junit)
4- our own frameworks jars / generated web services client jars
5- projects dependencies

some of these are on maven repositories and others aren't, gradle allows us to do everything from importing a jar from file system like ant or use central maven repo or use our own maven repo if we have one, to test this let's plan to add the following dependencies:

for DAO project it will depend on :
- spring for Dependency injection
- hibernate for persistence
- business entities project

for BL :
- spring for Dependency injection
- our own utility library [local jar]
- business entities project
- Junit4 for testing

for REST :
- spring for Dependency injection & spring web
- BL project
- BE project

BE project won't have any dependencies for now.

easiest way to get spring dependencies is to use maven central repo, and since spring core is common between more than one project let's configure this in one place.

In the master project build file i'll add this :

allprojects {
  apply plugin: 'java'
  apply plugin: 'eclipse'

  repositories {    mavenCentral()  } 

[':bl', ':dao', ':rest'].each { 
pn -> project(pn) {  dependencies 
      { compile 'org.springframework:spring-context:4.1.0.RELEASE'  }  

this tells gradle to user maven central repo to download the spring context jar (and it's dependencies)
and for each of the three projects add the spring-context jar as a compile time dependency

now run gradle eclipse in the master project, it will download the spring jars then update the class path for the three projects to reference the spring-context jar from the local

for the REST project it needs spring-webmvc.jar to expose our rest api's so in rest/build.gradle
add this :

dependencies {
compile 'org.springframework:spring-webmvc:4.1.0.RELEASE'

and run gradle eclipse to update classpath file

for the dao we will need hibernate jars so add this to its build.gradle:

dependencies {
compile 'org.hibernate:hibernate-core:4.3.6.Final'

now let's convert REST project to a WAR instead of JAR, to do that add the following plugin at the top of its build file :

apply plugin: 'war'

and add the following dependency :

dependencies {
compile 'org.springframework:spring-webmvc:4.1.0.RELEASE'
compile project(':bl')}

this is how we add a dependency  between the projects

now also add the following to complete the dependency between our projects :
in master-project/build.gradle :

[':bl', ':dao', ':rest'].each { pn ->
project(pn) {
dependencies {
compile 'org.springframework:spring-context:4.1.0.RELEASE'
compile project(':be') }

and in the bl/build.gradle:

dependencies {
compile project(':dao')
to add a local jar (not 3rd party and not in a Maven repo) we can do the following:
assume we want our library in the root project in folder called libs, for example I have put xpp3.jar in that folder and I want to reference it inside my projects

1- add flat directory repository :
repositories {
mavenCentral( )
flatDir {
    dirs "$rootDir/libs"
$rootDir is a DSL variable that points to the root project base directory.

and in the dependencies add :

compile 'xpp3:xpp3:1.1.4'

it will now be resolved to the libs directory without the need to complex configuration like maven.

another way to do this is to use the files( ) method without declaring a flatDir repository:

compile files('../libs/commons-fileupload-1.3.1.jar')  //[assuming we are in a subproject depedency ]

see the master-proj build.gradle :

ok now the final step is prepare our application for deployment, I have took some time to add the required spring configurations and wire everything together I added few dependencies for junit in the master project build.gradle:

[':bl', ':dao', ':rest'].each { pn ->
project(pn) {
dependencies {
compile 'org.springframework:spring-context:4.1.0.RELEASE'
compile project(':be')
testCompile group: 'junit', name: 'junit', version: '4.+'
testCompile 'org.springframework:spring-test:4.1.0.RELEASE'
notice the scope of junit is for test compile only so it won't be packaged with the final war.

to deploy the project run :

gradle build and you will get a war from the rest project, drop that in your server and you're good to go

visit the final project setup here on git hub:

Summary :
Gradle is simple, flexible and really powerful, the only thing took time is boilerplate required for the initial structure which I did manually on purpose to understand the very basics of gradle.

Gradle yet has more interesting features, and what I only covered is mainly the java plugin and maven in gradle, the possibilities are endless, since you are using groovy scripting for the build domain (DSL) which provides easy to change conventions.

refs :


Popular posts from this blog

Spring 4 + Hibernate 4 / Java configuration / rest service example with gradle

In this post I'll explain the required work to create a rest API utilizing both spring and hibernate version 4, and the configuration will be using java configuration classes not XML. I'll use gradle to build and for dependency management, it's way easier than maven and keeps you focused on the application, if you are not familiar with gradle and interested in it see my previous post about it. The first part which is dependency management is covered in gradle post mentioned above. I'll skip to explain each tier of the project and its configurations: As you can see we have 4 tiers: 1) DAO tier / data tier In this tier we configure the datasource and hibernate, I used HSQL in memory db it can be easily substituted with other db engine providing the right dependencies The DaoConfig defines the data source, transaction manager, session factory and  hibernate properties The most important part is the annotations : 1)  @Configuration  : to tell spring th

Android RecyclerView - Adding Empty View

So RecyclerView was introduced to replace List view and it's optimized to reuse existing views and so it's faster and more efficient as stated in the documentation: While using it, I faced the issue of missing a useful functionality that is implemented in ListView. that feature is setting an empty view in case there was no records. In ListView it was as simple as this View emptyView = findViewById(; ListView  myList = .... myList.setEmptyView(emptyView); but this method doesn't exist for recycler view so we need a work around until android team fixes this. and here are the screen shots of both list view and recycler view fix List view : Recycler view : here is how I fixed it: here is the content of empty_view, it can be anything. Enjoy.

[PART 5] NuTracker ReactJS app - Add Login & Profile using Router

In the previous part we finished the dashboard read functionality, now we want to add the skeleton for other pages: - Login   In this page the user will be able to login to their account and the dashboard won't show unless the user is logged in. - Profile In this page the user will be able to update their daily nutrition goals that they can track in the dashboard. to be able to have multiple 'pages' in react and navigate from one to one, we need something that can switch the rendered content based on what we want, we can do that with if statements in the App components and store some location state, but why invent the wheel. React Router every major single page app web framework has the routing concept and functionality to interact with the usual browser urls and switch the content based what user should see. for example on the profile page I want the url path to be /profile, and for login to be /login and so on. in more advanced cases you want the users