Additions
- Add hooks for different versions of the model and Polyglot support in general (the strategy can be taken from Polyglot for Maven), but an extension point is required in the core so that different libraries needed for parsing various formats are not all required in the distribution.
- A Builder interface for the different strategies we have for modes like single threaded, multi-threaded, and introduce a new implementation for aggressive parallelization and smart scheduling.
- A proper place at the beginning and end of the build to execute. The AbstractMavenLifecycleParticipant is working now to do some of that work, but with aggressive concurrency many of the techniques currently used (like the deploy-at-end technique in the deploy plugin) are not thread safe and assume a mode of serial execution. Robert Scholte: We should think of a smarter lifecycle-mechanism. The install and deploy phases are kind of finalize phases, which are only useful when all projects were packaged successfully.
- Execution environments: being to specify versions of the JVM in a similar way as Eclipse does, for spawned processes being able to pass in all Maven parameters and settings consistent (MNG-5199). This probably requires coming up with the one way to fork/invoke projects and finally get rid of the 5 ways we currently do it. Here I'm not sure what happens to the toolchains as they are a mechanism which is primarily used for finding a JDK other than the one Maven is started with.
- Overhauling profiles
- Smarter reactor. If you have a reactor with four projects: common-parent, jar-module, war-module and acceptance-tests-module. There is a dependency chain within the reactor, e.g. acceptance-tests-module:
pom
depends on war-module:war
depends on jar-module:jar
. If the user invokesmvn test
then Maven 2/3 will do the wrong thing, either blowing up because there is no war-module:war
dependency available, or using the war-module:war
that was installed 5 weeks ago when somebody last ranmvn install
. Neither of these is the correct thing to do. The correct thing to do is something along the lines of the following.- The build plan starts with all modules trying to attain the
test
phase. Then we start inspecting dependencies required by each module.- jar-module has no dependencies, so it stays as is.
- war-module has a plugin bound to the
compile
phase that needs either jar-module:jar
or jar-module/target/classes
, and as the latter is produced by jar-module in theprocess-classes
phase we add a constraint that the jar-moduleprocess-classes
phase must happen before the war-modulecompile
phase. - acceptance-tests-module has a plugin bound to the
generate-test-resources
phase that needs war-module:war
. We add a constraint that the war-modulepackage
phase must happen before acceptance-tests-modulegenerate-test-resources
phase and consequently the war-module is now escalated to build as far as thepackage
phase. - war-module has a plugin bound to the
package
phase that needs jar-module:jar
. We add a constraint that the jar-modulepackage
phase must happen before the war-modulepackage
phase and consequently the jar-module is now escalated to build as far as thepackage
phase.
- The net result:
- jar-module
process-classes
happens before war-modulecompile
- jar-module
package
happens before war-modulepackage
war-module
package
happens before acceptance-tests-modulegenerate-test-resources
- jar-module
- A single threaded reactor will run jar-module up to
package
, war-module up topackage
and finally acceptance-tests-module up totest
- A parallel reactor with three threads will be able to put locks in places such that the reactor behaves correctly
- This would be quite a big change, but one that makes Maven a lot more useful.
- Need a way to flag a packaging type as being produced by a mojo execution
- Need a way to flag where a mojo can take dependency substitutions... this is to let the
mvn compile
use case work without running the tests of upstream modules within the reactor. Another way to achieve that is to reorder the lifecycle and move the test phases afterpackage
... of course if we start assuming fork-join lifecycles we could let thepackage
phase run in parallel with the test phases which would let us split things up... another option would be to let phases be marked with constraints... so we can define a natural order to the lifecycle (i.e. the order the phases are listed in) and add phases that must happen before to the phase definition.
- The build plan starts with all modules trying to attain the
<phases>
<phase>validate</phase>
<phase after="validate">initialize</phase>
<phase after="initialize">generate-sources</phase>
<phase after="generate-sources">process-sources</phase>
<phase after="initialize">generate-resources</phase>
<phase after="generate-resources">process-resources</phase>
<phase after="process-sources">compile</phase>
<phase after="compile">process-classes</phase>
<phase after="initialize">generate-test-sources</phase>
<phase after="generate-test-sources">process-test-sources</phase>
<phase after="initialize">generate-test-resources</phase>
<phase after="generate-test-resources">process-test-resources</phase>
<phase after="compile, process-test-sources">test-compile</phase>
<phase after="test-compile">process-test-classes</phase>
<phase after="process-test-classes">test</phase>
<phase after="process-resources, compile">prepare-package</phase>
<phase after="prepare-package">package</phase>
<phase after="package, test-compile" finally="post-integration-test">pre-integration-test</phase>
<phase after="pre-integration-test">integration-test</phase>
<phase after="integration-test">post-integration-test</phase>
<phase after="post-integration-test">verify</phase>
<phase after="verify, package">install</phase>
<phase after="install">deploy</phase>
</phases>
The sequence of phases in the lifecycle would define the natural order which is what applies when the phase is specified on the command line. The after constraints would only apply when escalating a module, so when we escalate the war-module to package, we see that it must happen after prepare-package, which is after compile and process-resources. Now that would not have any net effect when running mvn test
on the example reactor, but it would have an effect when running mvn test-compile
as it would mean that any unit tests in jar-module and war-module would not be executed.
This kind of extra lifecycle constraints would also help us parallelise the build even more.
- Finally, if we can find a way of flagging mojos as producing artifacts with particular packagings, Maven could also escalate across different lifecycles. Say for a contrived example we have the site lifecycle producing the javadoc:jar, if we have the dependency plugin try to unpack the javadoc:jar into the war file during prepare-package then when invoking package we could insert a happens before constraint such that the pre-site phase gets pulled in.
- Also, might be helpful to have pre-site require validate as the first phase and perhaps site requires process-sources and process-test-sources which would remove a lot of the forked lifecycle issues with e.g. javadocs when running mvn clean deploy site-deploy. You would still need a forked lifecycle type of thing for code coverage, but most of the other use cases would then be redundant.
Cleanup
- All the listener interfaces are pretty convoluted and incomplete, we should probably review again. EventSpies cannot be hooked into the build as normal extensions so they are really kind of useless (hence the recent addition of AbstractMavenLifecycleParticipant#afterSessionEnd)
- ReactorManager: there are many inconsistencies where test jars are not resolved in the reactor, and the special magic that happens in the compiler plugin currently where it sets the artifacts file to the compile classes directory. This all needs to be encapsulated in a new workspace reader that behaves consistently and doesn't require special behavior in certain plugins. If you wrote a new compiler plugin for example and didn't set the file everything would break which is just poor encapsulation.
Removal
- Remove all site related configuration from the POM:
- Hervé Boutemy: I'm not ok with this one, reporting is useful.
- JVZ, then we'll need to discuss this because I don't see it as different than a normal set of plugins and there is no reason they can't just work as normal plugins. No disagreement that some think the site plugin is important but it should have no special provisions in the core.
- HB yes, there should be features in core for the site plugin be a normal plugin: AFAIK the key missing feature in core for maven-site-plugin is reporting plugins configuration inheritence: see explanations in the site plugin doc on why we went back to configure reporting in POM's reporting section instead of site plugin's reportPlugins parameter (and I don't want to live such a failure where we explained users to do something then to revert)
- Remove Ant Mojos, Beanshell and anything else no one is actually using. I think people will prefer the polyglot mode
- Remove RuntimeInfo (
MNG-3954) - Remove scope=system
- Remove LegacySupport
- Remove automatic plugin version selection (MNG-4173)
- Remove leniency for invalid parent POMs (
MNG-4488). There is no reason at this point the parent should not be valid. - Remove much deprecated code:
- In MavenSession, all the Plexus container related code
- PlexusUtilsInjector (not required it was a bridge way back for Maven 2.x)
- maven-compat and update our plugins not to use it
- Remove dynamic dependency addition. Dependencies should be explicit, no more magic support for things like the Cobertura plugin that injects dependencies (MNG-4363)
- Plexus: plexus-annotations, PlexusContainer. We should be fully JSR330 and where we need a container, and we still do in several places, we should make a small interface so we can use Sisu, Dagger, or anything else
Get rid of aggregator plugins, there are better ways to deal with aggregation. Something that can execute at the end of the build the start of the is the AbstractLifecycleParticipant.afterSessionEnd