Status
Version1
Issue(s)

Sources
Developer(s)


Status

This RFC is currently in the DRAFT state. Nothing in this RFC has been agreed or confirmed.

Contents

Introduction


Provide a way to control the execution of MOJOs within a phase and guarantee that specific MOJOs will be executed around lifecycle phases

Background

The standard Maven lifecycles have a number of phases with names that start with pre- and post- as siblings to a main phase, for example:

Most new users assume that as the pre- phases will be executed before the main phase (which is correct, but only be the accident of the lifecycle ordering) the post- phases will be executed after the main phase much like the finally block in a Java try expression (which is incorrect).

If we look more critically at the lifecycle phases we can also identify a number of phases that are purely present to enable the correct sequencing of MOJO executions:

The resulting multiude of phases just furthers the complexity for users: they become parallelized by choice.

Proposal

Provide a pom.xml  only naming scheme for ad-hoc dynamic phases that will enable the pom.xml  to control execution while restricting this syntax to the pom.xml  only. The command line would only be able to invoke the explicit lifecycle phases directly.

To clarify, these dynamic phases would only be valid in the /executions/execution/phase  element of a <plugin>  in the pom.xml 

There will be two classes of dynamic phases:

  1. Guaranteed execution
  2. In phase ordering

Note: please append any alternative syntax proposals to this section

Option 1: (before:|after:)$phase([$priority])

This syntax uses two prefixes before:  and after: to identify phases that will be guaranteed to run before and after the named phase $phase. As a result we would be able to deprecate the pre-integration-test  and post-integration-test  phases in favour of before:integration-test  and after:integration-test  which would not be defined in any lifecycle, but instead be dynamically created by virtue of specifying an execution bound to that phase.

<plugin>
  ...
  <executions>
    <execution>
      <id>start-server</id>
      <phase>before:integration-test</phase>
      <goals>
        <goal>start</goal>
      </goals>
      ...
    </execution>
    <execution>
      <id>stop-server</id>
      <phase>after:integration-test</phase>
      <goals>
        <goal>stop</goal>
      </goals>
      ...
    </execution>
    ...
  </executions>
  ...
</plugin>

Every phase in any lifecycle would have its own implicit before:  and after:  phases in the lifecycle.

The logic of using :  in these prefix names is that it would expressly be impossible to invoke these dynamic pseudo phases from the CLI as Maven will interpret any attempt to invoke them as $plugin:$goal and look for a maven-before-plugin  or maven-after-plugin 

The within phase ordering will be achieved by the addition of a [$priority] suffix. The priority will be an integer (positive and negative allowed) and execution of the lifecycle phase will invoke all bound MOJOs in order starting with the highest priority and ending with the lowest priority. Where two executions have the same priority, they will be executed in pom.xml  order.

The logic of using []  in these suffix priorities is that these characters are in the typical reserved set for POSIX shells and used to specify a range of characters, again making it difficult to envision invoking a phase with priority from the command line without careful escaping. In any case the CLI would not permit the execution of a phase with priority. The CLI will only be able to execute a phase as a whole.

<packaging>war</packaging>
...
<plugin>
  <artifactId>maven-jar-plugin</artifactId>
  <executions>
    <!-- create the jar file to use inside the war -->
    <execution>
      <phase>package[-1000]</phase>
      <goals>
        <goal>jar</goal>
      </goals>
      ...
    </execution>
    ...
  </executions>
  ...
</plugin>
<plugin>
  <artifactId>maven-assembly-plugin</artifactId>
  <executions>
    <!-- create the distribution that includes the war and docs -->
    <execution>
      <phase>package[2000]</phase>
      <goals>
        <goal>assemble</goal>
      </goals>
      ...
    </execution>
    ...
  </executions>
  ...
</plugin>


In order to allow lifecycle bindings per project type to include information about the pseudo phases and phase priorities, we would need to modify the syntax of the bindings reference, e.g. https://maven.apache.org/ref/3.6.2/maven-core/default-bindings.html

This proposal would modify the bindings XML schema to include optional attributes of execution-point  and priority if not specified then the execution point would be considered to be the phase itself and not before  or after  and the priority would be assumed to be 0 

    <phases>
      ...
      <integration-test execution-point="before">
        ...:...:...:start
      </integration-test>
      <integration-test execution-point="after" priority="1000">
        ...:...:...:stop
      </integration-test>
      ...
    </phases>

The rationale is that this schema change is backwards compatible with the existing bindings schema and thus existing extensions defining bindings will still remain valid (just not able to bind to these dynamic phases)

We would also need to modify the @Mojo  annotation adding new properties executionPoint = ExecutionPoint.BEFORE|ExecutionPoint.AFTER  and priority = <int> 

Lifecycle simplification

This proposal would lay the groundwork for the simplification of the Maven lifecycles. This proposal would only bring us to the transitional state, with the migration to the future state likely part of the Maven 5.0.0 effort.

Clean lifecycle

CurrentTransitionalFuture
pre-clean pre-clean  (deprecated with recommendation to use before:clean )use before:clean 
cleancleanclean
post-cleanpost-clean (deprecated with recommendation to use after:clean)use after:clean


Default lifecycle

CurrentTransitionalFuture
validate validate validate 
initialize initialize initialize 
generate-sources generate-sources (deprecated with recommendation to use before:sources use before:sources 

sources sources 
process-sources process-sources (deprecated with recommendation to use after:sources use after:sources 
generate-resources generate-resources (deprecated with recommendation to use before:resources use before:resources 

resources resources 
process-resources process-resources (deprecated with recommendation to use after:resources use after:resources 
compile compile compile 
process-classes process-classes (deprecated with recommendation to use after:compile use after:compile 
generate-test-sources generate-test-sources (deprecated with recommendation to use before:test-sources use before:test-sources 

test-sources test-sources 
process-test-sources process-test-sources (deprecated with recommendation to use after:test-sources use after:test-sources 
generate-test-resources generate-test-resources (deprecated with recommendation to use before:test-resources use before:test-resources 

test-resources test-resources 
process-test-resources process-test-resources (deprecated with recommendation to use after:test-resources use after:test-resources 
test-compile test-compile test-compile 
process-test-classesprocess-test-classes (deprecated with recommendation to use after:test-compile use after:test-compile 
test test test 
prepare-package prepare-package  (deprecated with recommendation to use before:package use before:package 
package package package 
pre-integration-test pre-integration-test  (deprecated with recommendation to use before:integration-test use before:integration-test 
integration-test integration-test integration-test 
post-integration-test post-integration-test  (deprecated with recommendation to use after:integration-test use after:integration-test 
verify verify verify 
install install install 
deploy deploy deploy 

To be determined:

Site lifecycle

CurrentTransitionalFuture
pre-site pre-site  (deprecated with recommendation to use before:site )use before:site
sitesitesite
post-sitepost-site (deprecated with recommendation to use after:site)use after:site
site-deploy site-deploy site-deploy