Start Here !

Welcome to my website. Find articles, presentations, tutorials, experiments on various technologies.

You can get in touch with me anytime at

r o m i n . i r a n i @ m i n d s t o r m s o f t w a r e . c o m

I am also active on Twitter (do follow me) and on Google+.

 

Posted in Uncategorized | Leave a comment

Gradle Tutorial : Part 7 : Android Studio + App Engine + Gradle

Welcome to Part 7 of the Gradle Tutorial. In the previous episode i.e. Part 6, we took a first look at understanding the Gradle build files that are generated for a basic Android application inside of Android Studio.

In this part of the tutorial, we shall expand on what we did in the last episode. We will continue to be with our basic Android application that has been generated in Android Studio. In addition, we are going to look at adding another module to this Android project. In other words, we are going to take a look at multi-module Java project inside of Android Studio and our knowledge from Part 3, where we loooked at multi-module Java projects will help us.

We look at App Engine Gradle plugin in Part 5 and in this episode, the second module that we shall be adding to our Android Project will be an App Engine module. Yes, you read that right. Android Studio has started to get good support for App Engine projects, such that if you are looking at writing a backend for your Android Application, this can be a great choice and you can do all of that inside of Android Studio.

Our goal in this episode will only be to familiarize ourselves with an Android Project in Android Studio that has 2 modules : Android App and the App Engine App. This is not an tutorial for learning, either Android or App Engine.

gradle

This part assumes that you have installed Android Studio on your development machine and that you are familiar with basic Gradle commands, project structure and files as we have seen in the series so far.

I have used Android Studio (Beta) 0.8.6 on Windows for this blog post. It is not necessary to have the same version or the OS, things should be pretty much similar from a Gradle perspective.

The areas that we shall cover in this blog post are as follows:

  • Begin with a default Android application in Android Studio. We shall not cover the basics of the gradle files for this. We saw that in the previous episode i.e. Part 6. Please read that.
  • Add an App Engine module to the Android Project i.e. convert the Android Project into a multi-module project i.e. Android App and App Engine App
  • Study the Gradle files for the multi-module project that we now have
  • Cover some basic operations of dealing with App Engine within Android Studio. This is the Android Studio version of the stuff that we tried out via the App Engine Gradle plugin in Part 5.

Android Application

Allright, lets go ahead and create/generate our Android Application. We are going to be using the Android Studio Wizard to do that. Nothing fancy.

Click on New Project in the Quick Launch dialog. This should bring up the New Project wizard as shown below. I have stuck to tradition and called my project HelloWorldAndroid :-)

gradle-ep6-4

Just take all the defaults as shown in the next screens for the wizard.

gradle-ep6-5

gradle-ep6-6

gradle-ep6-7

Click on Finish to end the wizard and then it weaves some magic to generate the Android Studio project files for you. Be a bit patient.

Add an App Engine Module

Now that we have an Android project and an Android app module within the project i.e. app, let us move forward and make this a multi-module project by adding an App Engine module to this project.

To add a new module to your project, simply select File –> New Module. This will bring up the dialog as shown below:

ep7-1You will see several modules that you can add to your existing project. Three of these modules are specific to App Engine and you can see them in the list. For now, we shall just take the most basic one i.e. App Engine Java Servlet Module as shown above.

This is the same basic template that you would have got if you were using Eclipse and had generated a new Web Application using the Google Eclipse plugin. 

Click on Next to proceed. This brings up a dialog where you should specify your module app. I am naming it serverapp and I give it a package name for my Java code that would reside in there.

ep7-2

Click on Finish to generate the project. Once the project is generated, you will find that you have now an additional module named serverapp in the Project hierarchy as shown below:

ep7-4

You will also notice that you can now Run both the Android App and the App Engine if you want to. Just check out the Run option as shown below:

ep7-6

Gradle Files

In Part 3, we had covered multiple Java projects and how at the root folder, we can specify the settings.gradle and build.gradle files that apply across all the modules.

Let us recap, what we have so far:

  • We have an Android Studio Project
  • It has 2 modules
  • One module (app) is the Android app
  • One module (serverapp) is the App Engine app

So, let us look at the settings.gradle file at the root:

include ':app', ':serverapp'

It includes now both the app module and the serverapp module, which is how we had seen in Part 3 of this series.

Take a look at the build.gradle file at the root:

// Top-level build file where you can add configuration options 
// common to all sub-projects/modules.

buildscript {
 repositories {
   jcenter()
 }

dependencies {
 classpath 'com.android.tools.build:gradle:0.12.2'

// NOTE: Do not place your application dependencies here; they 
// belong in the individual module build.gradle files
 }
}

allprojects {
  repositories {
    jcenter()
  }
}

No surprises here. This should be understandable too. For allprojects, we are specifying the repository to be used. JCenter is another repository similar to MavenCentral that we had seen earlier. Additionally, we had seen in the earlier episode, how buildscript can be used to specify what is going to be needed to run the script itself. At that time, we had included the App Engine Plugin/SDK and now we have the Gradle library for the Android Tools Project.

app module – build.gradle

This section is a repeat from the previous episode:

Let us now, step inside of the app module. There you will find the module specific build.gradle that is shown below. Remember it is an Android app, so it will utilize the Android plugin and have Android plugin specific closures that make sense when compiling, building , running, packaging the Android application.

The app/build.gradle file is shown below:

apply plugin: 'com.android.application'

android {
  compileSdkVersion 20
  buildToolsVersion "20.0.0"

  defaultConfig {
     applicationId "com.mindstorm.helloworldandroid"
     minSdkVersion 19
     targetSdkVersion 20
     versionCode 1
     versionName "1.0"
  }

  buildTypes {
    release {
      runProguard false
      proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
      }
    }
 }

dependencies {
 compile fileTree(dir: 'libs', include: ['*.jar'])
}

Some of the important points are:

  • We specify the use of the Android plugin via the apply plugin command
  • Take a look at dependencies closure that we have seen earlier. Currently it simply adds all the JAR Files that you might add to the libs folder. Alternately, you can also add more of your dependencies here as we have seen earlier.
  • The android closure is a standard one that is used for specifying which SDK version to use for compiling, the minimum SDK Version supported, package name, versioning information and pro Guard related stuff. If you have built Android applications, this will be familiar. If not, you need to do a 101 course on Android Development and this stuff will be clear to you.

serverapp module – build.gradle

Let us now, step inside of the serverapp module. There you will find the module specific build.gradle that is shown below. Remember, this one is an App Engine application, so it will utilize the App Engine plugin. We had seen a similar looking build.gradle file in Part 5 of the series.

The serverapp/build.gradle file is shown below:

// Currently, the appengine gradle plugin's appengine devappserver launch doesn't interact well with Intellij/AndroidStudio's
// Gradle integration. As a temporary solution, please launch from the command line.
// ./gradlew modulename:appengineRun
// If you would like more information on the gradle-appengine-plugin please refer to the github page
// https://github.com/GoogleCloudPlatform/gradle-appengine-plugin

buildscript {
 repositories {
 mavenCentral()
 }
 dependencies {
 classpath 'com.google.appengine:gradle-appengine-plugin:1.9.6'
 }
}

repositories {
 mavenCentral();
}

apply plugin: 'java'
apply plugin: 'war'
apply plugin: 'appengine'

sourceCompatibility = 1.7
targetCompatibility = 1.7

dependencies {
 appengineSdk 'com.google.appengine:appengine-java-sdk:1.9.6'
 compile 'javax.servlet:servlet-api:2.5'
}

appengine {
 downloadSdk = true
 appcfg {
 oauth2 = true
 }
}

Some of the important points are:

  • The appengine plugin is required by the buildscript, so we are including it in the buildscript closure. This is same from Part 5.
  • We are applying the plugins : java, war and appengine. This is standard stuff again since we have java files, war tasks are needed to build/assemble the package into a WAR file and appengine plugins adds several tasks that include running local dev server, uploading your application to appengine runtime in the cloud, etc.
  • Take a look at dependencies closure that we have seen earlier. It includes the App Engine SDK 1.9.6 and also the Servlet jar , since this is a basic JAva Web app and we require the JAR to compile our Servlet classes. Take a peek into src/main/java folder and you will get it why.
  • And finally we have the appengine closure. We looked at that too in Part 5. The downloadSDK downloads the App Engine SDK in case you do not have it locally in the cache. Additionally, we are using the OAuth 2 mechanism in case you wish to deploy your project via the appengineUpdate task. This will open up a browser window, where you authenticate, get a code and paste it back to proceed with update of your application in to the cloud.

That’s about it really as far as the Gradle stuff is concerned. Once you understand the multi-module projects in Gradle, it becomes that much simple to understand the files that are getting generated in Android Studio vis-a-vis Gradle.

Gradle Tasks

Since we have now two modules in the application and each of them utilizes the respective plugins for Android and App Engine, you will notice that the Gradle tab found in the vertical navigation bar on the right will have tasks categorized based on both the modules.

ep7-3

Since we added the serverapp module, you can see that various App Engine tasks are now available. The Gradle support inside of Android Studio has done a gradle tasks in the background for both the folders/modules and presented the tasks here for you.

ep7-5

To execute any of the tasks, without the hassle of going to the terminal and execute it, simply double click on the tasks and it will start executing.

Keep in mind that anytime you make any changes to your build files, do remember to click on the Sync Project with Gradle Files as shown below. It should launch the build and you should be able to see the Gradle commands getting executed in the Gradle Console.

gradle-ep6-11

App Engine – Start / Stop Application

If you develop App Engine applications, then you will end up starting / stopping the local server. We had seen this in Part 5 via the App Engine plugin for gradle. Over here we can do that right within the terminal itself. Remember that as mentioned in the previous section, you can always double click on one of the Gradle Tasks and it should launch up. But the Terminal gives you good control over things and it sort of reinforces our understanding from previous episodes and hence I am covering that here. 

To start the Terminal, simply click on the Terminal Option that you will see in the status bar at the bottom. It will launch up a Terminal window for you and the directory will be shown.

ep7-7

When it opens up, it does so within the app module. I just go back one level to the root folder where the gradle wrapper files (gradlew and gradle) are present.

Remember that the task appengineRun was used to launch the App Engine dev server locally. We are simply firing up that task over here. Since it is inside the serverapp module, we are providing the whole namespace here. i.e. modulename:taskname

This will launch the App Server as shown below:

ep7-8

Once the Local Dev Server is started, we can test out if it is running by navigating to the localhost:8080 URL as shown below. And all should work well.

ep7-9

ep7-10

 

You can always open up another Terminal window by clicking on the sign. Over here, we open another terminal and actually fire the appengineStop task to shutdown the Dev Server when we want.

ep7-11

Recommended: Do try out other appengine Tasks directly from the Terminal and or by clicking on the tasks in the Gradle View.

Moving forward

This tutorial helped you understand a multi-module Android project within Android Studio. We took our existing knowledge of Gradle for multi-module Java projects and applied it to understand the files that were generated for both the Android and App Engine module within a particular Android Studio project.

In the next episode, we shall continue keep exploring the multi-module project inside of App Engine. Specifically, we shall look at another App Engine module Endpoints that helps you create a backend for your Android applications.

Till then, Happy Gradling!

Posted in Tools | 3 Comments

Gradle Tutorial : Part 6 : Android Studio + Gradle

Welcome to Part 6 of the Gradle Tutorial. In the previous episode i.e. Part 5, we took a look at building / running / deploying App Engine Java Web Applications via Gradle.

In this part of the tutorial, we shall take our first look at Android Studio and understand the Gradle environment in Android Studio. Since you are now aware of the basics of single, multiple Java projects with Gradle, it should become a bit easier to understand what they generate for you.

Along the way, we shall also take a look at various tabs, configuration settings and the terminal inside of Android Studio, so that you can opt to run gradle via the command line/terminal even inside of Android Studio. This will help you use the knowledge that you have gained so far.

Our goal in this episode will only be to familiarize ourselves with the Gradle environment inside Android Studio. It is by no means expected to be an Android tutorial.

as_plus_gradle

This part assumes that you have installed Android Studio on your development machine and that you are familiar with basic Gradle commands, project structure and files as we have seen in the series so far.

I have used Android Studio (Beta) 0.8.6 on Windows for this blog post. It is not necessary to have the same version or the OS, things should be pretty much similar from a Gradle perspective.

The points that we shall cover in this blog post are as follows:

  • Project Template Gradle Configuration Settings in Android Studio
  • Generate a basic Android Application and understand Project specific settings for Gradle
  • Understand Gradle Project build files generated for a basic Android Application
  • Look at various windows Tabs available for working with Gradle. For e.g. Gradle, Gradle Console and Terminal window tabs.
  • Look at how we can add more dependencies to our Android Project

Project Template Gradle Settings

Go ahead and launch Android Studio. Close all the Projects in case a default one opens up. This should bring you to the Quick Start window that you see below. The Configure option that you see below is an important one and helps you configure almost anything in the Android Studio IDE. And that includes some global Gradle settings.

Click on Configure. 

gradle-ep6-1

This will bring you to the Configure options as shown below. Some of these will be recognizable now. For e..g the SDK Manager, that allows you to download the required Android SDK libraries. Click on Settings as shown below:

gradle-ep6-2

 

This will bring up the Settings window and you will see a Gradle option as highlighted below. Do not worry about the Linked Gradle Projects, which is empty, once we create a project things will get linked but for now, ignore it.

gradle-ep6-3

 

Over here you see some global settings as follows:

  • Offline work : If you check this option, Gradle will use things from the cache itself for dependency resolution. In case the files are not there in the cache, then it will result in a build error.
  • The Service Directory Path is the default Gradle Home directory. This is where the cache is maintained, etc.
  • Gradle VM Options can be used to tweak some JVM Settings and/or provide some property files.

Do not worry too much about this but be aware of the Offline setting. This can cause some heartburn in case you have checked it i.e. enabled offline and then after adding some dependency, Gradle is not able to resolve it since it is going to look into the cache itself.

Android Application

Allright, lets go ahead and generate our Android Application. We are going to be using the Android Studio Wizard to do that. Nothing fancy.

Click on New Project in the Quick Launch dialog. This should bring up the New Project wizard as shown below. I have stuck to tradition and called my project HelloWorldAndroid :-)

gradle-ep6-4

Just take all the defaults as shown in the next screens for the wizard.

gradle-ep6-5

gradle-ep6-6

gradle-ep6-7

Click on Finish to end the wizard and then it weaves some magic to generate the Android Studio project files for you. Be a bit patient.

Gradle Project Files

The Project is now created and is opened up in Android Studio. Go to File -> Settings and this should bring up the Project settings dialog as shown below:

gradle-ep6-8

This looks similar to the Project Template dialog that we saw earlier. Except that the Project (HelloWorldAndroid) has got linked and there are additional Project-level settings that have got added. I suggest that you stick to the default ones. For e.g. there is a default Gradle distribution that is already shipped and linked up in your project, so that you do not need to separately go ahead and download Gradle and set it up. Choose this in most scenarios.

However, if you wish to be very specific and have requirements that require you to use your own Gradle build, then do provide the local gradle distribution. Click on the Gradle home selector option and point it to the root of your Gradle distribution.

For most of us, the default Gradle Wrapper is recommended and it will suit our needs.

Now, take a look at the Project Files that have got generated. You should have a similar screenshot that I have put below. I have highlighted the Gradle specific files for you to take a look at:

gradle-ep6-9

 

Let us go over these now. The files circled in green are the default gradle wrapper files that you can use from the terminal / command window (we shall see that in a while). They are nothing but a way for the IDE and yourself to launch gradle on your own anytime. We will look at it a little later in this post, but keep in mind that they are the files to run gradle.

In Part 3, we had covered multiple Java projects and how at the root folder, we can specify the settings.gradle and build.gradle files that apply across all the modules. Android Studio follows the same convention. 

In short, what we have is an Android Project and a module (app) inside of it. That module is an Android application that will need to be built as per Android rules and would need the Android Gradle plugin. Simple enough , isn’t it ?

So, let us look at the settings.gradle file at the root:

include ':app'

It includes just the app module, which is how we had seen in Part 3 of this series.

Take a look at the build.gradle file at the root:

// Top-level build file where you can add configuration options 
// common to all sub-projects/modules.

buildscript {
 repositories {
   jcenter()
 }

dependencies {
 classpath 'com.android.tools.build:gradle:0.12.2'

// NOTE: Do not place your application dependencies here; they 
// belong in the individual module build.gradle files
 }
}

allprojects {
  repositories {
    jcenter()
  }
}

This should be understandable too. For allprojects, we are specifying the repository to be used. JCenter is another repository similar to MavenCentral that we had seen earlier. Additionally, we had seen in the earlier episode, how buildscript can be used to specify what is going to be needed to run the script itself. At that time, we had included the App Engine Plugin/SDK and now we have the Gradle library for the Android Tools Project.

Let us now, step inside of the app module. There you will find the module specific build.gradle that is shown below. Remember it is an Android app, so it will utilize the Android plugin and have Android plugin specific closures that make sense when compiling, building , running, packaging the Android application.

The app/build.gradle file is shown below:

apply plugin: 'com.android.application'

android {
  compileSdkVersion 20
  buildToolsVersion "20.0.0"

  defaultConfig {
     applicationId "com.mindstorm.helloworldandroid"
     minSdkVersion 19
     targetSdkVersion 20
     versionCode 1
     versionName "1.0"
  }

  buildTypes {
    release {
      runProguard false
      proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
      }
    }
 }

dependencies {
 compile fileTree(dir: 'libs', include: ['*.jar'])
}

Some of the important points are:

  • We specify the use of the Android plugin via the apply plugin command
  • Take a look at dependencies closure that we have seen earlier. Currently it simply adds all the JAR Files that you might add to the libs folder. Alternately, you can also add more of your dependencies here as we have seen earlier.
  • The android closure is a standard one that is used for specifying which SDK version to use for compiling, the minimum SDK Version supported, package name, versioning information and pro Guard related stuff. If you have built Android applications, this will be familiar. If not, you need to do a 101 course on Android Development and this stuff will be clear to you.

That’s about it really as far as the Gradle stuff is concerned. You can see easily that it you have dependencies on other JARs, simply drop them into your libs folder. Alternately, you can add to the dependencies closure by specific repository entries for your dependent files.

Gradle Tasks

On the extreme right side of Android Studio, you will find a vertical navigation bar, which has tabs like Maven Projects, Gradle and Commander.

Go ahead and click on the Gradle tab in that navigation bar. You will be presented with the Project -> Module -> All the Gradle tasks that come under this project. Just like how you do a gradle tasks to determine what are the tasks available for the project, this window basically has done that for you and shows you the tasks available.

gradle-ep6-10

 

 

You do need to refer to the documentation for the respective plugin since it will have information on all the tasks and what they can do.

To execute any of the tasks, without the hassle of going to the terminal and execute it, simply double click on the tasks and it will start executing. And the output is what will be visible in the Gradle console, that we shall see next.

Gradle Console

The Gradle console is tucked away in at the right bottom corner. Simply click on it, to bring it up and you shall see a output from Gradle tasks/commands as they are being executed. As a test, you can launch any of the Gradle tasks that we saw earlier via the Gradle Tasks window. Or simply go to the main menu and click on Rebuild Project, Make Project or something like that and it will show you the output from running Gradle.

gradle-ep6-12

This is very handy when you have an error since it is important for you to see what went wrong during the build.

Use the Terminal

Welcome to the Terminal. In the previous episodes, we were running all Gradle stuff directly from the command line or the terminal. The Android Studio developers have made it easier by integrating it within Android Studio itself, so that you do not need to go out.

This is useful , especially if you are perfectly clear on the tasks that you want to launch and prefer launching it yourself rather than some obscure option somewhere on the menu.

gradle-ep6-13

 

To start the Terminal, simply click on the Terminal Option that you will see in the status bar at the bottom. It will launch up a Terminal window for you and the directory will be shown. You can now execute any Gradle tasks. For e.g. since we have mentioned that Gradle wrapper is provided to you by default, notice how I execute the Gradle tool from the command line to display all the tasks. Go ahead and try out a few commands.

See the + sign in the Terminal Window. You can use that to launch multiple terminals and fire different commands from there if you prefer that sort of a developer workflow. For e.g. in a subsequent episode, we shall see how we can use App Engine modules within Android Studio projects and then use two instances of Terminal : one for launching the Development Server and the other for Shutting down the Development Server and so on.

Tip

Typically if you update any of the Gradle files, it is recommended that you click on the Sync Project with Gradle Files option. This will fire off the default task that has been configured for your project. Just make this option your friend.

gradle-ep6-11

Adding Project Dependencies

Finally, a few words on adding additional dependencies in your project. At a high level, there are 2 ways that you can do that:

  1. You can directly modify the build.gradle files and the dependencies closure. Nothing stops you from doing that. These are straight forward files, go ahead and modify them and save them. Once you save your files, do remember the tip above of clicking the Sync Project with Gradle Files.
  2. If you prefer to use the help of a User Interface to fill out the dependencies (either on JARs, Maven Repository JARs or even other modules in the project), you can choose do the following : Right Click on the module (app) and then choose Module Settings as shown below:gradle-ep6-14
  3. This will bring up the Dialog as shown below:gradle-ep6-15
    You can notice that you can modify values on any of the Tabs and this will reflect in the build.gradle file accordingly.
  4. Let us specifically look at dependencies. Click on the Dependencies tab. This will show the current values that we have the dependencies closure for the build.gradle file in the app module.gradle-ep6-16
  5. Now, let us look at how to add more dependencies inside of this closure. Simply click on the button. The following options come up:gradle-ep6-17a) Library Dependency b) File Dependency and c) Module Dependency. And these are pretty much the different ways of adding dependencies that we have seen in Part 2 and Part 3.
  6. Let us click on Library Dependency. This will bring up the following dialog where we can specify some entry from the central Maven Library or even pick one that we may have locally in our cache. For e.g. Joda Time.gradle-ep6-18
  7. If we click OK, you will find that the dependencies closure of our build.gradle file will be modified accordingly as shown below:
    dependencies {
    
      compile fileTree(dir: 'libs', include: ['*.jar'])
      compile 'joda-time:joda-time:2.3'
    
    }

    Go ahead and try adding more dependencies either from Maven Repository or even from local files, etc. Remember to always ave and Sync Project with Gradle Files to kick off the build.

Moving forward

This tutorial helped you understand how Gradle is seamlessly tied into Android Studio and basic understanding of Gradle files, configurations and various tabs.

In the next episode, we shall continue to stay inside of Android Studio. and look at App Engine modules inside of your Android Studio Project.

suggest to read up on the Gradle Plugin User Guide for Android Tools. Since this is the tool that Google wants us to use moving forward for Android Development, it is important to make this user guide your friend.

Till then, Happy Gradling!

References

Posted in Tools | 3 Comments

Gradle Tutorial : Part 5 : Gradle App Engine Plugin

Welcome to Part 5 of the Gradle Tutorial. In the previous episode i.e. Part 4, we took a look at building Java Web Applications via Gradle.

In this part of the tutorial, we shall look at the App Engine Gradle plugin. If you are an App Engine developer, you will know that there are multiple ways in which you can work with your App Engine projects. You could use the Google Eclipse plugin, command line and even Maven to handle all things from build, local dev server and finally deployment to the live instance.

gradle

Well, you can now do all of that via Gradle too. You may ask why use Gradle, when you may already have got used to one of the other mechanisms to deal with your App Engine Developer flow (Eclipse plugin, Maven or Command Line). I think it is important to understand Gradle for the simple reason that over the last few months, we have seen that App Engine modules can be added to your Android applications inside of Android Studio. I personally think that we will over time see more of that happening and with Google putting its weight behind Android Studio + Gradle, we need to be ready for that. And trust me, since you already know quite a bit of Gradle by now, things fall in place quite well.

To summarize, this episode will be about a basic App Engine application that we shall build, run locally and deploy to the Cloud via Gradle App Engine plugin and its related tasks. Let’s get started.

This part assumes that you have a Gradle installation on your machine and the basic environment is setup. For more information on that, refer to Part 1. Additionally, you know the basics of using the Java plugin in Gradle, which we covered in Part 2 and building multiple and interdependent Java projects that we covered in Part 3. You are also familiar with basic Java Web Application projects, some of that we covered in Part 4.

Our Project Scenario

For this episode, we shall look at a basic Hello World App Engine project that I have created in the following folder structure as shown below::

helloappenginegradle
|- src
   |- main
      |- java
         |- hellogradle (Sources inside this package)
         |- META-INF
             |- jdoconfig.xml
             |- persistence.xml
         |- log4j.properties
      |- webapp
         |- WEB-INF
            |- appengine-web.xml
            |- logging.properties
            |- web.xml
         |- favicon.ico
         |- index.html
|- build.gradle

All the project source code , including the build files is available on Github. Please download it from here and keep it available on your machine, so that you can follow the tutorial and run it along as we go through this episode.

Now, let us talk in brief about the project and other requirements:

  1. The structure above is a standard App Engine Java project. I used the Eclipse plugin to generate it and place it in the folder (helloappenginegradle). There is nothing more to the App Engine project for now.
  2. The folder structure follows convention that we would like to follow for Gradle. So we have the src / main folder and inside of that we have the java and the webapp folder. Notice that we have the build.gradle project at the root of the project folder. 
  3. The java folder contains the Java sources and other resource files. We have the standard Hello Gradle Servlet present in the sources.
  4. The web folder contains any Web resources and the standard WEB-INF folder. The WEB-INF folder contains web.xml and more importantly the appengine-web.xml file that has App Engine application specific configuration data. For e.g. the <application> and <version> values, which will be used to deploy to the App Engine project id that we have created via the Google Cloud Console.
  5. I will assume that you are aware about the basics of App Engine deployment and that you have a Google Account, have created a Project via the Google Cloud Console and have correctly placed the Application Id value in the <application> tag in appengine-web.xml file.

build.gradle

The build.gradle file that is found at the root folder i.e. \helloappenginegradle is shown below. We will go through it step by step.

apply plugin: 'war'
apply plugin: 'appengine'

def appId = "hellogradle" 
def appEmail = "romin.irani@mindstormsoftware.com"
def appengineVersion = "1.9.6"

buildscript { 
  repositories { 
     mavenCentral()
  } 
  
  dependencies {
    classpath "com.google.appengine:gradle-appengine-plugin:1.9.6
  }
}

repositories {
  mavenCentral()
}

dependencies {
 appengineSdk "com.google.appengine:appengine-java-sdk:${appengineVersion}"
 compile "javax.servlet:servlet-api:2.5"
 compile "com.google.appengine:appengine-api-1.0-sdk:${appengineVersion}"
}

appengine {
  httpPort = 8888
  downloadSdk = true

  appcfg {
    email = "${appEmail}"
    noCookies = true
    oauth2 = true
  }
}

Let us go through the file in brief:

  1. We are applying the WAR plugin. This by default also applies the java plugin as we have seen in earlier episodes.
  2. We then apply the AppEngine plugin.
  3. We then define 3 variables and you may not define it and directly provide the values but it is just good practice. The variables are the App Engine Project Id that you would have created via the Google Cloud Console. The email address is the account which owns this project and finally we are specifying the App Engine SDK Version.
  4. You will notice a new closure buildscript. This is nothing to do with App Engine and is generally used to specify dependencies that the build script will need to it. In our case, this script requires the App Engine Gradle library to be present and hence we are specifying it via the normal dependency and specifying from which repository to take it.
  5. Next we have the dependencies that this project source code needs to compile. The standard App Engine, Servlet, etc JAR files are specified. At the end of this tutorial, you will also find a small note on how to include many other dependencies that your code might need around JDO/JPA, etc.
  6. Finally, we have the appengine closure that is required to specify various things like which port the local Dev Server will be started on, the authentication mechanism for deployment process. We will cover more on this as we move forward here but if you are familiar with App Engine, it should sound familiar.

You can look at the additional tasks that have been added by opening up a command window/terminal and navigating to the root folder.

Simple fire the following:

gradle tasks

and you should see additional tasks available via the App Engine plugin that you have applied. Some of the key tasks that were added and which we will use are highlighted in bold (appengineRun , appengineUpdate). If you are familiar with App Engine, most of the tasks can do is something that you would have tried out anyways. Tasks for every aspect of dealing with App Engine i.e. Logs, Cron Jobs, Starting/ Stopping and more are available.

Google App Engine tasks
-----------------------
appengineConfigureBackends - Configures backends on App Engine.
appengineCronInfo - Get cron information from App Engine.
appengineDeleteBackend - Deletes backend on App Engine.
appengineDownloadApp - Retrieves the most current version of your application.
appengineDownloadSdk - Downloads and sets Google App Engine SDK.
appengineEndpointsExpandClientLibs - Expand the generated client libraries sourc
es in to build/generated-source
appengineEndpointsExportClientLibs - Export the generated client libraries jars
to a user-defined destination
appengineEndpointsGetClientLibs - Generate Endpoints java client libraries for c
lasses defined in web.xml
appengineEndpointsGetDiscoveryDocs - Generate Endpoints discovery docs for class
es defined in web.xml
appengineEndpointsInstallClientLibs - Install generated client libs into the loc
al Maven repository
appengineEnhance - Enhances DataNucleus classes.
appengineExplodeApp - Explodes WAR archive into directory.
appengineFunctionalTest - Runs functional tests
appengineListBackends - Lists backends on App Engine.
appengineLogs - Download logs from App Engine.
appengineRollback - Undoes a partially completed update for the given applicatio
n.
appengineRollbackBackend - Rolls back backend on App Engine.
appengineRun - Starts up a local App Engine development server.
appengineStartBackend - Starts backend on App Engine.
appengineStop - Stops local App Engine development server.
appengineStopBackend - Stops backend on App Engine.
appengineUpdate - Updates your application on App Engine.
appengineUpdateAll - Updates your application and all backends on App Engine.
appengineUpdateAllBackends - Updates all backends on App Engine.
appengineUpdateBackend - Updates backend on App Engine.
appengineUpdateCron - Updates scheduled tasks definition (known as cron jobs) on
 App Engine.
appengineUpdateDos - Updates DoS protection configuration on App Engine.
appengineUpdateIndexes - Updates indexes on App Engine.
appengineUpdateQueues - Updates task queues on App Engine.
appengineVacuumIndexes - Deletes unused indexes on App Engine.
appengineVersion - Prints detailed version information about the SDK, Java and t
he operating system.

Running the Local Dev Server

This is a common task that one does while doing development. Assuming that you have download the project from Github and/or have your own App Engine project with the build.gradle file, you can fire the following command:

gradle appengineRun

You should see the following output in the console:

E:\helloappenginegradle>gradle appengineRun
:appengineDownloadSdk
:compileJava 
:processResources UP-TO-DATE
:classes 
:war 
:appengineExplodeApp 
:appengineRun

..... <Several other console statements>

Aug 15, 2014 3:18:38 AM com.google.appengine.tools.development.AbstractModule st
artup
INFO: The admin console is running at http://localhost:8888/_ah/admin
Aug 15, 2014 8:48:38 AM com.google.appengine.tools.development.DevAppServerImpl
doStart
INFO: Dev App Server is now running
> Building 85% > :appengineRun

Notice, how Gradle takes care of the task dependencies by checking if the SDK is present locally or not. If not, be very patient, since it will download the whole SDK (200MB approximately).

It then compiles the code, builds the WAR file, explodes that and then launches in the in-built web server via appengineRun. You can now go to http://localhost:8888 in the browser and it should navigate on to your index page. Remember that you can specify several parameters to guide the HTTP Server that will be launched on your machine. This is done via the appengine closure and for our build.gradle file, we had specified the httpPort as 8888. A section of that closure is shown below:

  appengine {
     httpPort = 8888
     .....
  }

If you look at the documentation for the App Engine plugin, you will also find several other properties that you can specify to control the Web Server launch. I have listed down some of them from the documentation.

  • httpAddress: The IP address for the local development server (if server is to be accessed from network). Default is localhost.
  • httpPort: The TCP port which local development server should listen for HTTP requests on (defaults to 8080).
  • warDir: Web application directory used for local development server (defaults to build/exploded-war).
  • disableUpdateCheck: Disables the Google App Engine update check if set to true.
  • jvmFlags: The JVM flags to pass on to the local development server. The data type is a List.

At any point in time, if you wish to stop the server, you can do that via the
gradle appengineStop task.

Deploying to App Engine

Once you have developed your app, tested in locally and if everything looks good, the next step is to deploy the application to App Engine.

This is a fairly interesting task and you can do that via the following command:

gradle appengineUpdate

But before you go right ahead and launch it, let us recollect first what is needed to deploy the application to App Engine.

  1. You need to have the Application Id and version of the App Engine application that you want to deploy in the cloud. These values will need to be set in the WEB-INF\appengine-web.xml file as is the standard for Java App Engine applications.
  2. You need to have your Account Name and Password ready, so that you can be authenticated/authorized to move forward with deployment.
  3. Given the above two things and ofcourse your project files, the appengineUpdate task is clever enough to do all the heavy lifting for you.

However, it is important to understand how the script will authenticate itself via your credentials. You have to make a decision for that and whether you want your Admin credentials to be remembered via a cookie or not. The Plugin gives you the flexibility to control it via any process that you see fit for your deployment workflow.

So, you can opt for a prompt for password mechanism , where you will be asked for a password and you can enter that, before the deployment process moves forward. Else, you could also opt for a OAuth2 mechanism, where a browser window launches for you to login and authorize your Google Account for deployment and then you need to paste the Authentication Token to move forward.

It can be quite confusing the first time, so let me show you both the options. But first,  see where that magic is specified in the build.gradle file.

The required snippet from the file is shown below (this could be different that the one that is hosted and which you may download via the Github link)

...
def appId = "hellogradle"
def appEmail = "romin.irani@mindstormsoftware.com"
....
appengine {
  httpPort = 8888
  downloadSdk = true

  appcfg {
    email = "${appEmail}"
    noCookies = true
    
  }
}

 

Specifically, focus on the appcfg closure.

  • It has an email property that is my Google Account under which I have created the hellogradle project.
  • It has a noCookies property that ensures that my Sign In credentials will not be stored. If this property is set to true, then every single time that you do an update, it will require that the authentication process is done , whether it is oauth2 or via the password.

To deploy the project, we will fire the following command:

gradle appengineUpdate

This will go through the necessary steps and you will find that it waits at the password prompt as shown below:

E:\helloappenginegradle>gradle appengineUpdate
:appengineDownloadSdk
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:war UP-TO-DATE
:appengineExplodeApp UP-TO-DATE
:appengineUpdate
Reading application configuration data...
Aug 15, 2014 10:46:20 AM com.google.apphosting.utils.config.AppEngineWebXmlReade
r readAppEngineWebXml
INFO: Successfully processed E:/helloappenginegradle/build/exploded-app\WEB-INF/
appengine-web.xml
Aug 15, 2014 10:46:20 AM com.google.apphosting.utils.config.AbstractConfigXmlRea
der readConfigXml
INFO: Successfully processed E:/helloappenginegradle/build/exploded-app\WEB-INF/
web.xml

Beginning interaction for module default...
> Building 85% > :appengineUpdatePassword for romin.irani@mindstormsoftware.com:

Go ahead and start typing the password inside the console/terminal itself and press enter, it will validate the password and go ahead with the deployment as shown below:

0% Created staging directory at: 'C:\Users\irani_r\AppData\Local\Temp\appcfg8064
659880720537353.tmp'
5% Scanning for jsp files.
20% Scanning files on local disk.
25% Initiating update.
28% Cloning 3 static files.
31% Cloning 25 application files.
40% Uploading 0 files.
52% Initializing precompilation...
90% Deploying new version.
95% Closing update: new version is ready to start serving.
98% Uploading index definitions.

Update for module default completed successfully.
Success.
Cleaning up temporary files for module default...
BUILD SUCCESSFUL
Total time: 37.594 secs

Now, you can also do the following:

  • If you do not want to enter your password again, you can specify the password in plain text via the password property.
  • Alternately, since the password is now captured, you could opt to go for the noCookies = false and let the process use the password that it knows.

I suggest that you try out various combinations. As per the documentation, you can even specify the password in a separate properties file. You can try that too.

Now, let us try the following snippet – which bypasses the password prompt and instead goes for the OAuth2 mechanism. The only change we have made is that we have introduced another property of the appcfg closure called oauth2 and made that as true.

The snippet is shown below:

appcfg {
 
 email = "${appEmail}"
 noCookies = true
 oauth2 = true

}

If we now run the gradle appengineUpdate task, we get the entire OAuth2 Dance started via the browser.

First, you will see the normal tasks getting executed as shown below:

E:\helloappenginegradle>gradle appengineUpdate
:appengineDownloadSdk
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:war UP-TO-DATE
:appengineExplodeApp UP-TO-DATE
> Building 85% > :appengineUpdate

Next, it will popup a browser window, where you will authorize the process of deployment via your account. A screenshot is given below:

gradle-ep5-3 gradle-ep5-2

Once you accept the process, it will show the following:

gradle-ep5-3

You need to now paste this code and go back to the terminal. Simply paste it there and the rest of the process of deployment moves forward:

> Building 85% > :appengineUpdate4/tUZl_B2_k7AU4xLkbVaqLLmbCQ4c.ssxy9yQGz7kTBrG_
bnfDxpKI8UGwjwI
:appengineUpdate
Please enter code: Reading application configuration data...
Aug 15, 2014 10:56:40 AM com.google.apphosting.utils.config.AppEngineWebXmlReade
r readAppEngineWebXml
INFO: Successfully processed E:/helloappenginegradle/build/exploded-app\WEB-INF/
appengine-web.xml
Aug 15, 2014 10:56:40 AM com.google.apphosting.utils.config.AbstractConfigXmlRea
der readConfigXml
INFO: Successfully processed E:/helloappenginegradle/build/exploded-app\WEB-INF/
web.xml
Beginning interaction for module default...
0% Created staging directory at: 'C:\Users\irani_r\AppData\Local\Temp\appcfg8235
825904506985013.tmp'
5% Scanning for jsp files.
20% Scanning files on local disk.
25% Initiating update.
28% Cloning 3 static files.
31% Cloning 25 application files.
40% Uploading 0 files.
52% Initializing precompilation...
90% Deploying new version.
95% Closing update: new version is ready to start serving.
98% Uploading index definitions.
Update for module default completed successfully.
Success.
Cleaning up temporary files for module default...
BUILD SUCCESSFUL

This completes our little tutorial on using the App Engine Gradle plugin. There is a lot more to it, and you should check out the complete documentation.

App Engine JDO/JPA Code

If you are planning to migrate your existing App Engine projects over to using Gradle as your build tool, you will need to do a bit more work than what we have seen in this episode. Specifically, I would advise that you look at the following 2 points:

  • If you are using Eclipse, you will notice that there are several App Engine JAR files that are linked up in the Java Build Path. You should carefully add compile dependencies to your build.gradle file for all these JAR files. For e.g. take a look at this Stack Overflow question where the sample build.gradle file contains various dependencies. You will need to be accurate with the versions for your project. For e.g. some additional compile dependencies than the ones that we have seen so far could be something like the one shown below:
        // Persistence
        compile 'org.ow2.asm:asm:4.0'
        compile 'org.datanucleus:datanucleus-api-jpa:3.1.3'
        compile 'org.datanucleus:datanucleus-api-jdo:3.1.3'
        compile 'com.google.appengine.orm:datanucleus-appengine:2.1.2'
        compile 'org.datanucleus:datanucleus-core:3.1.3'
        compile 'org.apache.geronimo.specs:geronimo-jpa_2.0_spec:1.0'
        compile 'javax.jdo:jdo-api:3.0.1'
        compile 'javax.transaction:jta:1.1'
  • If using JDO and JPA code, you should keep in mind that the Entity classes need to be enhanced to weave in the persistent code. To do that, the App Engine plugin for Gradle, provides a closure named enhancer, the documentation for which I produce below:

Within appengine you can also define a closure named enhancer:

  • version: The version (v1/v2) parameter for App Engine datanucleus enhancer task
  • api: The api (jdo/jpa) parameter for the App Engine datanucleas enhancer task
  • enhanceOnBuild: Automatically run the enhancer (defaults to false)

for e.g.

enhancer {
version
= "v2"
enhanceOnBuild
= true
}

Moving forward

This tutorial helped you understand how to build , locally run and deploy your App Engine Applications.

Google App Engine modules are now supported inside of Android Studio. As a result of that, it is important that you understand what went on in this chapter. It will make the task of understanding the Gradle build files for Android Studio projects that contain an App Engine module that much easier.

In the next episode, we shall begin our journey to Android Studio. Gradle files are generated by default for you in Android Studio, but our learnings so far from Part 1 to Part 5 of this series will hold us in good stead to understand and modify stuff as needed.

Till then, Happy Gradling!

References

Posted in Tools | 6 Comments

Gradle Tutorial : Part 4 : Java Web Applications

Welcome to Part 4 of the Gradle Tutorial. This part takes off from Part 3 , where we covered building multiple interdependent Java projects.

In this part of the tutorial, we shall look at building Java Web Applications via Gradle. As is the pattern, we shall have a multi-project scenario where we will have one Java Project that has some utility class and which is built separately. And then we have a Java Web Project that is dependent on this project and has JSP/Servlets and so on.

In the process, we shall look at 2 additional plugins that Gradle provides, which will make our task easier. The plugins are:

  1. War Plugin : This plugin allows us to compile and assemble a WAR (Web Application Archive) file from our Java Web Application.
  2. Jetty Plugin : This plugin allows us to run our web application inside of a Jetty container. Very useful to test out the project quickly.

This part assumes that you have a Gradle installation on your machine and the basic environment is setup. For more information on that, refer to Part 1. Additionally, you know the basics of using the Java plugin in Gradle, which we covered in Part 2 and building multiple and interdependent Java projects that we covered in Part 3.

Our Project Scenario

For this episode, we shall look at 2 projects that are arranged under a common directory. Our root directory is going to be called mywebapp and inside of that we shall have 2 folders that will contain individual projects as shown below:

mywebapp
|- utils
|- web

All the project source code , including the build files is available on Github. Please download it from here and keep it available on your machine, so that you can follow the tutorial and run it along as we go through this episode.

Now, let us talk about the dependencies. These dependencies are something like this:

  1. utils: This project contains some utility code and hence it will not depend on any of the other projects. The Java code in this project depends on an external Java Date Time Library : Joda Time. So we will need to have that dependency defined for this project.
  2. web: This is a Java Web Application project, that just has a simple Servlet and JSP file, along with the web.xml file. This project depends on the utils project, since it uses the utility Java class from there. Along with that dependency, it also has dependency on the Servlet Jar file that is needed to compile Java HTTP Servlet code.

Multiple Gradle files

As we had seen in the last episode, it is better to create multiple build.gradle files, so that we can customize and maintain the build specific requirements for each project in a much more maintainable fashion.

In essence, what we are ending up with is a structure that looks like the following:

/mywebapp
|- /utils
     |- build.gradle
     |- (Java Sources and files)
|- /web
     |- build.gradle
     |- (Java Sources , JSPs and files)
|- settings.gradle
|- build.gradle

settings.gradle

Since, we have two projects (utils and web), our settings.gradle will reference both the project as shown below:

include ":utils",":web"

build.gradle

The build.gradle file that is found at the root folder i.e. \mywebapp is shown below. You will notice that since both of these are Java projects, we are applying the Java plugin and also specifying that Maven Central be used for downloading any dependent libraries:

subprojects {
  
  apply plugin : "java"
 
  repositories {
     mavenCentral()
  }
}

Now that we have got the common configuration out of the way, let us look at the individual build.gradle files that will be present in each of the projects i.e. web and utils.

utils project – build.gradle

The build.gradle file for the utils project is shown below:

apply plugin: "java"
dependencies {
 compile "joda-time:joda-time:2.4"
}

The above is a straight forward build.gradle file. It is applying the Java plugin. You need not mention it since it is specified for all subprojects in the common build.gradle at the root folder, but I am just mentioning it here, so that you have a complete build.gradle file.

The next line defines the dependency on the joda-time library. We have got the group id, artifact id and the version from the Maven Central library over here.

Please note that if you download the source code from Github, the utils project only contains a single Java utility class under the conventional directory structure as shown below:

gradle-ep4-1

Note the conventional structure i.e. inside of the utils project. I have the src/main/java folder and inside of that are my package structure and Java class names. So for example, in the above case, the Java class is DateUtils and its package is com.mindstorm.apputils.

web project – build.gradle

Now, let us look at the build.gradle file for the web project. We will introduce the Jetty plugin a bit later.

The initial version of the build.gradle file is shown below:

apply plugin: "war"

dependencies {
     compile project(":utils")
     compile "javax.servlet:servlet-api:2.5"
}

Here we are applying the War plugin. Additionally, we are making this project dependent on the utils project and on the Servlet API 2.5 version, since we have some Servlets in this project.

As per the documentation “The War plugin extends the Java plugin to add support for assembling web application WAR files. It disables the default JAR archive generation of the Java plugin and adds a default WAR archive task.”

The plugin also adds the war and assemble tasks to the tasks available for the project.

You can look at the additional tasks that have been added by opening up a command window/terminal and navigating to the web folder.

Simple fire the following:

gradle tasks

and you should see additional tasks available via the war plugin that you have applied:

Build tasks
-----------
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 classes 'main'.
clean - Deletes the build directory.
jar - Assembles a jar archive containing the main classes.
testClasses - Assembles classes 'test'.
war - Generates a war archive with all the compiled classes, the web-app content
 and the libraries.

Building the WAR file

Since we have made the web project depend on the utils project, we can build the entire Web Application, by going to the web folder in the terminal and firing the following command:

gradle assemble

You should see the following output in the console:

E:\mywebapp\web>gradle assemble
:utils:compileJava
:utils:processResources UP-TO-DATE
:utils:classes
:utils:jar
:web:compileJava
:web:processResources UP-TO-DATE
:web:classes
:web:war
:web:assemble

BUILD SUCCESSFUL

Total time: 5.804 secs

Notice, how Gradle takes care of the dependencies by compiling the utils project first and then building out the web project.

At this point in time, you should have a build folder inside your web folder. Go to the libs folder inside the build folder and you will find that the .war file has been generated for you.

The Jetty Plugin

It would be cool if we could not just build out the WAR file but also deploy it inside of the Jetty container and run the application for us to test out. That is exactly what the Jetty plugin can do for you.

To do this, we will modify our build.gradle file for the web folder as shown below:

apply plugin: "war"
apply plugin: "jetty"

dependencies {
 compile project(":utils")
 compile "javax.servlet:servlet-api:2.5"
}

httpPort = 8080

Notice the additional entries that we have added in bold. We have simply applied the Jetty plugin and also provided one of the standard properties available to configure the Jetty Web Server when it is launched i.e. the HTTP Port. We have specified 8080 as the value.

Save the above in the build.gradle file. Go to the web folder again and fire the following command again:

gradle tasks

You will notice that the additional tasks around Jetty have also got added now (only the additional Jetty tasks are shown in the output below):

Web application tasks
---------------------
jettyRun - Uses your files as and where they are and deploys them to Jetty.
jettyRunWar - Assembles the webapp into a war and deploys it to Jetty.
jettyStop - Stops Jetty.

The tasks look straightforward. Our goal should be now to assemble the WAR, deploy the same into Jetty and run the server too.

To do that, simply give the following command in the web project.

gradle jettyRunWar

This will build things, if they are updated and you should see output similar to the following:

E:\mywebapp\web>gradle jettyRunWar
:utils:compileJava UP-TO-DATE
:utils:processResources UP-TO-DATE
:utils:classes UP-TO-DATE
:utils:jar UP-TO-DATE
:web:compileJava UP-TO-DATE
:web:processResources UP-TO-DATE
:web:classes UP-TO-DATE
:web:war UP-TO-DATE
> Building 88% > :web:jettyRunWar > Running at http://localhost:8080/web

This means that the server has got started with our web application and is available at http://localhost:8080/web.

If we navigate to the URL in a browser, we see the web application come up nicely as shown below:

gradle-ep4-2

You can even visit the servlet configured if you want:

gradle-ep4-3

To stop the Jetty Web Server, you can open up another console/terminal and fire the following command:

gradle jettyStop

Moving forward

This tutorial helped you understand how to build your Java Web Applications using Gradle. Specifically, we looked at how the WAR and Jetty Plugin makes this possible.

I recommend that you also look at a couple of examples that ship with the standard Gradle build. These examples are present in samples/webApplication folder of your Gradle installation directory. The folder has two examples : quickstart, which is sort of what we have seen here. The other example customized is interesting and shows how you can move away from convention and specify exactly what files and from where it should take to build the Web application.

In the next episode, we shall look at the Google App Engine plugin in Gradle, and how it can help build/run/deploy our Java Web applications written for the App Engine platform.

Till then, Happy Gradling!

References

Posted in Tools | 4 Comments

Gradle Tutorial : Part 3 : Multiple Java Projects

Welcome to Part 3 of the Gradle Tutorial. This part builds on Part 2, where we looked at using the Java plugin in Gradle to compile/build our Java project.

In this part of the tutorial, we shall look at a common scenario where you will have multiple Java projects that could be dependent on each other. For e.g. You could have a library project where you write some utility classes and another Java project that depends on it.

This part assumes that you have a Gradle installation on your machine and the basic environment is setup. For more information on that, refer to Part 1. Additionally, you know the basics of using the Java plugin in Gradle, which we covered in Part 2.

Just to remind readers, the focus will be on understanding Gradle and how it goes about doing stuff when it comes to Java projects. So we will not be worried about the Java code that goes into those projects.

Multiple Project Scenario

For this episode, we shall look at 3 projects that are arranged under a common directory. This is just for demonstration but it will help us understand the concepts well.

Our directory will be called javaprojects and inside of that we have 3 other folders that will house the individual projects as shown below:

javaprojects
|- api
|- common
|- app

Now, let us talk about the dependencies. These dependencies are something like this:

  1. common: This project contains some utility code and hence it will not depend on any of the other projects. Do note that this does not mean that common does not have dependencies on external libraries for compilation. So that concept that we saw in the earlier chapter still remains. It may depend on 3rd party JARs.
  2. api : This project contains some API code and it depends on common project
  3. app : This project contains the application code and it depends on api and common projects

On my machine, I have created a folder named e:\javaprojects and inside of that I have 3 empty folders api, common and app. I have intentionally left them empty for now, so that you can see how it will all come together.

You can select the appropriate drive and/or root folder, but for the purpose of this episode, e:\javaprojects is my container for the other 3 projects.

While they are empty, you can easily visualize that in reality you will have Java classes inside of each of these folders. And since we are going to eventually use the Java Gradle plugin to compile the code, the Java classes inside of these folders will follow convention i.e. they will be present under src/main/java folder as we saw in Part 2.

Including Multiple Projects in Build

The first thing you should think of is a central place to control the overall build for all the 3 projects. Gradle makes this easy for you by asking you to create a settings.gradle file in the root folder.

So, in the e:\javaprojects folder, create a file named settings.gradle and in the file, all we will need to do is mention the projects (i.e. the folders) that comprise our 3 Java Projects i.e. api, common and app. The settings.gradle file is shown below:

include ":api", ":common", ":app"

Common Configuration

You are familiar with the build.gradle file, which is what the Gradle command looks for in terms of what it has to do.

Create a build.gradle file in e:\javaprojects directory. This will be our file that will specify what Gradle needs to do.

Remember we do not have any Java files so far in any of the 3 directories : app, common and api.

Let us look at one of the recommended and fairly intuitive structures for the build.gradle file as shown below:

allprojects {
  //Put instructions for all projects
}

subprojects {
  //Put instructions for each sub project
}

To understand what is happening, update your build.gradle file in the root folder i.e. e:\javaprojects to contain the following:

allprojects {
  task hello << { task -> println "I'm $task.project.name" }
}

subprojects {
  
}

What have we done here ? We have added a task (written in Groovy) to simply print out the project name. And we have put that inside the allprojects closure. This means that it will apply to all the projects.

Save the build.gradle file and go to the root folder at the command prompt/terminal where the build.gradle file is, and fire the following command:

gradle -q hello

This will produce the output as given below:

I'm javaprojects
I'm api
I'm app
I'm common

You can also fire the task individually for any specific project, as given below:

gradle -q app:hello

This will produce only app specific output as given below:

I'm app

This should make things clear that you can apply commands to all projects and then you have full control on how to run it i.e. run it in such a way that it applies to each project or any specific project.

Apply Java plugin to Sub Projects

Now, we know that the 3 projects : api, common and app are Java projects. Hence we can do the following for the 3 Projects:

  • Apply the Java plugin
  • Setup the MavenCentral repository, assuming that these projects will have 3rd party dependencies , which we would like to pick up from Maven Central.

The build.gradle file in the root folder will now look like the following:

allprojects {
  task hello << { task -> println "I'm $task.project.name" }
}

subprojects {
  apply plugin: "java"
  repositories {
      mavenCentral()
  }
}

We know that the Java plugin adds several tasks like clean, assemble, build, etc, which make it easy to work with the build process if you follow conventions. We saw that in Part 2, if you wish to refer to that.

By putting those commands inside of subprojects, we have essentially injected common characteristics into each of the sub projects i.e. common api and app.

Go back to the command prompt or terminal and fire the following command:

gradle build

You will find in the output (which I am not listing here) that the build task got fired on each of the projects and all tasks that it was dependent on is also executed. Cool isn’t it.

Remember, if you just wish to build the common project, you can always invoke the following (gradle <project-name>:<task-name>):

gradle api:build

We do not have any Java files in any of the folders so far, but that is fine for now.

Project Specific Configuration

What if you wanted to apply some tasks , plugins, dependencies differently to each project and or one or more projects and not all of them.

For the 3 projects that we have, the build.gradle file would need to look something like this:

allprojects {
  task hello << { task -> println "I'm $task.project.name" }
}

subprojects {
  apply plugin: "java"
  repositories {
      mavenCentral()
  }
}

//API Project specific stuff
project(':api') {
}

//Common Project specific stuff
project(':common') {
}

//App Project specific stuff
project(':app') {
}

As an example, let us say that we would like to apply the java plugin only to common project and not to any of the other projects. An example of such a build.gradle is shown below:

allprojects {
  task hello << { task -> println "I'm $task.project.name" }
}

subprojects {
   //Some other stuff (Empty for now)  
}

//API Project specific stuff
project(':api') {
}

//Common Project specific stuff
project(':common') {

   apply plugin: "java"
   
   repositories {
     mavenCentral()
   }
}

//App Project specific stuff
project(':app') {
}

Save the above build.gradle file.

Now fire the following command :

gradle app:build

This should give us the error that there is no build task for project app. This is because build task is only available in the project for which the Java plugin has been applied.

FAILURE: Build failed with an exception.

* What went wrong:
Task 'build' not found in project ':app'.

Similarly, if you fired the following command:

gradle common:build

You will find that it executes the build task successfully since it is available for that project as per our build.gradle file.

:common:compileJava UP-TO-DATE
:common:processResources UP-TO-DATE
:common:classes UP-TO-DATE
:common:jar UP-TO-DATE
:common:assemble UP-TO-DATE
:common:compileTestJava UP-TO-DATE
:common:processTestResources UP-TO-DATE
:common:testClasses UP-TO-DATE
:common:test UP-TO-DATE
:common:check UP-TO-DATE
:common:build UP-TO-DATE

BUILD SUCCESSFUL

Total time: 3.681 secs

Project Compilation Dependencies

Recollect that we had defined our project dependencies as follows:

  1. api depends on common
  2. app depends on api and common

In addition, we will also need to consider that each of the projects might have dependencies on 3rd party JAR files.

So , let us say that the requirements to compile the projects are as follows:

  1. common requires Apache Commons Lang 3.3.2
  2. api requires Apache Commons Lang 3.3.2 and Apache Log4j 1.2.7
  3. app requires Apache Log4j 1.2.7
  4. All of the projects have JUnit Test cases and require that the JUnit Jar file is linked. Any JUnit JAR file above 4.x will do.

Given the above requirements (I am not going to show you the source Java files or JUnit Test cases, since that is not necessary here), our build.gradle file that is present in the root folder will look like this:

subprojects {
  apply plugin: "java"
  repositories {
      mavenCentral()
  }

 dependencies {        
    testCompile "junit:junit:4+"
 }
}

//Common Project specific stuff 
project(':common') { 
  dependencies {
    compile 'org.apache.commons:commons-lang3:3.3.2'
  }
} 

//API Project specific stuff 

project(':api') { 
   dependencies {
      compile project(':common')
      compile 'org.apache.commons:commons-lang3:3.3.2'
      compile 'log4j:log4j:1.2.17'
   }
} 


//App Project specific stuff 

project(':app') { 
   dependencies {
      compile project(':common'), project(':api')
      compile 'log4j:log4j:1.2.17'
   }
}

Some notes on the above build.gradle file:

  • In the subprojects closure, we have added the stuff that is common to each project i.e. applied the Java plugin, added the maven repository and added the common dependency on JUnit JAR for the testCompile configuration.
  • Then for each of the sub projects, we have clearly specified the dependencies , not just on the project but also on any individual JARs.
  • Please note that we have considered only the compile configuration in the build file here. You can always target other configurations provided by Java plugin like testCompile, run, testRun and so on. So you can enhance the file depending on your requirement.
  • The compilation dependency on another project is specified via the
    compile project(<projectname>) statement
  • The compilation dependency on a JAR file is specified via the same mechanism that we saw in Part 2 i.e. “group:name:version”

As an exercise, I suggest adding a few of your own Java files, setting up the correct dependencies and then firing the gradle build command.

One or multiple build.gradle files?

The question that you should be asking now is whether it is the right approach to create a single large build.gradle file in the root folder that will:

  • Apply common code within the subprojects closure
  • Contain individual project(<projectname>) closures that will define tasks specific to that project, its own dependencies, etc.

We have an example of one such build.gradle file in the previous section. A good practice is actually not to have one single file but to break them into multiple build.gradle files and each of these specific build.gradle files will be present in the respective root folders of the 3 projects i.e. app, common and api.

In essence, what we are ending up with is a structure that looks like the following:

/javaprojects
|- /api
     |- build.gradle
     |- (Java Sources and files)
|- /common
     |- build.gradle
     |- (Java Sources and files)
|- /app
     |- build.gradle
     |- (Java Sources and files)
|- settings.gradle
|- build.gradle

Notice how at the root, we will continue to have the settings.gradle that includes all the projects as we saw.

There is a build.gradle at the root also. This will contain stuff that is common to each of the sub projects. For e.g. since each of our sub projects are Java projects and we plan to use the Maven Central repository, the contents of our build.gradle could be as short as the following:

subprojects {

  apply plugin: "java"
 
  repositories {
    mavenCentral()
  }

  dependencies {
     testCompile "junit:junit:4+"
  }
}

Now, our individual build.gradle for the specific projects will be roughly as shown below:

build.gradle for app project

dependencies {
      compile project(':common'), project(':api')
      compile 'log4j:log4j:1.2.17'
}

build.gradle for api project

dependencies {
      compile project(':common')
      compile 'org.apache.commons:commons-lang3:3.3.2'
      compile 'log4j:log4j:1.2.17'
   }

build.gradle for common project

dependencies {
    compile 'org.apache.commons:commons-lang3:3.3.2'
  }

In this way, you can manage the Gradle build files separately for each project. It will be easier in the long run to do things in this fashion, so that any new project can be added and its specific dependencies / tasks can be handled in its own build.gradle file.

Keep in mind that each of these individual build.gradle files can be enhanced to as much extent as you want depending on your requirements.

Recommended Reading

I suggest that you look at the following documentation in Gradle that contains a lot more examples and will help in solidifying your understanding : Multi-Project Builds.

As an exercise, if you use Android Studio and have attempted to generated both an Android project and an App Engine project, you will now be able to understand what has been generated when it comes to Gradle. You will find a settings.gradle there with all your modules in the Android Studio Project. It will contain a base build.gradle file that will contain common behaviour and then individual build.gradle files for each of the plugins. You should feel more confident of things now. We will get to those in a while, so if you do not want to revisit your Android Studio for now, that is fine too. 

Moving forward

We have moved quite a bit now in our Gradle journey. By now, you should start feeling comfortable with the whole thought process of building your projects and how Gradle fits into the project.

But we still have a long way to go and the next logical step to take for us is to look at Gradle War (Web Application Archive) plugin that helps with Java Web projects. That is covered in the next part. Till then, Happy Gradling!

References

Posted in Tools | 6 Comments

Gradle Tutorial : Part 2 : Java Projects

Welcome to Part 2 of the Gradle Tutorial. This part builds on Part 1, where we looked at installing Gradle and learnt a few basic commands.

In this part of the tutorial, we shall look at how you can use Gradle to compile/build/test your Java projects. The focus will be more on Gradle mechanics rather Java code, so I will be using simple Java projects that help illustrate the Gradle concept. You should be able to build on this while tackling a larger Java code base.

This part assumes that you have a Gradle installation on your machine and the basic environment is setup. For more information on that, refer to Part 1.

Gradle : Project , Tasks and Plugins

Let us recap a few things from the previous session and add to it some more stuff that will be required in this tutorial.

To summarize, the build.gradle was the file that we wrote to drive our Gradle build process and the build file contained tasks i.e. instructions to do something. Think of tasks as the ones that we would normally do if we did not have any of these tools to manage the build process. These tasks would be compile, test, build the jar, deploy, etc.

We do not have to write all these tasks by hand and just like what we have seen with other build tools and our IDEs, plugins come to our rescue. There are several Gradle plugins that make it easier for us to simply invoke the Tasks and if we follow convention, then Gradle does the rest for us.

What do we mean by a Plugin ? A plugin is a mechanism by which we can extend the capabilities of Gradle. Gradle need to know how to build everything and anything for us. But we can make that possible if we know a certain process and can create pre-built tasks that it can then perform for us. This is the role of a plugin.

The series will not focus on how to write a Gradle plugin. Rather we will use great Gradle plugins that are available to us to do our job. These plugins will add tasks that we can invoke straightaway. And you know what a Task is .. correct ? We saw that in the first part.

Just bear with me a little bit more .. things will fall in place.

Java plugin

Let us start with the most important of all for Java developers : the Java plugin. As expected, this plugin adds the following capabilities to a project:

  • compilation
  • testing
  • bundling

Logically, this is all we need to do with our Java projects, isn’t it ? The bundling typically would mean a JAR file in most cases.

Any plugin that you need to use should be added to the build.gradle file via the following statement:

apply plugin: <plugin-name>

In our case, since we want to use the Java plugin, we will use the following statement:

apply plugin: "java"

Let us get started with understanding what goes on behind the scenes.

Create a folder say example2 on your machine. You can use any folder that you wish on your machine. Just make sure that you follow one that suits your environment and that gradle is available from any directory on your machine.

Create our standard build.gradle in this folder. Just put the following line shown below in the build.gradle:

apply plugin: "java"

As discussed earlier, the plugin will add a bunch of tasks that know how to deal with typical Java projects. Let us fire the following command to understand what tasks have been added:

gradle tasks

This will produce the following output ( I am only including the buildTasks from my output):

Build tasks
-----------
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 classes 'main'.
clean - Deletes the build directory.
jar - Assembles a jar archive containing the main classes.
testClasses - Assembles classes 'test'.

As you can see, various tasks have been added and most of them are intuitive enough for you as a Java Developer to understand. For e.g.

  • clean will delete a build directory, all your classes will be removed for a fresh compile.
  • assemble will create an archive (JAR) file from your Java project and will run all other tasks that require compile, test and so on.

These tasks could also depend on each other and so on. Refer to the documentation for a complete dependency graph of these tasks.

Basic Java Project with Gradle Java plugin

Given this basic information, the first question that should strike you is that now that you have added the Java plugin and have some idea about the tasks that it provides i.e. clean, assemble, build, etc. , how do we invoke it ?

We already know that to invoke the tasks, all we need to do is fire the gradle <task-name> command. That is fine but what about my Java project i.e. the .java files and so on. Where is that ? What are the rules to follow for that ? Is there any conventions to follow so that the plugin knows exactly what to do ? What if my folder structure is different, will Gradle be able to help there?

The above are valid questions and Gradle has an answer for all of them. In this tutorial, we shall be following convention which means that the Java plugin of Gradle will look for files in certain folders. But be assured that if you prefer a non-convential way, you can get those things addressed via Gradle too – just that it is out of scope of this tutorial series.

From the official documentation, the Java plugin expects the following folder structure for your Java code and Java test classes:

img4

This is not mandatory and if you wish you could have different folders. Just look up SourceSets in the official documentation for the Java plugin to see how you can specify alternate Sourceset.

What is a SourceSet ? It identies the source i.e. grouping for your source files that need to be compiled and built together, some sort of a logical grouping or component. As per the official documentation, the Java plugin defines two standard source sets, called main and test. The main source set contains your production source code, which is compiled and assembled into a JAR file. The test source set contains your unit test source code, which is compiled and executed using JUnit or TestNG.

Given this information, we are going to put all our sources and test files as per the folder structure recommended by default by the Java plugin. This means:

  • Put all your Java files (full package,etc) into the src/main/java folder
  • Put all your Test files (JUnit stuff) into the src/main/test folder

I have gone ahead and put one Java source file inside of src/main/java folder. The folder structure as per the package is :

img5

Inside this quoteapp folder i.e. package com.mindstorm.quoteapp I have my one single Java file named Quote.java as shown below:

package com.mindstorm.quoteapp;

public class Quote {
 private Long id;
 private String who;
 private String what;
 
 public void setId(Long id) {
 this.id = id;
 }
 public void setWho(String who) {
 this.who = who;
 }
 public void setWhat(String what) {
 this.what = what;
 }
 public Long getId() {
 return id;
 }
 public String getWho() {
 return who;
 }
 public String getWhat() {
 return what;
 }
}

Now, let us go back to the root folder i.e. example2 where I have my build.gradle file. The file still has just a single statement i.e. apply plugin: “java”

Now fire the following command as given below (Note that I have removed the -q so that you can see all the console output)

gradle assemble

This will do all the hard work of compiling, building your Java files into a JAR file. Multiple tasks are fired, which shows that the assemble task in return depends on several tasks that it is executing first. The output of the command is shown below:

E:\gradle-projects\example2>gradle assemble
:compileJava
:processResources UP-TO-DATE
:classes
:jar
:assemble

You can experiment with introducing compilation errors and seeing what happens if you try to run the assemble command.

What did the command result in? If everything went well, the command resulted in a build folder in your project root directory. Inside of that, you will find a libs folder and inside which is the example2.jar . Your file name might be different depending on your folder name.

If you wish to clean (empty) the build directory and do a clean build again, you can invoke a gradle clean command first and then a gradle assemble command.

You can also fire the following task which does all the check and assemble for you:

gradle -q build

Let us improve things a bit. What if we wanted to give a version to the JAR file and a different name. To do that, simply do the following:

Update your build.gradle so that it looks like this:

apply plugin: 'java'
archivesBaseName = "quote"
version = '1.0-FINAL'

Now, fire the gradle assemble command and you should have a JAR file that is named as <name>-<version>.jar in the build/libs folder. In my case, it will be quote-1.0-FINAL.jar.

Note : You might be wondering from where do I produce stuff like archivesBaseName, etc. The only answer I can give is that the documentation is vast and you will have to navigate yourself through it. For e.g. go to the official page of the Java plugin, search for archivesBaseName and you will understand what is going on. My only advice is to keep the documentation handy, some property or the other will be there, just think logically and you will find the answer in the documentation.

The beginning of Dependencies

We have to tackle this sooner or later. And the moment has arrived. There is not much chance for any of your Java projects to not depend on 3rd party libraries. Consider the above Quote.java where we just wrote a simple Java Bean and there was nothing else to it. What if we modify it a bit by adding a toString() method implementation that makes use of the 3rd party library : Apache Commons JAR.

Let us first look at the code:

package com.mindstorm.quoteapp;
import org.apache.commons.lang3.builder.ToStringBuilder;

public class Quote {
 private Long id;
 private String who;
 private String what;
 
 public void setId(Long id) {
 this.id = id;
 }
 public void setWho(String who) {
 this.who = who;
 }
 public void setWhat(String what) {
 this.what = what;
 }
 public Long getId() {
 return id;
 }
 public String getWho() {
 return who;
 }
 public String getWhat() {
 return what;
 }

 public String toString() {
 return ToStringBuilder.reflectionToString(this);
 }
}

This is fairly straightforward Java stuff. Nothing much of interest here.

Obviously if you try to fire a gradle assemble command now, you will face issues. I suggest that you do, so that you can see the error reporting in all its glory. You should see the standard compilation error along with the BUILD FAILED message.

The solution is obviously to tweak the build.gradle file so that it is aware of 2 things:

  • What JAR files are needed to compile the code ?
  • Where to find those JAR files ?

Enter the world of Repositories in Gradle. A Repository in Gradle is a location where Gradle can locate the JAR files in our case. Gradle supports popular public repositories like Maven Central, Ivy and even your local repositories if you want. So if you are coming in from a Maven world, this will sound familiar.

To configure a Remote Repository, you will need to add the following element to your build.gradle file:

repositories {
  mavenCentral()
}

This will make Gradle look for any dependency (JAR files) that you specify in the Maven Central Repository.

Just keep this point in mind and we shall come to it later. Each file when published to Maven Central or any repository for that matter will have the following characteristics:

  • A Group Id (group)
  • An Artifact Id (name)
  • A Version (version)

So for example, if you want to locate the Apache Commons 3.3.2 JAR (which is the latest at this time of writing), it will be available in Maven Central as given below:

img1

The above screen is taken from Maven Central repository. If you are in doubt for any of your dependent JAR files, simply search in the Maven Central Repository.

Allright, more on this later. But first, let us understand Configurations in Gradle.

Configurations provided by Java plugin

All we have talked about so far, is that we found that we need to provide the build.gradle file with additional information on which dependencies (JAR files) are needed to compile the code and where it can find that. We solved the where part by mentioning the mavenCentral() repository from where it can pick up the files. But we are yet to specify which files to build.gradle, especially in our case the Apache Commons Lang library.

Now, it is perfectly possible that you may one set of JAR files for compiling and maybe some additional files for testing and so on. For e.g. if you are compiling JUnit Test Cases and want to run them too, you might need to provide the JUnit JAR file under those circumstances. But under other situations for compiling your main source files, you may not need the JUnit JAR files.

To address this, Gradle has the concept of Confgiurations. A Configuration is simply a named set of dependencies. You can use them to declare the external dependencies of your project.

But what are these configurations and what are their names. It turns out that typically plugins will add a list of configurations that we can use to specify our dependencies. For the Java plugin, it adds several standard configurations that we can use to specify our dependencies. Some of these are:

  • compile
  • runtime
  • testCompile
  • testRuntime

I will quote the official documentation here:

compile

The dependencies required to compile the production source of the project.

runtime

The dependencies required by the production classes at runtime. By default, also includes the compile time dependencies.

testCompile

The dependencies required to compile the test source of the project. By default, also includes the compiled production classes and the compile time dependencies.

testRuntime

The dependencies required to run the tests. By default, also includes the compile, runtime and test compile dependencies.

Now, since we have to compile our Quote class that has a dependency on the Apache Commons Lang 3.3.2 , we add the following entry now to our build.gradle

apply plugin: 'java'
version = '1.0-FINAL'

repositories {
  mavenCentral()
}

dependencies {
  compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.3.2'
}

Some notes on the dependencies block:

  • Each dependency is defined separately.
  • You specify first the configuration name i.e. compile in our case. Then you mention the library via its group, name and version as earlier mentioned.
  • Currently there is only one compile time dependency shown. But we can add more dependencies too. Just add them on each line.
  • There is also a short form of specifying the dependency library. Instead of using group:value,name:value,version:value, you can just give the value in the form ‘group-value:name-value:version-value’. As an example, we could have rewritten the above dependencies as given below:
dependencies {
  compile 'org.apache.commons:commons-lang3:3.3.2'
}

Save this build.gradle and try running the gradle assemble command. This time, you will find that it will work by first downloading the JAR file from the Maven Central Repository, adding it to the local cache and then continuing with the compilation of the project.

 

Note (Very Important):
Make sure you are patient and you have a good working Internet connection, since Gradle looks in its local cache if you have already downloaded this library and version. If not, it will need to go to the Internet , access the Maven Central Repository, download it first and then continue with the build process. This process of doing a local check first and then downloading the artifacts is a major source of problem for most newcomers (I suffered from it!). The point is that if your dependencies are large for e.g. as we shall see in the later episodes (App Engine SDK), then it is a good 200 MB of download and you might just feel that the whole process has stopped working and has gone into a loop, whereas on the other hand, it is sincerely doing its job of downloading the JARs and any other transitive dependencies for you. 

Hope things are becoming a bit clear and you have been able to successfully build your Java project via Gradle and which has dependencies on external libraries.

Some more dependencies

Now that we have seen how to add a compile dependency, it makes sense to look at what we should do to add a test dependency. Remember that we can add our own JUnit Test cases. These test cases (Java classes) would be present in the src/test/java folder.

Recollect that the Java plugin added the following configurations to the Gradle project:

  • compile
  • runtime
  • testCompile
  • testRuntime

Now, we can easily see that we will need to add the JUnit JAR file dependency to the testCompile configuration. To do that, simply add your JUnit Test classes to the respective source directories and update your build.gradle so that it looks like this:

apply plugin: 'java'
version = '1.0-FINAL'

repositories {
  mavenCentral()
}

dependencies {
  compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.3.2'
  testCompile group: 'junit', name: 'junit', version: '4.+'
}

The format should look familiar. Just that you will notice one difference in the version. There is a sign instead of a specific version number. This is a hint to Gradle that it should go and fetch the latest version that is available.

Summing up

Hope you are getting the hang of Gradle now. We are barely scratching the surface in terms of its capabilities but you get the picture. I strongly recommend to go through the official documentation i.e. Gradle User Guide and more specifically the Java Quickstart  and Gradle Java plugin. I found repeated readings of this documentation very useful in my learning journey and I am still learning :-) I strongly recommend trying out this on your machine, since that will help you understand it more and provide you with ready templates that you can create for a variety of Java projects.

See you in the next episode, where we shall cover Part 3 : Building Multiple Java Projects with Dependencies, where we have one or more Java projects that are dependent on each other. For e.g. you write a library and the other Java project requires that. And moving forward, we will cover the Gradle War (Web Application Archive) plugin that helps with Java Web projects. Till then, Happy Gradling!

Posted in Tools | 7 Comments

Gradle Tutorial : Part 1 : Installation + Setup

To read an overview of this series, refer to the original blog post.

In this part of the tutorial, we shall focus on setting up Gradle on our system. While tools like Android Studio do ship with an internal Gradle distribution, our intention here is to understand the tools, its installation, the setup and firing up some basic Gradle commands.

Before we begin with that, if you are still wondering why Gradle is a good choice for build tools, I suggest that you read the following article. Though not essential to read it, it opens up your views as to why companies/developers are flocking to Gradle.

The next few sections will take you through setting up of Gradle on your machine. Gradle requires Java to be present on your machine. So, I shall assume that you are a Java developer and have setup the Java SDK on your machine. 

Download Gradle

At the time of writing, Gradle is in version 2.0 and is available for download here.

Just go ahead and download the ZIP file to your machine. You should have a file named gradle-2.0-all.zip. Expand it to a folder of your choice.

For e.g. on my machine, I have expanded the same in e:\gradle-2.0, such that I have the following sub-folders as shown below:

img3

 

You might ask why you need a separate installation of Gradle ? This would especially be on your mind if you have already downloaded Android Studio and worked with it. As you know, Android Studio ships with Gradle inside of it and no external installation of Gradle is required.

When we come to the later parts of this tutorial , where we will talk about Android Studio, we will use the Gradle distribution that comes along with it. The focus for all of us in this part and the next few lessons, will be on setting up our own setup of Gradle, running stuff from the command line and being as closed to the bare metal as possible, so that we understand what is going on. Later on, when Android Studio does these things, it will be much easier to understand what is going on ? And you will stop believing that Android Studio is doing some voodoo under the hood.

So for now, do download a separate Gradle installation as instructed and set it up.

 

Environment Settings

The \bin folder of your gradle distribution contains the gradle script file (both Unix and Windows) that you will use to run the gradle command along with various parameters.

Ideally, do the following:

  1. Create an environment variable GRADLE_HOME and point it to the Gradle Installation folder. On my machine, the Gradle installation folder is e:\gradle-2.0 and hence I have created a GRADLE_HOME Environment variable that has the value e:\gradle-2.0
  2. Add %GRADLE_HOME%\bin to the PATH environment variable. This will allow you to launch gradle command from any directory.

Verify Gradle Setup

To verify our setup, go to the command prompt / terminal and type the following:

gradle -v

This should display information about Gradle / versions and other information as shown below:

------------------------------------------------------------
Gradle 2.0
------------------------------------------------------------
Build time: 2014-07-01 07:45:34 UTC
Build number: none
Revision: b6ead6fa452dfdadec484059191eb641d817226c
Groovy: 2.3.3
Ant: Apache Ant(TM) version 1.9.3 compiled on December 23 2013
JVM: 1.7.0_40 (Oracle Corporation 24.0-b56)
OS: Windows 7 6.1 amd64

If you do not see information similar to the one above, check your installation of Gradle and ensure that you have set your PATH variable correctly that contains the direct %GRADLE_HOME%\bin as explained earlier.

A word about Groovy

Any discussion of Gradle is incomplete without Groovy. Groovy as you know is one of the most popular and powerful languages available on the JVM.

Some of the key reasons in favor of Gradle are:

  • It is less verbose
  • It is very flexible
  • It lets you configure and dictate things the way you want

Groovy plays a big role in making the above points happen. Unlike XML that is typically used in Ant and Maven, Groovy is a high level language that not only cuts down on the verbosity with its intuitive and productive syntax but it also gives you full programmatic power to tweak / specify things. All programming language advances like closures etc are available to you. And the build file that you typically ask Gradle to run is actually code that is running for you.

One question that could typically arise is “Do I need to know Groovy?” ? I am tempted to answer you do not. Unless you really want to stray away from convention and do things your own way, then you need to know Groovy because that is where the flexibility of Gradle comes in. But for all purposes, you can use various build.gradle templates that we shall look at and while it contains the Groovy DSL, you need not know much about it or for all you care, not know anything about it. 

So, while you do not have to know Groovy well to understand Gravel, it helps to know that the full power of Groovy is available to you, should you desire that.

Groovy is shipped with default with your Gradle distribution, so you do not have to separately download the same. 

Basic Gradle commands

We have not yet written any source code or build files (Gradle) and we will get to it in while. But try out the following on the command line:

gradle -q help

This command prints out basic help information for Gradle. The -q parameter is just for quiet mode in the console output. It is quite useful as you move along to see less verbose output.

gradle -q tasks

This shows a list of tasks that are already available to you. Give it a shot.

gradle properties

This will list of several properties that are preconfigured for you. You can definitely modify most of these properties in your build files. But it gives you a sense to the heavy duty work that Gradle is setting up for you prior to executing your tasks.

We are not yet going to get to compiling our Java code projects, etc. That is for the next part in this series. We are going to understand how Groovy brings the whole power of programming to Gradle.

To get started, let us first talk about the build.gradle file. This is the standard name used for our build file. All instructions that you need to give to Gradle are contained over here. Over the entire series, we will essentially work with build.gradle file to create / use all sorts of plugins/tasks that will help us compile, build , test and run our Java applications.

For now, let us try out the following (I leave it to you to use a directory of your choice to store the files/code as we move along):

In a folder of your choice, for e.g. example1, create a file named build.gradle.

Put the following as contents of the build.gradle file.

task compileTask << { 
    System.out.println "compiling..." 
}

Now, go to the command line and the folder in which you created the above build.gradle and give the following command

gradle -q tasks

This will list out various tasks that you can perform and you will notice in the output that apart from the standard tasks that you noticed, you also have the task that we created i.e. compileTask 

Other tasks
-----------
compileTask

This brings us to the first concept that our gradle build file is a series of tasks that we specify and which the gradle build system can execute for us. Currently the task that we have specified is named compileTask and what you see is the Groovy code where we just define the task code, where all we are doing is just doing a System.out.println. Remember that Groovy is a high level JVM language.

Now, what if we want to run the compileTask command ?

Before, we get to that, there is one more point to understand. When we fire the gradle command, it looks for a file named build.gradle in the current directory. If it finds one, it uses that. In the above case, since it found one, it determined what tasks are present in the file and added that to the list of tasks that it can perform.

So, what happens if we just type gradle with no other parameters nor do we specify any task to be execute. Let’s try that:

gradle

This will give the following output:

:help
Welcome to Gradle 2.0.
To run a build, run gradle <task> ...
To see a list of available tasks, run gradle tasks
To see a list of command-line options, run gradle --help
BUILD SUCCESSFUL
Total time: 2.39 secs

It is clearly telling you that you need to specify the task name when you run it i.e. gradle <task>. Let us do that by giving the following command:

gradle -q compileTask

This will output the text

compiling...

Let us enhance the build.gradle file with another task, so that it looks now like the following:

task compileTask << {
 System.out.println "compiling..." 
}

task buildTask << {
 System.out.println "building..."
}

Now, if you give the following command:

gradle -q tasks

You will find that both the tasks are listed in the otherTasks as shown below:

Other tasks
-----------
buildTask
compileTask

You can now run any of the tasks via gradle compileTask or gradle buildTask and so on.

What if we want to create a default task to be executed, so that if we do not specify the task name, it should execute that.

To do that, modify the build.gradle file as shown below:

defaultTasks 'buildTask'

task compileTask << {
  System.out.println "compiling..." 
}

task buildTask << {
  System.out.println "building..."
}

Now, if we simply say gradle -q , it will print the building… string output.

The last part to note here is dependency among tasks. What if we want to make the buildTask dependent on the compileTask, so that if the buildTask is run, it should always run the compileTask first.

To do that, modify the build.gradle file as shown below:

defaultTasks 'buildTask'

task compileTask << {
  System.out.println "compiling..." 
}

task buildTask (dependsOn:compileTask) << {
  System.out.println "building..."
}

Now, when you simply invoke gradle -q , it will show the following output:

compiling...
building...

What we have covered in this episode is the very basics of Gradle. Think of your build file as a series of tasks that need to be done. If you are a Java developer and have some experience of the build process (Ant, Maven) , you can easily relate to the fact that to build any stuff, we will need to do things like: compile, build, run tests, package , etc. These are nothing but tasks in Gradle.

We do not necessary have to write all these tasks by hand, though you could if you want to. By using convention that Gradle follows and plugins that work automagically off those conventions, we can perform the same series of steps that are required to build our projects.

There are plugins available in Gradle for e.g. Java plugin, WAR plugin, AppEngine plugin, Android plugin and so on, that expose predefined tasks that you can invoke. We shall see more of that, moving forward in this series.

Next Part

In the next part of the tutorial, we shall look at using Gradle to compile / build our Java projects.

Posted in Tools | 8 Comments