I am about to embark on a new Java project so I thought I would take a look at the current state of build tools for Java projects. First I thought I would draw up some assessment criteria to use as a loose guide. This is what I came up with:

Fast

I want a build tool that spends as much time as possible building my application and not setting itself up to perform the task.

Manages Dependencies

Gone are the days when I can or want to manage my dependencies manually. Current Java applications want to make use of frameworks and those frameworks want to build upon other frameworks. To take advantage of these I need something that can take care of finding and delivering project dependencies.

Quick to set up

I don’t want to spend a long time learning a new tool. I am willing to invest in learning when I have an unusual problem to solve in the build system but out of the box I want to be up and running quickly.

Encourages good practices

I work with others in team to deliver projects. A tool that encourages and rewards good project source and binary management is important. A clean well supported syntax for any build scripts is important. Unnecessary syntax is annoying and distracting when it comes to build system creation and management.

Good Tool Support

I use an IDE for Java development (IntelliJ Idea) and others might use Eclipse. I want a tool that either understands my IDE or is understood by my IDE. Given that I am likely to manage my dependencies in the build file (I prefer command line builds) then a build system that can update my IDE is better than an IDE that knows how to interpret my build file.

Flexible

There are always fringe cases where I might need to introduce some other types of code e.g. ANTLR grammar files that compile into Java source. I need to be able to introduce pre-compilation and post compilation steps but I am happy that I may need to do a little work here.

Support or planned support for other JVM based languages would be a bonus.

Extensible

No two projects are the same and people that write build tools cannot predict all of their users requirements so I want a build too that I can extend for my projects.

Good Community Support

For open source tooling (preferred) an active community is essential for help - particularly if the documentation is not particularly extensive.

Support Continuous Integration

All my projects run with continuous integration (CI). I run my own CI server for my personal projects. CI systems ‘know’ how to interface with some build apps to monitor progress and capture output.

Test and compilation reports need to be captured for reporting and metrics.

Candidates

The candidate list came from tools that I have used on projects in the past and some basic web searching - I am sure it is not extensive!

I have been spiking a number of web projects using the dropwizard framework. It has some really nice features and made a good candidate for the evaluation (at least from a Hello World type app perspective).

Ant & Ivy

I have been using Ant for a very long time. Surprisingly Ivy has not come up on projects in the past but I have heard some very good things about its performance in finding and acquiring dependencies.

In the past I have added the Ant distribution to my source repository to minimize the setup work for developers. This has worked very well in the past and I thought I would use this technique this time around. It could be me but trying to set up Ivy integration with Ant in a single directory took longer than I was willing to wait. There was little documentation on how to use Ant and Ivy with Dropwizard and from past experience even a simple application with few dependencies results in 100s of lines of XML. After an initial attempt to get things working I decided to see if there were better options later with the option to coming back to an old friend if I needed to.

Maven

Maven ‘invented’ the de-facto standard of dependency management for Java projects that is now making itself known in other spheres. It is also the standard in many corporate environments. I will admit that I am a ‘light’ maven user and not been forced or motivated to drill below the other interface.

Maven has a particular view of the builds and their stages that is relevant to a lot of projects but I also find that on most of these projects there are also some exceptions that ‘break the model’.

Maven is similar to Ant in that the build files are XML based. I apologize but I just cant get over the angle bracket tax. I will use it if it is the project norm but the signal to noise ratio is just not strong enough.

Raven & Rake

Some years ago I worked with some developers who were passionate about building Java projects using Ruby and Rake. Since then there have been a number of projects in this space (Raven being one of them). Looking at the source repository Raven has not been updated since 2007. Rake does not understand Java dependency management norms and would require a lot of libraries or custom code to get working effectively. While poking around in this space I came across http://buildr.apache.org[Apache Buildr].

Gradle

I have heard some good things about using Groovy and in particular Gradle for Java builds. I installed the distribution and wrote a 3 line ‘Hello World’ build script that took 1.3 seconds to load and run

  • just far too long. So I gave up pretty quickly.

Buildr

Apache Buidlr is another build tools built in Ruby and based on Rake. But and this is a big but the libraries and build DSL work with the common build conventions for build projects. After a bit of messing around with transitive dependencies I ended up with a very simple 19 line build file for my Dropwizard project.

Downloaded all the dropwizard dependencies in about 20 seconds (there are a lot of dependencies).

Compiling a few Java classes is not quite as fast as I would like but below 2 seconds.

Simple build file

repositories.remote << 'http://repo1.maven.org/maven2'

desc 'My project build'
define 'my-java-project' do
  project.version = 1.0
  project.group = 'My group name'
  manifest['Copyright'] = 'Graham Brooks 2013'
  compile.options.target = '1.8'

  desc 'The API component'
  define 'my-api' do
    compile.with transitive('com.yammer.dropwizard:dropwizard-core:jar:0.6.2')
    package :jar
    run.using :main => %w(com.HelloWorldService server hello-world.yml)
  end

Buildr infers a lot from the project structure. This can be overridden (flexible) but if you use a Maven file structure you don’t need to write much of a build script.

The run line took a while to work out how to add command line parameters.

run.using :main => %w(com.HelloWorldService server hello-world.yml)

Combining the parameters with the classname to run makes sense after you see it but usually the two are separated out into different parameters.

Buildr has been under development since 2007 so it has some pedigree. It also supports ant tasks if you use the JRuby variant.

So if you are looking around for an alternative or starting a new project I think Buildr is definitely worth evaluating.