A detailed explanation of how you can ensure that your Maven-based project only relies on RELEASE dependencies... and why you should care.

In my previous post, I explained how you can configure the maven-dependency-plugin to ensure that your dependency declarations are minimally complete. Following on from where I left off, I want to show how you can configure another very useful plugin to require that all (or certain) dependencies are released.

There are many reasons why you might want to enforce this. A few that come to mind are:

  1. You need to perform regular releases and want to make sure you're always in a position to release your project
  2. You want to ensure that your project is built on stable components that don't change while you're developing
  3. You perhaps have some security or business restriction preventing you from using unreleased code

Potentially Releasable

In my particular case, the primary concern is ensuring that any build is potentially releasable (note the similarity to Scrum's goal of having every sprint delivering "potentially shippable" code). To do this, we need to ensure that we do not include any snapshot dependencies.

One option is to do a manual check of all dependencies prior to each release. Apart from the unnecessary additional work this introduces, it also exposes the problem far too late as you might find some snapshot dependencies that block the release. You can't always roll back, but you're relying on code that hasn't yet been released. The ideal situation is to prevent these dependencies from being added in the first place.

Rule Enforcement

This is where the maven-enforcer-plugin comes in handy. Sounds like a superhero name for a Maven plugin!

This plugin comes with a set of standard rules, but you can also create your own if you have a particular use case that hasn't already been solved. In this case, we're using the standard rule called requireReleaseDeps which checks if any dependencies are snapshots. Here's a basic example of how to configure it:

The example above uses fairly minimal configuration, but does exactly what I need it to do. You'll notice that I've added an exclusion for ${project.groupId}:* to avoid all child projects failing, as I'm using this in a multi-module project. You might also use this to help migrate off snapshots versions over a period of time. Enabling the plugin with the existing snapshots excluded at least prevents new snapshots from being introduced while you resolve the known issues. Far better than chasing a moving target!

This can be a very effective mechanism for enforcing some rules on your project - whether it be the snapshot dependency restriction or some other rule. In the context of a continuous integration pipeline, this can be even more effective. Any commit that violates the rule will automatically fail on the CI box, exposing the problem as early as possible. Particularly when trying to retain a permanently releasable build, this can be very useful!

Update: On a similar topic, here's a very useful article on best practices for releasing with 3rd party snapshot dependencies (if you must).


03 February 2012


submit to reddit