Controlling the Maven release cascade

In my previous post, I showed one of the pitfalls of maven's transitive dependency mechanism.

Luckily, there is a good workaround to this that will allow your team to stay focussed on development without getting bogged down too much into the release-cascade trap.

The thing to do is to create another level of indirection between your framework and the clients using it, this can be accomplished by providing a POM dependency.

For our framework it would look something like this:


<project>
<modelVersion>4.0.0</modelVersion>
<groupId>my.framework</groupId>
<artifactId>client-components</artifactId>
<version>2.0.1</version>
<packaging>pom</packaging>
<dependencies>
<dependency>
<groupId>my.framework</groupId>
<artifactId>main</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>my.framework</groupId>
<artifactId>A</artifactId>
<version>0.6</version>
</dependency>
<dependency>
<groupId>my.framework</groupId>
<artifactId>B</artifactId>
<version>0.8</version>
</dependency>
<dependency>
<groupId>my.framework</groupId>
<artifactId>C</artifactId>
<version>0.2</version>
</dependency>
<dependency>
<groupId>my.framework</groupId>
<artifactId>X</artifactId>
<version>0.4</version>
</dependency>
<dependency>
<groupId>my.framework</groupId>
<artifactId>Y</artifactId>
<version>0.5</version>
</dependency>
</dependencies>
</project>
Notice how this POM dependency is nothing more than a flattened dependency tree. We've pulled all our dependencies into one POM and we control their versions from there. This works pretty well, and all our clients have to do is to declare it like this:
<groupId>my.framework</groupId>
<artifactId>client-components</artifactId>
<version>2.0.1</version>
<type/>pom<type>
Using this, we can avoid the release cascade for module Y, our work is effectively reduced to:
  1. release module Y
  2. change version of Y in client-components POM
  3. release client-components POM
That's IT. Swift and fast like it should be.

The POM dependency can even be used from assemblies and the like. It behaves like a normal dependency in all aspects. Additionaly, it is a great way of quickly eliminating rogue dependencies: just exclude them in there and worry about tracking it down later.

That's it for now, I promise my next post will not take 4 months this time :-)

No comments: