Maven: The Complete Reference

11.3. Plugin Descriptor

A Maven plugin contains a road-map for Maven that tells Maven about the various Mojos and plugin configuration. This plugin descriptor is present in the plugin JAR file in META-INF/maven/plugin.xml. When Maven loads a plugin, it reads this XML file, instantiates and configures plugin objects to make the Mojos contained in a plugin available to Maven.

When you are writing custom Maven plugins, you will almost never need to think about writing a plugin descriptor. In Chapter 4, The Build Lifecycle, the lifecycle goals bound to the maven-plugin packaging type show that the plugin:descriptor goal is bound to the generate-resources phase. This goal generates a plugin descriptor off of the annotations present in a plugin’s source code. Later in this chapter, you will see how Mojos are annotated, and you will also see how the values in these annotations end up in the META-INF/maven/plugin.xml file.

Plugin Descriptor shows a plugin descriptor for the Maven Zip Plugin. This plugin is a contrived plugin that simply zips up the output directory and produces an archive. Normally, you wouldn’t need to write a custom plugin to create an archive from Maven, you could simply use the Maven Assembly Plugin which is capable of producing a distribution archive in multiple formats. Read through the following plugin descriptor to get an idea of the content it contains.

Plugin Descriptor. 

<plugin>
    <description></description>
    <groupId>com.training.plugins</groupId>
    <artifactId>maven-zip-plugin</artifactId>
    <version>1-SNAPSHOT</version>
    <goalPrefix>zip</goalPrefix>
    <isolatedRealm>false</isolatedRealm>
    <inheritedByDefault>true</inheritedByDefault>
    <mojos>
        <mojo>
            <goal>zip</goal>
            <description>Zips up the output directory.</description>
            <requiresDirectInvocation>false</requiresDirectInvocation>
            <requiresProject>true</requiresProject>
            <requiresReports>false</requiresReports>
            <aggregator>false</aggregator>
            <requiresOnline>false</requiresOnline>
            <inheritedByDefault>true</inheritedByDefault>
            <phase>package</phase>
            <implementation>com.training.plugins.ZipMojo</implementation>
            <language>java</language>
            <instantiationStrategy>per-lookup</instantiationStrategy>
            <executionStrategy>once-per-session</executionStrategy>
            <parameters>
                <parameter>
                    <name>baseDirectory</name>
                    <type>java.io.File</type>
                    <required>false</required>
                    <editable>true</editable>
                    <description>Base directory of the project.</description>
                </parameter>
                <parameter>
                    <name>buildDirectory</name>
                    <type>java.io.File</type>
                    <required>false</required>
                    <editable>true</editable>
                    <description>Directory containing the build files.</description>
                </parameter>
            </parameters>
            <configuration>
                <buildDirectory implementation="java.io.File">
                    ${project.build.directory}</buildDirectory>
                <baseDirectory implementation="java.io.File">
                    ${basedir}</baseDirectory>
            </configuration>
            <requirements>
                <requirement>
                    <role>org.codehaus.plexus.archiver.Archiver</role>
                    <role-hint>zip</role-hint>
                    <field-name>zipArchiver</field-name>
                </requirement>
            </requirements>
        </mojo>
    </mojos>
    <dependencies>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-io</artifactId>
        <version>1.3.2</version>
    </dependencies>
</plugin>

There are three parts to a plugin descriptor: the top-level configuration of the plugin which contains elements like groupId and artifactId, the declaration of mojos, and the declaration of dependencies. Let’s examine each of these sections in more detail.

11.3.1. Top-level Plugin Descriptor Elements

The top-level configuration values in the plugin element are:

description
This element contains a short description of the plugin. In the case of the Zip plugin, this description is empty.
groupId, artifactId, version
As with everything else in Maven, plugins need to have a unique set of coordinates. The groupId, artifactId, and version are used to locate the plugin artifact in a Maven repository.
goalPrefix
This element controls the prefix used to reference goals in a particular plugin. If you were to look at the Compiler plugin’s descriptor you would see that goalPrefix has a value of compiler. If you look at the descriptor for the Jar plugin, it would have a goalPrefix of jar. It is important that you choose a distinct goal prefix for your custom plugin.
isolatedRealm (deprecated)
This is a legacy property which is no longer used by Maven. It is still present in the system to provide backwards compatibility with older plugins. Earlier versions of Maven used to provide a mechanism to load a plugin’s dependencies in an isolated ClassLoader. Maven makes extensive use of a project called ClassWorlds from the Codehaus community to create hierarchies of ClassLoader objects which are modeled by a ClassRealm object. Feel free to ignore this property and always set it to false.
inheritedByDefault
If inheritedByDefault is set to true, any mojo in this plugin which is configured in a parent project will be configured in a child project. If you configure a mojo to execute during a specific phase in a parent project and the Plugin has inheritedByDefault set to true, this execution will be inherited by the child project. If inheritedByDefault is not set to true, then an goal execution defined in a parent project will not be inherited by a child project.

11.3.2. Mojo Configuration

Next is the declaration of each Mojo. The plugin element contains an element named mojos which contains a mojo element for each mojo present in the Plugin. Each mojo element contains the following configuration elements:

goal
This is the name of the goal. If you were running the compiler:compile goal, then compiler is the plugin’s goalPrefix and compile would be the name of the goal.
description
This contains a short description of the goal to display to the user when they use the Help plugin to generate plugin documentation.
requiresDirectInvocation
If you set this to true, the goal can only be executed if it is explicitly executed from the command-line by the user. If someone tries to bind this goal to a lifecycle phase in a POM, Maven will print an error message. The default for this element is false. <!--TODO: Might want some justification.-→
requiresProject
Specifies that a given goal cannot be executed outside of a project. The goal requires a project with a POM. The default value for requiresProject is true.
requiresReports
If you were creating a plugin that relies on the presence of reports, you would need to set requiresReports to true. For example, if you were writing a plugin to aggregate information from a number of reports, you would set requiresReports to true. The default for this element is false.
aggregator
A Mojo descriptor with aggregator set to true is supposed to only run once during the execution of Maven, it was created to give plugin developers the ability to summarize the output of a series of builds; for example, to create a plugin that summarizes a report across all projects included in a build. A goal with aggregator set to true should only be run against the top-level project in a Maven build. The default value of aggregator is false.
requiresOnline
Specifies that a given goal cannot be executed if Maven is running in offline mode (-o command-line option). If a goal depends on a network resource, you would specify a value of true for this element and Maven would print an error if the goal was executed in offline mode. The default for requiresOnline is false.
inheritedByDefault
If inheritedByDefault is set to true, a mojo which is configured in a parent project will be configured in a child project. If you configure a mojo to execute during a specific phase in a parent project and the Mojo descriptor has inheritedByDefault set to true, this execution will be inherited by the child project. If inheritedByDefault is not set to true, then a goal execution defined in a parent project will not be inherited by a child project.
phase
If you don’t bind this goal to a specific phase, this element defines the default phase for this mojo. If you do not specify a phase element, Maven will require the user to explicitly specify a phase in a POM.
implementation
This element tells Maven which class to instantiate for this Mojo. This is a Plexus component property (defined in Plexus ComponentDescriptor).
language
The default language for a Maven Mojo is Java. This controls the Plexus ComponentFactory used to create instances of this Mojo component. This chapter focuses on writing Maven plugins in Java, but you can also write Maven in a number of alternative languages such as Groovy, Beanshell, and Ruby. If you were writing a plugin in one of these languages you would use a language element value other than java.
instantiationStrategy
This property is a Plexus component configuration property, it tells Plexus how to create and manage instances of the component. In Maven, all mojos are going to be configured with an instantiationStrategy of per-lookup; a new instance of the component (mojo) is created every time it is retrieved from Plexus.
executionStrategy
The execution strategy tells Maven when and how to execute a Mojo. The valid values are once-per-session and always. Note: This particular property doesn’t do a thing, it is a hold over from an early design of Maven. This property is slated for deprecation in a future release of Maven.
parameters
This element describes all of the parameters for this Mojo. What’s the name of the parameter? What is the type of parameter? Is it required? Each parameter has the following elements:
name
Is the name of the parameter (i.e. baseDirectory)
type
This is the type (Java class) of the parameters (i.e. java.io.File)
required
Is the parameter required? If true, the parameter must be non-null when the goal is executed.
editable
If a parameter is not editable (if editable is set to false), then the value of the parameter cannot be set in the POM. For example, if the plugin descriptor defines the value of buildDirectory to be ${basedir} in the descriptor, a POM cannot override this value to be another value in a POM.
description
A short description to use when generating plugin documentation (using the Help Plugin)
configuration
This element provides default values for all of the Mojo’s parameters using Maven property notation. This example provides a default value for the baseDir Mojo parameter and the buildDirectory Mojo parameter. In the parameter element, the implementation specifies the type of the parameter (in this case java.io.File), the value in the parameter element contains either a hard-coded default or a Maven property reference.
requirements
This is where the descriptor gets interesting. A Mojo is a component that is managed by Plexus, and, because of this, it has the opportunity to reference other components managed by Plexus. This element allows you to define dependencies on other components in Plexus.

While you should know how to read a Plugin Descriptor, you will almost never need to write one of these descriptor files by hand. Plugin Descriptor files are generated automatically off of a set of annotations in the source for a Mojo.

11.3.3. Plugin Dependencies

Lastly, the plugin descriptor declares a set of dependencies just like a Maven project. When Maven uses a plugin, it will download any required dependencies before it attempts to execute a goal from this plugin. In this example, the plugin depends on Jakarta Commons IO version 1.3.2.