Message-ID: <1838844469.298936.1368950270231.JavaMail.email@example.com> Subject: Exported From Confluence MIME-Version: 1.0 Content-Type: multipart/related; boundary="----=_Part_298935_1370348871.1368950270230" ------=_Part_298935_1370348871.1368950270230 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Content-Location: file:///C:/exported.html
In Maven 2.x we have a boolean mojo annotation
with the following effects on the mojo execution:
For mojos executed directly from the CLI, the= mojo will only be executed once and not per each project in the reactor. F= or mojos bound to a lifecycle phase, the mojo will be executed for each pro= ject where the lifecycle binding is present.
If an aggregating mojo is annotated with
Besides, aggregating mojos often use the parameter expression
MavenSession.getSortedProjects() to get =
hold off all the projects in the reactor for processing.
The current design has some problems, especially if aggregators are boun= d into a lifecycle phase, so let's step back and look what we want to suppo= rt and how this might work.
While we currently have only one annotation to request aggregation, we h= ave at least two different use cases for it. The differences in these use c= ases as outlined next contribute to the problems we currently encounter wit= h aggregation and its use.
Given a (multi-module) build, users might want to perform tasks before t= he lifecycle of the first project starts or after the lifecycle of the last= project has completed. For instance, imagine a build like this:
It's assumed that build hooks are implemented as regular mojos (with spe=
cial annotations) and are introduced to a build via plugin executions defin=
ed in the POM. However, the
<phase> element of such a pl=
ugin execution would have a slightly different meaning. Instead of saying &=
quot;bind this mojo into lifecycle phase xyz" it should be intepreted =
as "if the build executes to phase xyz or beyond, register this mojo a=
s a pre-/post-build hook".
A further mojo annotation could be introduced to enable the plugin autho= r to control whether a post-build hook should be called regardless whether = the build failed before, i.e. to provide some finally-like cleanup.
An example use for a pre-build hook could be an Enforcer rule that check= s the build environment before any of the projects start to build.
A probably more common use case is to post-process output from child mod= ules in order to produce some aggregated/summarized output. In terms of bui= ld steps, this would look like:
The important difference of such a summary mojo compared to a post-build=
hook is the interaction with the regular lifecycle. A summary mojo bound t=
o say the
package phase would be executed during this phase su=
ch that later phases like
deploy of th=
e current project's build have access to the output of the summary mojo.
Finally note that for the summary mojo to be able to aggregate the outpu= t from the child modules, the aggregator project needs to run after the chi= ld modules.
A concrete example for this type of aggregation is the production of agg= regated 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.
Orthogonal to the scenarios outlined above, we have to distinguish what = part of a reactor build should be subject to aggregation. Consider the foll= owing multi-module hierarchy where the projects marked with (X) associate a= n aggregating mojo with their lifecycle:
mvn deploy on the top-level aggregator POM could ha=
ve the following effects:
Both styles have their supporting use cases. For a summary mojo that pro= duces an aggregated assembly, the user might not want to skip this assembly= step just because he invoked the build from a higher level of the project = hierarchy where an even bigger assembly is produced. For a pre-build hook l= ike a validation step on the other hand, it might be preferable to run only= on the top-most project (e.g. for performance reasons).
To address this distinction in aggregation scope, we might start off wit=
h new mojo annotations like
@aggregator top-level|project that=
plugin authors can use to indicate the desired operational mode. But it se=
ems this ultimatively demands a new POM element to enable the user to choos=
e the mode that fits his intentions.
Compared to Maven 2.x, the first style of aggregation resembles somehow = the current behavior, i.e. the aggregating mojo being executed in each proj= ect it is encountered. The major difference however is the order in which t= he individual projects are executed. For the common setup where the aggrega= tor POM is also used as parent POM, it would be build ahead of the child mo= dules in 2.x, making aggregation of child output impossible right now.
Also note that the second style of aggregation does not necessarily mean= the aggregating mojo is only executed once per reactor build. Consider thi= s variation of the above example where the aggregating mojo is only declare= d in S1:
When running Maven on the top-level project, it seems unintuitive to inv= oke the aggregating mojo on the entire reactor just because the user ran th= e build from a higher level of the project hierarchy where however the aggr= egating mojo is not declared. This would extend the effect of the aggregato= r to modules that are no sub modules of its declaring project S1. This is e= xactly one of the problems we have in Maven 2.x where an aggregating mojo b= ound to a lifecycle phase causes dependency resolution for the entire react= or although some modules haven't been built yet.
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 thi=
s single boolean
@aggregator annotation that does not tell whi=
ch use case a mojo is intended to serve. It appears though that the majorit=
y of aggregating mojos out there is meant to provide summary mojos. Hence I=
propose the following behavior of Maven core:
A project with packaging
pom can serve both as a parent POM=
and as an aggregator POM. Inheritance belongs to the construction of the e=
ffective model and happens long before we reach the lifecycle executor and =
as such does not care about project order. Aggregation in the sense of a su=
mmary mojo however imposes a constraint on the order namely that the projec=
t with the aggregating mojo needs to be built after its child modules. For =
this reason, the project sorter needs to be changed to mark an aggregator P=
OM as a dependant of all its modules. This is contrary to the related artic=
le (1) and the current behavior of Maven 2.x. The hopefully few cases where=
users setup an aggregator POM to produce some artifact for comsumption by =
sub modules would demand to restructure the build and move the production o=
f the artifact to a sub module of the aggregator.
A mojo flagged as
@aggregator should no longer trigger depe=
ndency resolution for the entire reactor but only for the sub tree of the p=
roject hierarchy where the aggregating mojo is rooted. For a mojo invoked d=
irectly from the CLI, this effectively makes no differences compared to Mav=
en 2.x. For mojos bound to the lifecycle, this prevents dependency resoluti=
on errors on modules that due to the project order can never be build in ti=
me for the aggregating mojo.
Just as with dependency resolution, an aggregating mojo should no longer= fork the entire reactor but only the sub tree of the project hierarchy it = is relevant for.
What remains unclear to myself is how to handle the
s parameter expression in aggregating mojos. I am tempted to believe=
that those mojos don't really want all reactor projects but again only the=
sub tree of the project hierarchy they operate in. If this assumption prov=
es sensible, it would fit the bill to change the semantics of the
ctorProjects expression to only deliver the projects from the sub tr=
ee of the project hierarchy, thereby being in sync with the changes for dep=
endency resolution and forking.
The obvious alternative is to leave
reactorProjects as is a=
nd introduce a new expression
subProjects or similar that only=
delivers the current project and all its (transitive) sub modules.
Internally, the core will need to keep the tree of projects that forms t=
he project hierarchy as determined by aggregation, i.e. via the
odules> section in the POM.
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 dist=
inguish them from the summary mojos that continue to use the existing