maven reactor

“Maven Combat” study notes

In a multi-module Maven project, a reactor (Reactor) refers to a build structure composed of all modules.
For a single-module project, the reactor is the module itself, but for a multi-module project, the reactor includes the inheritance and dependency relationship between modules, so that it can automatically calculate a reasonable The order in which modules are built.

The build order of the reactor

In order to explain the build order of the reactor more clearly, the aggregation configuration of account-aggregator is modified as follows:

 <modules>
      <module>account-email</module>
      <module>account-persist</module>
      <module>account-parent</module>
  </modules>

account-email extends account-parent
account-persist extends account-parent

After the modification, build account-aggregator and you will see the following output:

[INFO] Scanning for projects...
[INFO] ----------------------------------------------- -------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] account-parent [pom]
[INFO] account-email [jar]
[INFO] account-persist [jar]
[INFO] account-aggregator [pom]
[INFO]

If you read the POM files sequentially, the first thing you should read is the POM of account-asgregator, and the actual situation is consistent with the expectation,
However, the construction order of the next few modules is inconsistent with their declaration order in the aggregation module. account-parent came before account-email . Why? ? To explain this phenomenon:

Arrows from top to bottom indicate the POM reading order, but this is not enough to determine the build order of the reactor, Maven also needs to consider the inheritance of modules and dependencies, because the directed dotted lines indicate inheritance or dependencies between modules.
In this example, account-email and account-persist depend on account-parent. Then account-parent must be built before the other two modules.

There is also a right-to-left arrow. The actual build order is formed like this:

  • Maven reads the POM sequentially, if the POM does not have a dependent module, then build the module, otherwise build its dependent module first.
  • If the dependency also depends on other modules, further build the dependent dependencies first.

In this example,

  • account-aggregator has no dependencies, so build it first,
  • Then to account-email, it depends on the aecount-parent module, account-parent must be built first,
  • Then build account-email,
  • Finally, when it comes to account-persist, since its dependent modules have already been built, build it directly.

The dependencies between modules will form the reactor into a Directed Acyclic Graph (Direeted AcyelicGraph, DAG), Each module is a node of the graph, and the dependencies form a directed edge. This graph does not allow cycles, so When module A depends on B, and B depends on A, Maven will report an error.

Crop Reactor

Tailor Reactor Generally, users will choose to build the entire project or choose to build individual modules,
But sometimes, users will want to build only certain modules of the complete reactor. In other words, the user needs to crop the reactor in real time.
Maven provides a lot of command line options to support tailoring the reactor, enter mvn -h to see these options:

  • -am,–also-make Also build the dependent modules of the listed modules **(find ancestors)**
  • -amd,–also-make-dependents Also build modules that depend on the listed modules **(find descendants)**
  • -pl –project Build the specified modules, separated by commas
  • -rf -resume-from Resume the reactor from the specified module

Example

mvn clean install -pl account-email,account-persist

[INFO] Scanning for projects...
[INFO] ----------------------------------------------- -------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] account-email [jar]
[INFO] account-persist [jar]
[INFO]

mvn clean install -pl account-email -am
Since account-email depends on account-parent, you get a reactor like this:

[INFO] Scanning for projects...
[INFO] ----------------------------------------------- -------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] account-parent [pom]
[INFO] account-email [jar]

Use the -amd option to simultaneously build modules that depend on the listed modules.
**mvn clean install -pl account-parent -amd **

[INFO] Scanning for projects...
[INFO] ----------------------------------------------- -------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] account-parent [pom]
[INFO] account-email [jar]
[INFO] account-persist [jar]

Use the –leaf option to specify which module to start building on top of the complete reactor build order.
mvn clean install -rf account-email
For example: in the complete reactor build order, account-email is third, after it only account-persist,
Thus we get the following tailored reactor:

[INFO] Scanning for projects...
[INFO] ----------------------------------------------- -------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] account-email [jar]
[INFO] account-persist [jar]
[INFO] account-aggregator [pom]

Finally, on top of **-pl -am or -pl -amd**, the -rf parameter can also be applied to re-crop the trimmed reactor
mvn clean install -pl account-parent -amd -rf account-email

[INFO] Scanning for projects...
[INFO] ----------------------------------------------- -------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] account-email [jar]
[INFO] account-persist [jar]

During the development process, flexible application of the above four parameters can help us skip modules that do not need to be built, thus speeding up the build. This effect will be very obvious when the project is large and the modules are particularly new.