Java Build Systems, Part 2: Maven

Continuing the Java build systems discussion, today I want to focus on Maven, what it does well and what it does that frustrates.  We’ll get a little taste of the minimum expectations for a new build system as well.  Note:  this page may be subject to edits, as I come across more pros & cons of Maven.

What Maven does right

Maven teaches us several important things about what we need from a build system.

  • Convention over configuration. Maven strongly encourages developers to put source files, resources, tests, and project metadata in standard locations.  Maven make life very difficult for anyone deviating from the norms.  In general, this is good, helps teamwork and collaboration, and helps for picking up a project cold.
  • Defaults just work. Similar to the last entry, if you follow maven standards, then it works fine and has a reasonable assumption of defaults.
  • Dependency Management. Probably the single best feature of Maven and modern build tools.  This allows a developer to specify requirements for a project without having to directly specify the physical location of those library dependencies.  This frees the build system to resolve from the network, automatically check for updates, and manage multiple versions of libraries.
  • Plugins.  Easy extensibility is key to Maven.  In fact, most of its internals actually exist as plugins, from compilation to Ant support to deployment.  The ability to add new, custom behavior and have it tie into your builds is fantastic.

What Maven does wrong

There are some pretty big gotchas in Maven.  Nothing insurmountable, but frustrating nonetheless.  And before you say “It’s open source, fix it yourself!” know that it is not that simple.  There may be resistance to a certain change, for example, from “the establishment” or some issues and Maven’s solutions are fundamentally tricky.

  • Outside the ordinary is very hard. Doing anything beyond the standard use cases requires an arcane knowledge of plugins.  All of a sudden, Maven’s configuration-based approach falls down, and things become easier to do in code — ie, you have to write a plugin.  But don’t think you can use the nifty ant-scripted mojos for that plugin– for example, for compilation, there isn’t a standard way to get the classpath into the ant script.
  • Dependency Management. Yep, the same benefit is a detriment.  Or, at the very least, Maven’s handling of it.  Several things fall in here.  The ones I can recall are:
    • Transitive dependencies prove very tricky and make for lots of classloading troubles.  Adding a single dependency to a POM can really change the entire dependency graph of  a project.
    • There is no way to simply say “I want the latest of library XX”.  On the one hand, Maven makes sense here; you should usually know exactly which version of software you are building against.  But there are cases, for example, due to a lack of maturity, where having to know that version number is just an annoyance.  Ivy apparently has an intermediate option here, where you can specify latest, but when a build happens, it records what that version was.
  • Long-standing bugs. Maven suffers a bit from what other mature open-source products hit upon.  Whether it is loss of momentum for something that works well enough or that too many are depending on the quirks, there are lots of oddities and issues left in core plugins.  A perfect example is maven-antrun-plugin, which only sets its classpath once per maven run, regardless of how many POMs reference it.
  • Documentation bugs. Some of the Maven docs are a bit light on details.  Part of it may be Maven’s built-in site creation, which leads to some sites that have lots of links but are pretty information-sparse.  Other times, many common scenarios are presented, but some of the edge cases are glossed over.  Related:  looking for a list of available Maven properties for use in your POM is tricky because of Maven’s dynamic nature.  But a simple guide describing common ones and how to construct others would be great.

Summary

Generally, what Maven teaches us is that you need to fully embrace Maven to get the full benefit of Maven.  Once you get the hang of the Maven way, things go much more smoothly.  That is not unexpected, but it is uncomfortable.  But there are times where you have to fight — deploying to multiple load-balanced servers, for example, and you end up with some nasty scripts and configuration on top of a previously elegant solution.

The important thing is, though, that Maven does work.  It’s not too much of a bear to get started with, has great defaults, and it has some compelling solutions to annoying problems.

So, can Maven be fixed?  Should it be fixed, or should a build system start from scratch?  More on that next time.

This entry was posted in java and tagged , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published.