Maven: The Complete Reference

11.5. Mojo Parameters

Just as important as the execute() method and the Mojo annotations, a Mojo is configured via parameters. This section deals with some configuration and topics surrounding Mojo parameters.

11.5.1. Supplying Values for Mojo Parameters

In EchoMojo we declared the message parameter with the following annotations:

/**
* Any Object to print out.
* @parameter
*   expression="${echo.message}"
*   default-value="Hello Maven World"
*/
private Object message;

The default expression for this parameter is ${echo.message}, this means that Maven will try to use the value of the echo.message property to set the value for message. If the value of the echo.message property is null, the default-value attribute of the @parameter annotation will be used instead. Instead of using the echo.message property, we can configure a value for the message parameter of the EchoMojo directly in a project’s POM.

There are a few ways to populate the message parameter in the EchoMojo. First we can pass in a value from the command-line like this (assuming that you’ve added org.sonatype.mavenbook.plugins to your pluginGroups):

$ mvn first:echo -Decho.message="Hello Everybody"

We could also specify the value of this message parameter, by setting a property in our POM or in our settings.xml.

<project>
    ...
    <properties>
        <echo.message>Hello Everybody</echo.message>
    </properties>
</project>

This parameter could also be configured directly as a configuration value for the plugin. If we wanted to customize the message parameter directly, we could use the following build configuration. The following configuration bypasses the echo.message property and populates the Mojo parameter in plugin configuration.

<project>
    ...
    <build>
        <plugins>
            <plugin>
                <groupId>org.sonatype.mavenbook.plugins</groupId>
                <artifactId>first-maven-plugin</artifactId>
                <version>1.0-SNAPSHOT</version>
                <configuration>
                    <message>Hello Everybody!</message>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

If we wanted to run the EchoMojo twice at difference phases in a lifecycle, and we wanted to customize the message parameter for each execution separately, we could configure the parameter value at the execution level in a POM like this:

<build>
    <plugins>
        <plugin>
            <groupId>org.sonatype.mavenbook.plugins</groupId>
            <artifactId>first-maven-plugin</artifactId>
            <version>1.0-SNAPSHOT</version>
            <executions>
                <execution>
                    <id>first-execution</id>
                    <phase>generate-resources</phase>
                    <goals>
                        <goal>echo</goal>
                    </goals>
                    <configuration>
                        <message>The Eagle has Landed!</message>
                    </configuration>
                </execution>
                <execution>
                    <id>second-execution</id>
                    <phase>validate</phase>
                    <goals>
                        <goal>echo</goal>
                    </goals>
                    <configuration>
                        <message>${project.version}</message>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

While this last configuration example seems very verbose, it illustrates the flexibility of Maven. In the previous configuration example, you’ve bound the EchoMojo to both the validate and generate-resources phases in the default Maven lifecycle. The first execution is bound to generate-resources, it supplies a string value to the message parameter of "The Eagle has Landed!". The second execution is bound to the validate phase, it supplies a property reference to 1.0. When you run mvn install for his project, you’ll see that the first:echo goal executes twice and prints out two different messages.

11.5.2. Multi-valued Mojo Parameters

Plugins can have parameters which accept more than one value. Take a look at the ZipMojo shown in A Plugin with Multi-valued Parameters. Both the includes and excludes parameters are multivalued String arrays which specify the inclusion and exclusion patterns for a component that creates a ZIP file.

A Plugin with Multi-valued Parameters. 

package org.sonatype.mavenbook.plugins

/**
* Zips up the output directory.
* @goal zip
* @phase package
*/
public class ZipMojo extends AbstractMojo
{
/**
* The Zip archiver.
* @parameter \
expression="${component.org.codehaus.plexus.archiver.Archiver#zip}"
*/
private ZipArchiver zipArchiver;

/**
* Directory containing the build files.
* @parameter expression="${project.build.directory}"
*/
private File buildDirectory;

/**
* Base directory of the project.
* @parameter expression="${basedir}"
*/
private File baseDirectory;

/**
* A set of file patterns to include in the zip.
* @parameter alias="includes"
*/
private String[] mIncludes;

/**
* A set of file patterns to exclude from the zip.
* @parameter alias="excludes"
*/
private String[] mExcludes;

public void setExcludes( String[] excludes ) { mExcludes = excludes; }

public void setIncludes( String[] includes ) { mIncludes = includes; }

public void execute()
throws MojoExecutionException
{
try {
zipArchiver.addDirectory( buildDirectory, includes, excludes );
zipArchiver.setDestFile( new File( baseDirectory, "output.zip" ) );
zipArchiver.createArchive();
} catch( Exception e ) {
throw new MojoExecutionException( "Could not zip", e );
}
}
}

To configure a multi-valued Mojo parameter, you use a series of elements for each value. If the name of the multi-valued parameter is includes, you would use an element includes with child elements include. If the multi-valued parameter is excludes, you would use an element excludes with child elements exclude. To configure the ZipMojo to ignore all files ending in .txt and all files ending in a tilde, you would use the following plugin configuration.

<project>
    ...
    <build>
        <plugins>
            <plugin>
                <groupId>org.sonatype.mavenbook.plugins</groupId>
                <artifactId>zip-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>**/*.txt</exclude>
                        <exclude>**/*~</exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

11.5.3. Depending on Plexus Components

A Mojo is a component managed by an IoC container called Plexus. A Mojo can depend on other components managed by Plexus by declaring a Mojo parameter and using the @parameter or the @component annotation. A Plugin with Multi-valued Parameters shows a ZipMojo which depends on a Plexus component using the @parameter annotation, this dependency could be declared using the @component annotation.

Depending on a Plexus Component. 

/**
* The Zip archiver.
* @component role="org.codehaus.plexus.archiver.Archiver" roleHint="zip"
*/
private ZipArchiver zipArchiver;

When Maven instantiates this Mojo, it will then attempt to retrieve the Plexus component with the specified role and role hint. In this example, the Mojo will be related to a ZipArchiver component which will allow the ZipMojo to create a ZIP file.

11.5.4. Mojo Parameter Annotations

Unless you insist on writing your Plugin descriptors by hand, you’ll never have to write that XML. Instead, the Maven Plugin Plugin has a plugin:descriptor goal bound to the generate-resources phase. This goal generates the plugin descriptor from annotations on your Mojo. To configure a Mojo parameter, you should use the following annotations on either the private member variables for each of your Mojo’s parameters on public setter methods for each property. The most common convention for Maven plugins is to annotate private member variables directly.

@parameter [alias="someAlias"] [expression="${someExpression}"] [default-value="value"]
Marks a private field (or a setter method) as a parameter. The alias provides the name of the parameter. If alias is omitted, Maven will use the name of the variable as the parameter name. The expression is an expression that Maven will evaluate to obtain a value. Usually the expression is a property reference like ${echo.message}. default-value is the value that this Mojo will use if no value can be derived from the expression or if a value was not explicitly supplied via plugin configuration in a POM.
@required
If this annotation is present, a valid value for this parameter is required prior to Mojo execution. If Maven tries to execute this Mojo and the parameter has a null value, Maven will throw an error when it tries to execute this goal.
@readonly
If this annotation is present, the user cannot directly configure this parameter in the POM. You would use this annotation with the expression attribute of the parameter annotation. For example, if you wanted to make sure that a particular parameter always had the value of the finalName POM property, you would list an expression of ${build.finalName} and then add the @readOnly annotation. If this were the case, the user could only change the value of this parameter by changing the value of finalName in the POM.
@component
Tells Maven to populate a field with a Plexus Component. A valid value for the @component annotation would be:
@component role="org.codehaus.plexus.archiver.Archiver" roleHint="zip"

This would have the effect of retrieving the ZipArchiver from Plexus. The ZipArchiver is the Archiver which corresponds to the role hint zip. Instead of component, you could also use the @parameter annotation with an expression attribute of:

@parameter expression="'+++${component.org.codehaus.plexus.archiver.Archiver#zip}+++'"

While the two annotations are effectively the same, the @component annotation is the preferred way to configure dependencies on Plexus components.

@deprecated
The parameter will be deprecated. Users can continue configuring this parameter, but a warning message will be displayed.