When working with Java you will sooner or later come across Maven and Maven modules. Before you start developing a new module feature, upstream modules need to be built, and before you finish you must build downstream modules to make sure that you have not broken any dependencies or tests. However, it is not always obvious how different modules relate to each other. If you just call mvn clean install
at the project root it does not really matter, but as the project grows the builds will become more and more tedious. This blog aims to demonstrate how you can take advantage of Maven command line options to work in a smarter, more efficient way.
Project
Let us assume that we have a project structure with the modules below and that we will add a new feature to the A1 module:
master | +- A | +- A1 (the module under development) | +- A2 | +- B | +- B1 (depends on A1) | +- B2 | +- ITest (integration tests enabled by the "itest" profile) | +- A-ITest | | +- A1-ITest (depends on A1) | | +- A2-ITest (depends on A2) | | | +- B-ITest | | +- B1-ITest (depends on B1) | | +- B2-ITest (depends on B2) | +- more modules...
If you are in the master folder and execute mvn clean install -Pitest
, then all projects will be compiled, tests will be executed, integration tests will be executed and the resulting binaries will be deployed to your local Maven repo as expected. All is good, but it may take a while to complete. In the following example, we will see how it is possible to work on the A1 module without rebuilding the non-dependent A2* and B2* modules.
Build a single module
If you are working with a single module, it is possible to compile and test just the specific project by providing the -pl
(or --projects
) option and add a colon before the specific artifact id. For example, if you just would like to build the A1 project, simply execute:
mvn -pl :A1 clean install
If you would like to build more than one project, just add list the artifact ids separated by comma. To build both A1 and A2:
mvn -pl :A1,:A2 clean install
Build dependencies and module
Building a single module will only work if you have access to its dependencies. If it is the first time you build a project, or if you have updated your project with the latest changes from the version control, you may have to rebuild the module’s upstream dependencies. Continuing with the example, this implies that you need to build both the master and the A module before attempting to build the A1 module. Of course, the just mentioned -pl
can be used, but there is another Maven option that works out the dependency graph for you so that the master, A and A1 will be built in one command. The -am
(or --also-make
), option does exactly that:
mvn -pl :A1 -am clean install
Build module and dependents
When you have finished the implementation of your A1 feature, you would like to be sure that all downstream modules that depend on A1 still works. To build the A1 and the B1 projects in one command you can use the -amd
(or --also-make-dependents
) option:
mvn -pl :A1 -amd clean install
Similarly, if you also would like to execute the integration test, you must enable the itest profile with the -P
option. The modules A1, B2, A1-ITest and B1-ITest will be built consequently:
mvn -Pitest -pl :A1 -amd clean install
Reference
Maven has many other command line options such as -o
, -fae
and -rf
that can be used to tweak and improve your builds if used wisely. See the Maven command line help for reference, or simply execute Maven with the -h
(or --help
) option:
mvn -h
Pingback: itemprop="name">Programming with Opendaylight | Sreenivas Makam's Blog
Hi,
one note:
mvn -pl :A1,:A2 clean install
ist not correct, you have to name the modules without the colon.
mvn -pl A1,A2 clean install
would be correct.
@Sascha: Well, it depends if you are addressing your modules based on their artifact ids (i.e. they are prefixed with colons), or on their relative paths (no colons), see the output of
mvn -help
:Maven extension gitflow-incremental-builder may be your friend. If you have multi-module maven project and you need to build or test only modules containing changes between two branches e.g. develop is usually stable and feature branches are not.
See: https://github.com/vackosar/gitflow-incremental-builder
@Vaclav: This is news for me, thanks for sharing.
Looks like reactor is retired, is there any other way to achieve this?
@Krishna: I am sorry, I do not know. It was quite some time ago since I last used Maven and I have not been keeping up with its tools and plugins development.
Thanks for sharing. This really helped me better understand how to conditionally compile/test specific modules in my multi module project
@Matt: Thanks, glad to help.
Hey,
I’m trying to tun exclusive test, using the module specification command, but the tests aren’t running.
Do you know what is the reason?
Here is my command:
mvn -pl :tika-parsers -am test surefire:test -DfailIfNoTests=false -Dmaven.test.failure.ignore=true -Dtest=org.apache.tika.mime.TestMimeTypes
@Rotem: When debugging CLI tools in general, my recommendation is that you start from the basics. For example, start by executing
mvn test
. When that works, add another option such as the “projects” option , e.g.mvn -pl :tika-parsers test
. If is still working add the “also make” optionmvn -pl :tika-parsers -am test
and so on until you no longer get the expected result. At that point you know which option failed and you can make appropriate changes.