Technical How-To

Maven: Don't just blindly "mvn clean install"

Suppose you have a multi-module Maven project, with a ton of modules, two of them being fancynewtool-db and fancynewtool-rest. fancynewtool-rest has fancynewtool-db as a dependency. What happens if you cd into the rest-module and do a mvn clean compile/test for the first time? Maven will tell you that it cannot resolve the db-module dependency. And now your instinct might be to do a blind mvn clean install in the parent project, because that is just the way Maven works ™.

A full mvn clean install works, but is simply not the fastest and most efficient way. Additionally, maven now "installs" those snapshot dependencies to your local Maven repository, which means that you will be using outdated dependencies in your future builds, unless of course you do the full mvn clean install again. Sure, with more intrusive class changes you might realise pretty soon that you are using an outdated version, but think about smaller change or database scripts/resources etc.

Gradle for example handles this gracefully by automatically building dependent modules before the actual module. With a bit of work we can get Maven to display very similar behaviour, albeit a bit more verbose.

Whenever you do a install or even a deploy from the parent directory, you tell Maven to resolve project dependencies (i.e. modules) from the current project directory first instead of going directly to the Maven repository. This is called using the reactor. But actually we do not always have to build the whole project, but we can tell the reactor to only consider one or more sub-modules! Just do it like this:

cd [myproject-root]
mvn -pl [submodule1,submodule2....] -am [goal]

The module list (maven actually calls it "project list") is a comma separated list of the modules you want to (consider in this) build. It uses the same path syntax as in the pom.xml itself, in most cases that is just the name of the module or it's directory name. "-am" stands for also make which tells maven to automatically build dependency projects too.

This means that if your project is structured like this (note: db-migrator has a dependency on db-scripts)

+ parent
+ -- business-logic
+ -- frontend
+ -- db-scripts
+ -- db-migrator

You just need to use the following command to invoke maven in the db-migrator module and also automatically resolve and build the db-scripts module without ever having to wait for the not-needed frontend and business-logic modules. The maven goal here is fictional.

mvn -pl db-migrator -am db:migrate

Watch for Maven's reactor summery it will tell you what modules were built:

[INFO]
[INFO] parent................................................. SUCCESS [0.002s]
[INFO] db-scripts ............................................ SUCCESS [0.002s]
[INFO] db-migrator ........................................... SUCCESS [0.003s]
[INFO] business-logic ........................................ SKIPPED [0.000s]
[INFO] frontend .............................................. SKIPPED [0.000s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

So have fun with the reactor and save yourself some mvn clean install time and headaches.

Don`t miss out!

Want to receive more news that make you a better programmer or help you manage IT projects better? Sign up for our newsletter!

* indicates required
autor

Andreas Eisele

Andreas is a DevOps guru and the man for the hard programming jobs: everything JVM related & Linux servers, he can do it all ;)
Back to Overview

comments