Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

1. Background

In Maven 2.x we have a boolean mojo annotation @aggregator with the following effects on the mojo execution:

Execution

For mojos executed directly from the CLI, the mojo will only be executed once and not per each project in the reactor.
For mojos bound to a lifecycle phase, the mojo will be executed for each project where the lifecycle binding is present.

Dependency Resolution

If an aggregating mojo is annotated with @requiresDependencyResolution, the core will resolve the dependencies for all projects in the reactor and not just for the current project.

Forking

The annotation @execute on an aggregating mojo will fork the requested goal/phase on all projects in the reactor.

Besides, aggregating mojos often use the parameter expression reactorProjects or MavenSession.getSortedProjects() to get hold off all the projects in the reactor for processing.

The current design has some problems, especially if aggregators are bound into a lifecycle phase, so let's step back and look what we want to support and how this might work.

2. Use Cases

While we currently have only one annotation to request aggregation, we have at least two different use cases for it. The differences in these use cases as outlined next contribute to the problems we currently encounter with aggregation and its use.

...

It's assumed that build hooks are implemented as regular mojos (with special annotations) and are introduced to a build via plugin executions defined in the POM. However, the <phase> element of such a plugin execution would have a slightly different meaning. Instead of saying "bind this mojo into lifecycle phase xyz" it should be intepreted interpreted as "if the build executes to phase xyz or beyond, register this mojo as a pre-/post-build hook".

...

A concrete example for this type of aggregation is the production of aggregated API docs or other assembly-like output that should be attached to a project and installed/deployed alongside the main artifact. An aggregated site with summary reports is another example.

Scope for Aggregation

Orthogonal to the scenarios outlined above, we have to distinguish what part of a reactor build should be subject to aggregation. Consider the following multi-module hierarchy where the projects marked with (X) associate an aggregating mojo with their lifecycle:

...

To address this distinction in aggregation scope, we might start off with new mojo annotations like @aggregator top-level|project that plugin authors can use to indicate the desired operational mode. But it seems this ultimatively ultimately demands a new POM element to enable the user to choose the mode that fits his intentions.

...

When running Maven on the top-level project, it seems unintuitive to invoke the aggregating mojo on the entire reactor just because the user ran the build from a higher level of the project hierarchy where however the aggregating mojo is not declared. This would extend the effect of the aggregator to modules that are no sub modules of its declaring project S1. This is exactly one of the problems we have in Maven 2.x where an aggregating mojo bound to a lifecycle phase causes dependency resolution for the entire reactor although some modules haven't been built yet.

...

3.

...

Realization

All the different use cases outlined above are the things that we might want to support in future Maven versions. Yet we historically have only this single boolean @aggregator annotation that does not tell which use case a mojo is intended to serve. It appears though that the majority of aggregating mojos out there is meant to provide summary mojos. Hence I propose the following behavior of Maven core:

...

The details of this are left open for future design. Right now, I simply assume we will introduce new mojo annotations to mark those goals and distinguish them from the summary mojos that continue to use the existing @aggregator annoation annotation.

4. Related Articles

  1. Atypical Plugin Use Cases
  2. Deterministic Lifecycle Planning