Wednesday, February 8, 2012

Using Gradle with Ubuntu 11.10 (Oneiric Ocelot)

I am a big fan of dependency management. After learning about Maven and working with it for several projects I have really bought into the idea of using build repositories and having projects be dependent on build artifacts that reside in repositories rather than storing all the dependency jars in the SCM. Even worse is when a team has a bunch of modules but only a single build that constantly builds them all. This seems like such a waste of time and resources to be constantly building something that may not have changed recently. Anyway, I've heard a log of good things about Gradle, so today I wanted to check it out.

Since I'm running with Ubuntu, I first searched the Synaptic Package Manager to see if Gradle was available there.  It was so I quickly installed it.  There were a lot of dependencies, so it took a few minutes to download and install everything.
From there I went to the Gradle site and started the Hello World tutorial and quickly had it running.  Since I am familiar with Java projects, I wanted to start comparing the Java capabilities of Gradle to Maven.  I was happy to see that Gradle seems to be following the same directory structure that Maven uses, so that makes life easier.  I created a very simple Java application that would just have a single HelloWorld class with a JUnit test case to test it.  I started by following the Gradle Java tutorial

Here is the basic project:
TestGradleJava
    build.gradle
    src/main/java
        HelloWorld.java
    src/test/java
        TestHelloWorld.java

build.gradle
apply plugin: 'eclipse'
apply plugin: 'java'

repositories {
    mavenCentral()
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.+'
}

HelloWorld.java
public class HelloWorld {

    public String getHello() {
        return "Hello World";
    }   
}

TestHelloWorld.java
import static org.junit.Assert.assertEquals;

import org.junit.Test;

public class TestHelloWorld {

    @Test
    public void test() {
        assertEquals("Hello World", new HelloWorld().getHello());
    }

}

On a side note, I was able to get Gradle to create the Eclipse project files by adding apply plugin: 'eclipse' to the build.gradle file.  Then just running 'gradle eclipse' from the command line created the .project and .classpath files needed for Eclipse.

Following the instructions from the tutorial it states to run 'gradle build'.  Doing so I got the following output:

brian@torreys:~/workspace/TestGradleJava$ gradle build
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:jar
:assemble
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':test'.
Cause: Could not generate test report to '/home/brian/workspace/TestGradleJava/build/reports/tests'.
Cause: java.lang.NullPointerException (no error message)

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

Total time: 15.675 secs

Doing some research online I found some information that stated there is an issue with the Gradle installation done by the Ubuntu package, (http://www.mail-archive.com/s4-dev@incubator.apache.org/msg00220.html). The resolution is to manually install it. Here are the steps I used to install Gradle manually, after using Synaptic Package Manager to uninstall first of course.
  1. Download the latest version of Gradle from here: http://www.gradle.org/downloads.  I grabbed gradle-1.0-milestone-7-bin.zip
  2. Move the download to /opt
  3. Unzip the archive
    >sudo unzip gradle-1.0-milestone-7-bin.zip
  4. Create a symbolic link to create a gradle dir that points to the dir created by unzipping the archive.  I like to plan for easy upgrades of tools, so I create a symbolic link to the actual gradle directory.
    >sudo ln -s /opt/gradle-1.0-milestone-7 gradle
  5. Create another symbolic link to put the gradle executable into /usr/sbin.  I find this easier than modifying the PATH adding /opt/gradle/bin, but you can do that too.
    >sudo ln -s /opt/gradle/bin/gradle /usr/sbin/gradle
  6. Try it to make sure it works
    >gradle -v
Here are the instructions that Gradle publishes: http://www.gradle.org/docs/current/userguide/installation.html

Now we head back to our TestGradleJava directory and we'll try running 'gradle build' again:
brian@torreys:~/workspace/TestGradleJava$ gradle build
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:jar
:assemble
:compileTestJava
Download http://repo1.maven.org/maven2/junit/junit/4.10/junit-4.10.pom
Download http://repo1.maven.org/maven2/org/hamcrest/hamcrest-core/1.1/hamcrest-core-1.1.pom
Download http://repo1.maven.org/maven2/org/hamcrest/hamcrest-parent/1.1/hamcrest-parent-1.1.pom
:processTestResources UP-TO-DATE
:testClasses
:test
:check
:build

BUILD SUCCESSFUL

Total time: 24.657 secs

This is great, now the JUnit targets are running and passing!

My overall conclusion at this point is Gradle looks really nice.  A very simple build file can easily build a simple Java project with dependency management.  I'll have to see how it does with more complex build files as I progress the simple application into something more complicated.