Filed under: Uncategorized
At work we have a small, but perfectly formed set of Java applications that help run our business, and we have a well practised methodology for developing, testing and deploying all our modules.
The perfectly formed claim above is a lie. The various modules are a rats nest of inter-dependencies and there’s an incestuous level of circular dependency between some of these modules. And while our methodology for testing and deployment might be well practiced, it’s certainly not straight forward and could easily be streamlined and improved with better tools.
On our old build box, which released it’s magic smoke some months ago, a build cycle would take over half an hour because it had to start with the application with the most dependants and work it’s way down the stack from there. That’s hardly good for instant feedback when your check in breaks the build.
In order to be able to implement Continuous Integration for our Java stack, there were several problems we needed to solve:
- Monolithic build
- Dependency Nightmare
- Visibility of build statistics.
There are others, but these were the main ones for me. The old build platform was based on ant and Cruise Control, using ant wasn’t bad, but for new developers there was quite a bit of work involved in getting a module built. This wasn’t all down to ant, but it didn’t make it easy to manage a projects dependencies.
Some of the 3rd party dependencies we have are ancient, and it’s hard to find the right jar file for most of them. There are reasons for this, but I’m not going to go into them here.
This is where Maven comes in, it’s ability to manage any dependencies a module might have was the biggest draw, tell it which library you want, and what version and let it worry about where it comes from. So I picked the module that had no dependencies on any of our other applications and started to convert that.
The biggest lesson I learned from that is do not try and munge the Maven pom to fit your file structure, change your file structure to match what Maven expects, once you’ve done a couple, it really doesn’t take that long. As well as making the conversion smoother, in the long run you get the benefit of every project looking the same, so new developers know where the source is, they know where the tests are and they know where the extra resources like jboss config files are. It’s a good example of convention over configuration.
The next problem you’ll come across is working out which of the many Maven repositories you’ll need to use, many of the libraries are duplicated across more than one repo, and in some instances the same class is available in multiple artifacts. I didn’t find a quick solution to this, it was instinct & trial and error. Some of them are obvious though.
Once we had the first module converted over, we started to look at the next one. We quickly noticed that many of our apps share dependencies, so I created a parent pom file that they can all share to get the same dependencies. This also made it easy to plug in the code quality checks later as well.
So I’m nearly at the end of this post, and I haven’t mentioned Hudson yet. Why did I choose Hudson over the incumbent Cruise Control? Well the build scripts that built the apps on the build box were different to the ones that developers used to build the same app on their dev box, and I wanted to unify that, also when I looked at the 2, Hudson was up and building something from scratch in about 30 minutes, and cruise control wasn’t even anywhere close. Initially I had some problems with stability, the Hudson process would become unresponsive over night, moving from the default Winstone app server to Tomcat seems to have sorted this out though. Watch out for file permissions in the Hudson directory though if you do the same, it made a plugin I use vanish, which made all my builds that depend on it disappear for a time too!
Using maven also solves the monolithic build problem because each module just becomes a dependency the same way log4j or junit are. It doesn’t help the circular dependencies either, you have to fix them yourself. Using a repository manager like Nexus is a really good idea too.
Creating a project in Hudson is easy, point it at your code repository and away you go. Simplicity is crucial if you want to get everyone in the department on board and it doesn’t get much simpler than that.
I’d like to say a massive thanks to the members of the Sheffield Java User Group who helped me get over some of the initial problems I had using Maven.
Next I’m going to cover the various Hudson & Maven plugins that we use.