Continuous Delivery with Maven

conveyor-beltMaven is not perfect, but it is very useful for its version dependency support when compiling Java programs. You specify the version of a jar file you want, and it will download the version from a repository and all transient dependencies as well. This encourages breaking a project up into smaller jar files, which can help separate out code with dependencies on other jar files.

For example, if you have a data access interface and two implementations based on MongoDB or an Oracle relational database, then if you throw it all into the one jar file that jar file will depend on MongoDB client libraries AND Oracle client libraries. It is better in this case to have 3 jar files: one that holds the interface, one for MongoDB (which depends on the interface jar), and one for Oracle (which also depends on the interface jar). Other applications can now choose which jar they want to depend on – the interface (not knowing which implementation will be used), or a specific implementation. Maven tracks the dependencies for you, making it less painful to split projects into multiple little jar files.

The Maven release process however is not ideal for continuous delivery. The idea developers use a SNAPSHOT suffix on library version numbers until they are ready to release. Maven knows “SNAPSHOT” is special, and will find the latest snapshot for that version available in the repository it accesses. The release plug in goes into the pom.xml files and modifies them to remove the SNAPSHOT suffix, commit the code, increment version numbers, branch, re-add SNAPSHOT back in, and … and I am sure I did not get that quite right. See posts like this one if you want to know how it really works: http://www.lucasward.net/2010/11/maven-and-continuous-delivery.html

The idea of Continuous Delivery (as distinct from Continuous Deployment) is each build should be a potentially releasable version. There are a couple of good posts I came across on this. They use slightly different strategies, but in both cases you use a Jenkins build number inserted into the version number, so every Jenkins run builds a new version of the jar files (e.g. 1.2.3-5324 where 5324 is the Jenkins build number).

One good set of slides I came across was here: Continuous delivery-with-maven. The approach uses SNAPSHOT versions still for developers, but the CI farm always substitutes in real version numbers (the build number is inserted into the version of the jar file). Part of the trick seems to be to get Maven not to rerun everything it would by default all the time.

Another article I found was here: http://jamesbetteley.wordpress.com/2012/02/21/continuous-delivery-using-maven/. Both seemed on the surface potentially sensible approaches. This approach got rid of SNAPSHOT altogether. Again, lots of magic to get certain phases to be skipped so only the required phases are run when you want them to in the overall build pipeline.

Issues I have not seen described however. How long do you keep all the binaries around for? Multiple complete sets of binaries are being created each day. How do you know what really is in production? You need to put some housekeeping in place, or buy a few terabyte disk drives.

If you have any experiences with Continuous Delivery with Maven I would love to hear about them!

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.