--- Guide to Configuring Default Mojo Executions --- John Casey --- 2009-06-10 --- ~~ Licensed to the Apache Software Foundation (ASF) under one ~~ or more contributor license agreements. See the NOTICE file ~~ distributed with this work for additional information ~~ regarding copyright ownership. The ASF licenses this file ~~ to you under the Apache License, Version 2.0 (the ~~ "License"); you may not use this file except in compliance ~~ with the License. You may obtain a copy of the License at ~~ ~~ http://www.apache.org/licenses/LICENSE-2.0 ~~ ~~ Unless required by applicable law or agreed to in writing, ~~ software distributed under the License is distributed on an ~~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY ~~ KIND, either express or implied. See the License for the ~~ specific language governing permissions and limitations ~~ under the License. ~~ NOTE: For help with the syntax of this file, see: ~~ http://maven.apache.org/doxia/references/apt-format.html Guide to Configuring Default Mojo Executions In most cases where you need to configure a plugin, there are two options that work well: plugin-level configuration and execution-level configuration. Plugin-level configuration is the most common method for configuring plugins that will be used from the command line, are defined as part of the default lifecycle, or that use a common configuration across all invocations. In fact, for direct invocation from the command line, plugin-level configuration has been the option historically. On the other hand, in cases where a more advanced build process requires the execution of mojos - sometimes the same mojos, sometimes different ones - from a single plugin that use different configurations, the execution-level configuration is most commonly used. These cases normally involve plugins that are introduced as part of the standard build process, but which aren't present in the default lifecycle mapping for that particular packaging. In these cases, common settings shared between executions are still normally specified in the plugin-level configuration. However, these two options leave out a few important configuration use cases: # Mojos run from the command line during the build, when the CLI-driven invocation requires its own configuration. # Mojo executions that are bound to the lifecycle as part of the default mapping for a particular packaging, especially in cases where the same mojos need to be added to a second execution with different configuration. # Groups of mojos from the same plugin that are bound to the lifecycle as part of the default mapping for a particular packaging, but require separate configurations. [] Originally, the default value of the executionId - literally set to <<>> in the POM model - was meant to provide some of this functionality. Unfortunately, this solution was never tested to make sure it worked with the use cases above; they fell through the cracks during testing. Now, with the release of Maven 2.2.0 (and later, Maven 3.0), these use cases can finally be addressed. *Default <<>>s for Implied Executions When you consider the fact that the aforementioned configuration use cases are for mojos that are not explicitly mentioned in the POM, it's reasonable to refer to them as implied executions. But if they're implied, how can Maven allow users to provide configuration for them? The solution we've implemented is rather simple and low-tech, but should be more than adequate to handle even advanced use cases. Starting in Maven 2.2.0, each mojo invoked directly from the command line will have an execution Id of <<>> assigned to it, which will allow the configuration of that execution from the POM by using this default execution Id. Likewise, each mojo bound to the build lifecycle via the default lifecycle mapping for the specified POM packaging will have an execution Id of <<>>> assigned to it, to allow configuration of each default mojo execution independently. **Example: Command-line variant invocation of the assembly plugin Consider the case where the user wants to execute the <<>> mojo directly on the command line, but already has a configuration for the <<>> mojo that runs during the main build lifecycle. Since these configurations require different options, the user cannot use the plugin-level configuration section to specify common elements. In this case, the assembly-plugin configuration might look like this: +---+ maven-assembly-plugin gnu build-distros package single src/main/assembly/bin.xml src/main/assembly/src.xml default-cli jar-with-dependencies project +---+ In the above example, you can see several interesting things. First, the main build process will invoke the <<>> mojo during the <<>> phase of the build, and produce both binary and source distribution artifacts using custom assembly descriptors included with the project. Second, all invocations of the assembly plugin should use a <<>> strategy of <<>>. Finally, when the assembly plugin is invoked from the command line, it will build the standard <<>> and <<>> artifacts for the project, and ignore the custom assembly descriptors in <<>>. Now, notice the difference in the way the two execution blocks reference assembly descriptors. One uses custom descriptors via the <<>> section, and the other uses standard descriptors via the <<>> section. These two sections cannot override one another, so it's impossible to setup one section - say, <<>> - in the plugin-level configuration block (to provide CLI access to it, as historical versions of Maven would require), then have the <<>> invocation override it with the custom descriptors specified in the <<>> section. This configuration is not possible in versions of Maven before 2.2.0. **Example: Configuring <<>> to run twice In this scenario, the user wants to run the <<>> mojo twice for his <<>> packaging project. The main reason for this is to provide an entry point into the application that will warn the user if he's using a Java version older than 1.5, then exit gracefully. Without such an entry point, the user would be confronted with a stacktrace in the event he tried to run this application with a 1.4 or older JRE. Therefore, the user needs to compile tha bulk of his application to target the 1.5 Java specification, then compile the rest (the entry point) to target an older specification...say, 1.3. The first execution will specify the <<>> and <<>> values at <<<1.5>>>, and add an <<>> section to avoid compiling the entry point for the application. The second pass will then re-specify <<>> and <<>> to <<<1.3>>>, and basically invert the original <<>> section to be an <<>> section, so as to compile the entry point class. The resulting configuration might look something like this: +---+ maven-compiler-plugin 1.5 1.5 default-compile **/cli/* build-java14-cli compile compile 1.3 1.3 **/cli/* +---+ There are three important things to notice in the above compiler-plugin configuration: # The default <<>> and <<>> compatibility levels are for Java 1.5. This means that the compiler will generate binaries for Java 1.5 from both the main codebase and the test codebase, unless otherwise overridden. # The default pass of the <<>> goal will the <<<**/cli/*>>> path pattern, but will compile everything else in <<>> to run under Java 1.5. # The second pass of the <<>> mojo - in the execution called <<>> - resets the <<>> and <<>> versions to <<<1.3>>>, and inverts the exclude rule from the first pass. This means the second time around, the compiler will produce 1.4-targeted binaries for the classes matching the <<<**/cli/*>>> path pattern. [] Note that prior to Maven 2.2.0, it was much more difficult - if not impossible - to compile different subpaths within your project's codebase to target different Java versions. **Example: Configuring <<>> and <<>> mojos separately Finally, building on our use of the compiler plugin to tease out these different use cases, consider the case where a user wants to target version 1.4 of the Java specification as his runtime platform. However, he still wants the convenience and other advantages to be found in a unit-testing framework like TestNG. This forces the user to configure the <<>> mojo with one set of <<>> and <<>> values - specifically, <<<1.4>>> - and the <<>> mojo with another (<<<1.5>>>). The resulting compiler-plugin configuration might look something like the following: +---+ maven-compiler-plugin default-compile 1.3 1.3 default-testCompile 1.5 1.5 +---+ This example is fairly simple and straightforward. First, the <<>> execution sets the <<>> and <<>> values to <<<1.3>>> to allow older Java versions to run the project. Then, the <<>> execution resets the <<>> and <<>> values to <<<1.5>>>, which enables the project to use tools like TestNG that use annotations. Incidentally, it's perhaps useful to point out that the example above is a little bit contrived; the compiler plugin targets Java 1.3 by default, so the only configuration that's really required is the <<>> execution. The <<>> execution respecifies plugin defaults. The only time this might be useful is when a parent POM defines a plugin-level configuration for <<>> and <<>> that needs to be changed for the purposes of these different compiler executions. This example is meant to be illustrative of the potential for separate configuration of default lifecycle mojos to be found in Maven 2.2.0. Again, the above configuration would not be possible in older versions of Maven. Starting with Maven 2.2.0, these advanced configurations have become a reality.