Saturday, January 15, 2011

Maven build helper POMs

A typical misconception in Maven is that if you want to build a project in a special way, or parameterize it somehow, profiles are the thing for you. My opinion is that..

Profiles are POM smell.
While I know they have their uses, I have abused profiles heavily in the past, and seen others do this too. What might start off as a simple little trick to get some desired build eventually leads to:
  • One profile for each testing category (unit, database, web-tests, etc)
  • One profile for each environment/stage configuration (testing, live, etc)
  • One profile for each artifact assembly (exclude module X when deploying in certain environments)
The POM ends up awfully complicated, you get confusion around what kind of artifact is deployed where, and people start hating Maven because they forget -P parameters when they build, and end up rebuilding the whole project to change some single configuration.

The point of a POM is that the output of the build, the artifact, should always be the same thing.

If you want to build *a different thing*, you probably should build another project. Andrew Spencer recently wrote a nice article about best practices in Maven profiles. If you want more advice you should have a look.

An example from the other day:  I wanted to build a sub-set of the modules in a rather large multi-module project. In order to speed up the build, I wanted to exclude the modules with static contents (texts and resources):

Instead of making a quickbuild-profile, I made an adjacent fastbuild-pom.xml that extends the original, but excludes the static modules:

This build I can invoke in the CI-server:

mvn clean install -f fastbuild-pom.xml

So, not too much duplication of the original pom, and very unobtrusive.

Remember that in 95% of the cases you want to create profiles, there is probably a better tool for what you are trying to do. I think the best cases for profiles are read in their activation docs: Making it possible to build the project on different JDK's, or different OS. Then again, the whole point of Java is to be platform-independent, so this seldom an issue.