Design Considerations: Lifecycle and Plugin Handling for Maven 2.1

Proposals

  1. Suppression, Ordering, and Replacement of Plugins and Mojos Bindings

Relevant New Features

  1. Deterministic Lifecycle Planning

Refactoring Aggregation

  • Problem controlling whether aggregation happens before vs. after the main build
  • Problems with aggregator mojos being bound into the lifecycle
  • Others? Need to accumulate problems from JIRA...

Suppression of Mojos and Executions

We need to provide a standardized way to suppress one or more executions of a given mojo. This is usually required when a mojo is bound to the build via packaging or something in the POMs ancestry.

Fine-grained Ordering of Phase Bindings

Need a way to organize the order of operations within a single lifecycle phase, in order to specify when a mojo binding should precede the standard bindings, etc.

Super-lifecycle

Provide a mechanism for external tools that embed Maven, so they can register pre- or post-build hooks per project.

Need more information about specific needs here...it may be better to enable this within the embedder itself, rather than interfering with the standard lifecycle.

Flexible Artifact Filtering for Maven's Core Classloader

If we find that we must include build extensions in Maven's core classloader, then we'll need a way to adjust the artifact filter used to avoid double-loading a given dependency in the plugin and the core. In other words, this filter prevents the loading of plugin dependencies into the plugin's classloader in cases where that dependency already exists in the core...in cases where build extensions are used, we need to ensure that this filter takes those loaded extensions into consideration.

Method for Defining Available Plugin Expressions

It would be useful to define the APIs exposed for plugin parameter injection using some sort of annotation or other tools. This would enable us to render a guide to plugin parameter expressions, and would remove the String-based logic associated with parameter injection. (Need more details here.)

  • No labels

5 Comments

  1. John,

    I would like to give some input/views/feedbck on the subject of "Suppression of Mojo and Executions" as I have had to handle this myself in some of my plugins and recently I also had a mailing list exchange with Kaare where this would have helped (see http://www.nabble.com/Problems-with-aspectj-maven-plugin-and-reporting-using-ajdoc-tf2060246.html#a6035528).

    I think that the suppressing execution on (at least) the following would come in handy:

    • package name
    • package version: you not want to run a certain plugin on non-stable releases such as alfa/beta or even SNAPSHOT
    • package type: some plugins only make sense to run on e.g. jar, war and ear

    and maybe even

    • module/project dependency: if there is a dependency on library x (e.g. project has dependency on aspecjt-rt run aspectj-ajdoc)
    • other plugins that executed or are to execute after: e.g. don't run plugin B if plugin A and C has already run

    This might be way overkill and make it harder for newcomers - I don't know. But, it think that a common and generic suppression mechanism would help Maven plugin developers as well as users a lot. Instead of each plugin having their own solution the user will get used to the configuration.

    How should this be configurable? excludes/includes with wildcard capability, regular expression or? I think that flexibility is of big concern, but at the same time it can't add to much complexitity as an "average" shall be able to use it easily.

  2. We also need to consider isolating local-repository storage of plugins in some cases.

    For example, if we have a multimodule build, and many modules use the same plugin, but one module specifies a snapshot repository and version for that plugin to be used there, it could (don't think it would now, but not sure) resolve the plugin metadata from the snapshot repository and replace the version to be used by other modules. This may result in Really Bad Things, so we need to be careful in this case.

  3. Unknown User (franz see)

    Good day,

    May I suggest the ability to define one's own packaging as well ( so that the user can assign his/her own default bindings to the phases ). This is related to "Suppression of Mojos and Executions" in the sense that this will not only allow users to change default bindings, but will allow them to use their configured bindings across other projects.

    Cheers,
    Franz 

  4. Unknown User (digulla@hepe.com)

    In the AROS project, we had good success with a tool called MetaMake. It allows to define targets in different projects and as soon as they are built together, mmake will figure out the common dependency tree and call the goals in the correct order. Here is an example what it can do:

    #MM include : generate-includes
    #MM install : install-includes

     This way, my project says "whenever you run the global target "include", run my target "generate-includes". Same goes during the install. This can be taken one step further:

     #MM generate-includes : build-preprocessor

    This makes sure the preprocessor is built before any project runs "generate-includes".

    Internally, I build a tree/graph of all dependencies and then start with building the first leaf (ie. some node which doesn't depend on anything else). Then I remove the leaf and repeat. If there is no leaf, then I know there must be a cyclic dependency somewhere. This was pretty simple to implement and allows our project to control the build of each part with as much detail as the part needs.

    MetaMake itself doesn't even maintain a standard lifecycle. Instead, we have a mmakefile somewhere where we define it (mmake always reads all of them at once and then processing starts, so mmake always has a top view):

    #MM all : prepare compile install
    #MM prepare : build-tools include
    ...

    "all" is the default target which mmake will run but you can also supply any number of targets on the command line and mmake will stop when they are built.

    I would like to see something like this replace the limited lifecycle management of Maven2. In the end, there shouldn't be any goals, targets or phases because they confuse users to no end (what's the difference between them? Why are you always talking about targets and then suddenly of "lifecycle"? etc). Instead, there should be only targets. Maven should define standard targets and the plugins should be able to say "before the target XXX can be run, I want a go!"

    I'm not sure if we also need "post targets". I don't think that is possible to reliably sort out all dependency issues in the plugin itself. Instead, I suggest that you can define additional dependencies in the POM. This way, a developer can make sure that competing plugins run in the order she needs.

  5. Unknown User (digulla@hepe.com)

    I've found two new use cases which are hard to do with Maven:

    GWT: GWT creates a lot of files which are collected in a WAR. In my case, I have to create and add META-INF/context.xml after the WAR has been built, so I need to inject a phase between package and install.

    Groovy: I can have Groovy code which depend on Java and Java code which depends on Groovy. Therefore, I need two or three compile phases so I can compile incrementally.