blob: b152eebc28d1326e47bf315306b7708d8801f70d [file] [log] [blame]
------
Guide to Configuring Plug-ins
------
Jason van Zyl
Vincent Siveton
------
2009-08-26
------
~~ 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 Plug-ins
%{toc|fromDepth=2}
* Introduction
In Maven, there are two kinds of plugins, build and reporting:
* <<Build plugins>> are executed during the build and configured in the <<<\<build/\>>>>
element.
* <<Reporting plugins>> are executed during the site generation and configured in the
<<<\<reporting/\>>>> element.
[]
All plugins should have at least the minimal required
{{{/ref/current/maven-model/maven.html#class_plugin}information}}:
<<<groupId>>>, <<<artifactId>>> and <<<version>>>.
<<Important Note>>: Always define the version of each plugin used to guarantee
build reproducibility. A good practice is to specify each build plugin's version in a <<<\<build\>\<pluginManagement/\>\</build\>>>>
element. Often the \<pluginManagement/\> element is found in the parent POM.
For reporting plugins, specify each version in the <<<\<reporting\>\<plugins/\>\</reporting\>>>> element
(and in the <<<\<build\>\<pluginManagement/\>\</build\>>>> element too).
* {Generic Configuration}
Maven plugins (build and reporting) are configured by specifying a <<<\<configuration\>>>> element where the child elements of the
<<<\<configuration\>>>> element are mapped to fields, or setters, inside your Mojo. (Remember that a plug-in consists of
one or more Mojos where a Mojo maps to a goal.) Say, for example, you have a Mojo that performs a query against
a particular URL, with a specified timeout and list of options. The Mojo might look like the following:
+----+
@Mojo( name = "query" )
public class MyQueryMojo
extends AbstractMojo
{
@Parameter(property = "query.url", required = true)
private String url;
@Parameter(property = "timeout", required = false, defaultValue = "50")
private int timeout;
@Parameter(property = "options")
private String[] options;
public void execute()
throws MojoExecutionException
{
...
}
}
+----+
To configure the Mojo from your POM with the desired URL, timeout and options you might have something like
the following:
+----+
<project>
...
<build>
<plugins>
<plugin>
<artifactId>maven-myquery-plugin</artifactId>
<version>1.0</version>
<configuration>
<url>http://www.foobar.com/query</url>
<timeout>10</timeout>
<options>
<option>one</option>
<option>two</option>
<option>three</option>
</options>
</configuration>
</plugin>
</plugins>
</build>
...
</project>
+----+
The elements in the configuration match the names of the fields in the Mojo.
The mapping is straight forward. The
<<<url>>> element maps to the <<<url>>> field, the <<<timeout>>> element maps to the <<<timeout>>> field, and the
<<<options>>> element maps to the <<<options>>> field. The mapping mechanism can deal with arrays by inspecting
the type of the field and determining if a suitable mapping is possible.
For Mojos that are intended to be executed directly from the CLI, their parameters usually provide a means to be
configured via system properties instead of a <<<\<configuration\>>>> section in the POM. The plugin documentation
for those parameters will list an <expression> that denotes the system properties for the configuration. In the
Mojo above, the parameter <<<url>>> is associated with the expression <<<$\{query.url\}>>>, meaning its value can
be specified by the system property <<<query.url>>> as shown below:
------
mvn myquery:query -Dquery.url=http://maven.apache.org
------
The name of the system property does not necessarily match the name of the mojo parameter. While this is
a rather common practice, you will often notice plugins that employ some prefix for the system properties to avoid
name clashes with other system properties. Though rarely, there are also plugin parameters that (e.g. for historical
reasons) employ system properties which are completely unrelated to the parameter name. So be sure to have a close
look at the plugin documentation.
** {Help Goal}
Most Maven plugins have a <<<help>>> goal that prints a description
of the plugin and its parameters and types. For instance, to see help
for the javadoc goal, type:
------
mvn javadoc:help -Ddetail -Dgoal=javadoc
------
And you will see all parameters for the javadoc:javadoc goal, similar to this
{{{/plugins/maven-javadoc-plugin/javadoc-mojo.html}page}}.
** {Configuring Parameters}
Parameterization of Mojos relies internally on the Plexus Component Configuration API provided by {{{https://github.com/eclipse/sisu.plexus}sisu-plexus}}.
*** {Mapping Value Objects}
Mapping value types, like Boolean or Integer, is very simple. The <<<\<configuration\>>>> element might look like
the following:
+----+
<project>
...
<configuration>
<myString>a string</myString>
<myBoolean>true</myBoolean>
<myInteger>10</myInteger>
<myDouble>1.0</myDouble>
<myFile>c:\temp</myFile>
<myURL>http://maven.apache.org</myURL>
</configuration>
...
</project>
+----+
The detailed type coercion is explained in the table below.
For conversion to primitive types their according {{{https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html}wrapper classes are used and automatically unboxed}}.
*---------------------*--------------*
|| Parameter Class || Conversion from String
*---------------------*--------------*
<<<Boolean>>> | {{{https://docs.oracle.com/javase/8/docs/api/java/lang/Boolean.html#valueOf-java.lang.String-}<<<Boolean.valueOf(String)>>>}}
*---------------------*--------------*
<<<Byte>>> | {{{https://docs.oracle.com/javase/8/docs/api/java/lang/Byte.html#decode-java.lang.String-}<<<Byte.decode(String)>>>}}
*---------------------*--------------*
<<<Character>>> | {{{https://docs.oracle.com/javase/8/docs/api/java/lang/Character.html#valueOf-char-}<<<Character.valueOf(char)>>>}} of the first character in the given string
*---------------------*--------------*
<<<Class>>> | {{{https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#forName-java.lang.String-}<<<Class.forName(String)>>>}}
*---------------------*--------------*
<<<java.util.Date>>> | {{{https://docs.oracle.com/javase/8/docs/api/java/text/DateFormat.html#parse-java.lang.String-}<<<SimpleDateFormat.parse(String)>>>}} for the following patterns: <<<yyyy-MM-dd hh:mm:ss.S a>>>, <<<yyyy-MM-dd hh:mm:ssa>>>, <<<yyyy-MM-dd HH:mm:ss.S>>> or <<<yyyy-MM-dd HH:mm:ss>>>
*---------------------*--------------*
<<<Double>>> | {{{https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html#valueOf-java.lang.String-}<<<Double.valueOf(String)>>>}}
*---------------------*--------------*
<<<Enum>>> | {{{https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html#valueOf-java.lang.String-}<<<Enum.valueOf(String)>>>}}
*---------------------*--------------*
<<<java.io.File>>> | {{{https://docs.oracle.com/javase/8/docs/api/java/io/File.html#File-java.lang.String-}<<<new File(String)>>>}} with the file separators normalized to <<<File.separatorChar>>>. In case the file is relative, is is made absolute by prefixing it with the project's base directory.
*---------------------*--------------*
<<<Float>>> | {{{https://docs.oracle.com/javase/8/docs/api/java/lang/Float.html#valueOf-java.lang.String-}<<<Float.valueOf(String)>>>}}
*---------------------*--------------*
<<<Integer>>> | {{{https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html#decode-java.lang.String-}<<<Integer.decode(String)>>>}}
*---------------------*--------------*
<<<Long>>> | {{{https://docs.oracle.com/javase/8/docs/api/java/lang/Long.html#decode-java.lang.String-}<<<Long.decode(String)>>>}}
*---------------------*--------------*
<<<Short>>> | {{{https://docs.oracle.com/javase/8/docs/api/java/lang/Short.html#decode-java.lang.String-}<<<Short.decode(String)>>>}}
*---------------------*--------------*
<<<String>>> | n/a
*---------------------*--------------*
<<<StringBuffer>>> | {{{https://docs.oracle.com/javase/8/docs/api/java/lang/StringBuffer.html#StringBuffer-java.lang.String-}<<<new StringBuffer(String)>>>}}
*---------------------*--------------*
<<<StringBuilder>>> | {{{https://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html#StringBuilder-java.lang.String-}<<<new StringBuilder(String)>>>}}
*---------------------*--------------*
<<<java.net.URI>>> | {{{https://docs.oracle.com/javase/8/docs/api/java/net/URI.html#URI-java.lang.String-}<<<new URI(String)>>>}}
*---------------------*--------------*
<<<java.net.URL>>> | {{{https://docs.oracle.com/javase/8/docs/api/java/net/URL.html#URL-java.lang.String-}<<<new URL(String)>>>}}
*---------------------*--------------*
*** {Mapping Complex Objects}
Mapping complex types is also fairly straight forward. Let's look at a simple example where we
are trying to map a configuration for Person object. The <<<\<configuration/\>>>> element might look like the
following:
+----+
<project>
...
<configuration>
<person>
<firstName>Jason</firstName>
<lastName>van Zyl</lastName>
</person>
</configuration>
...
</project>
+----+
The rules for mapping complex objects are as follows:
* There must be a private field that corresponds to name of the element being mapped. So in our case the
<<<person>>> element must map to a <<<person>>> field in the mojo.
* The object instantiated must be in the same package as the Mojo itself. So if your mojo is in
<<<com.mycompany.mojo.query>>> then the mapping mechanism will look in that package for an
object named <<<Person>>>. The mechanism capitalizes the first letter of
the element name and uses that to search for the object to instantiate.
* If you wish to have the object to be instantiated live in a different package or have a more
complicated name, specify this using an <<<implementation>>> attribute like the
following:
[]
+----+
<project>
...
<configuration>
<person implementation="com.mycompany.mojo.query.SuperPerson">
<firstName>Jason</firstName>
<lastName>van Zyl</lastName>
</person>
</configuration>
...
</project>
+----+
*** {Mapping Collection Types}
The configuration mapping mechanism can easily deal with most collections so let's go through a few examples
to show you how it's done:
**** {Mapping Collections and Arrays}
Mapping to collections works in much the same way as mapping to arrays. Each item is given in the XML
as dedicated element. The element name does not matter in that case. So if you have a mojo like the following:
+----+
public class MyAnimalMojo
extends AbstractMojo
{
@Parameter(property = "animals")
private List<String> animals;
public void execute()
throws MojoExecutionException
{
...
}
}
+----+
where you have a field named <<<animals>>> then your configuration for the plug-in would look like the following:
+----+
<project>
...
<build>
<plugins>
<plugin>
<artifactId>maven-myanimal-plugin</artifactId>
<version>1.0</version>
<configuration>
<animals>
<animal>cat</animal>
<animal>dog</animal>
<animal>aardvark</animal>
</animals>
</configuration>
</plugin>
</plugins>
</build>
...
</project>
+----+
Where each of the animals listed would be entries in the <<<animals>>> field. Unlike arrays, collections do not necessarily have
a specific component type. In order to derive the type of a collection item, the following strategy is used:
[[1]] If the first item XML element contains an <<<implementation>>> hint attribute, try to load the class with the given fully qualified class name from the attribute value
[[2]] If the first item XML element contains a <<<.>>>, try to load the class with the fully qualified class name given in the element name
[[3]] Try the first item XML element name (with capitalized first letter) as a class in the same package as the mojo/object being
configured
[[4]] Use the parameter type information from either
{{{https://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Field.html#getGenericType()}<<<Field.getGenericType()>>>}} or
{{{https://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Method.html#getGenericParameterTypes()}<<<Method.getGenericParameterTypes()>>>}}
[[5]] If the element has no children, assume its type is <<<String>>>. Otherwise, the configuration will fail.
[]
The following collection implementations are being used when there is no <<<implementation>>> hint attribute in the XML element representing the collection:
*---------------------*--------------*
|| Collection Class || Used for
*---------------------*--------------*
<<<TreeSet>>> | for all types assignable to <<<SortedSet>>>
*---------------------*--------------*
<<<HashSet>>> | for all types assignable to <<<Set>>>
*---------------------*--------------*
<<<ArrayList>>> | for every other <<<Collection>>> type which is not a <<<Map>>>
*---------------------*--------------*
Since Maven 3.3.9 ({{{https://issues.apache.org/jira/browse/MNG-5440}MNG-5440}}), you can list individual items alternatively as comma-separated list in the XML value of animals directly.
This approach is also used if configuring collection/array parameters via command line
The following example is equivalent to the example above:
+----+
<project>
...
<build>
<plugins>
<plugin>
<artifactId>maven-myanimal-plugin</artifactId>
<version>1.0</version>
<configuration>
<animals>cat,dog,aardvark</animals>
</configuration>
</plugin>
</plugins>
</build>
...
</project>
+----+
Each item is mapped again according to the rules of this section depending on the type of the collection/array.
**** {Mapping Maps}
In the same way, you could define maps like the following:
+-----+
...
@Parameter
private Map<String,String> myMap;
...
+-----+
+-----+
<project>
...
<configuration>
<myMap>
<key1>value1</key1>
<key2>value2</key2>
</myMap>
</configuration>
...
</project>
+-----+
Unlike Collections the value type for Maps is always derived from the parameter type information from either
{{{https://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Field.html#getGenericType()}<<<Field.getGenericType()>>>}} or
{{{https://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Method.html#getGenericParameterTypes()}<<<Method.getGenericParameterTypes()>>>}}.
It falls back to <<<String>>>.
The key type must always be <<<String>>>.
In contrast to value objects and collections/arrays there is no string coercion defined for maps, i.e. you cannot give parameters of that type via CLI argument.
The map implementation class is by default <<<TreeMap>>> but can be overridden with an <<<implementation>>> attribute on the XML element representing the map.
**** {Mapping Properties}
Properties should be defined like the following:
+-----+
...
@Parameter
private Properties myProperties;
...
+-----+
+-----+
<project>
...
<configuration>
<myProperties>
<property>
<name>propertyName1</name>
<value>propertyValue1</value>
</property>
<property>
<name>propertyName2</name>
<value>propertyValue2</value>
</property>
</myProperties>
</configuration>
...
</project>
+-----+
In contrast to value objects and collections/arrays there is no string coercion defined for properties, i.e. you cannot give parameters of those type via CLI argument.
* {Configuring Build Plugins}
The following is only to configure Build plugins in the <<<\<build\>>>> element.
** {Using the <<<\<executions\>>>> Tag}
You can also configure a mojo using the <<<\<executions\>>>> tag. This is most commonly used for mojos that are
intended to participate in some phases of the {{{../introduction/introduction-to-the-lifecycle.html}build lifecycle}}.
Using <<<MyQueryMojo>>> as an example, you may have something that will look like:
+----+
<project>
...
<build>
<plugins>
<plugin>
<artifactId>maven-myquery-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<id>execution1</id>
<phase>test</phase>
<configuration>
<url>http://www.foo.com/query</url>
<timeout>10</timeout>
<options>
<option>one</option>
<option>two</option>
<option>three</option>
</options>
</configuration>
<goals>
<goal>query</goal>
</goals>
</execution>
<execution>
<id>execution2</id>
<configuration>
<url>http://www.bar.com/query</url>
<timeout>15</timeout>
<options>
<option>four</option>
<option>five</option>
<option>six</option>
</options>
</configuration>
<goals>
<goal>query</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
</project>
+----+
The first execution with id "execution1" binds this configuration to the test phase. The second execution does not
have a <<<\<phase\>>>> tag, how do you think will this execution behave? Well, goals can have a default phase binding
as discussed further below. If the goal has a default phase binding then it will execute in that phase. But if the
goal is not bound to any lifecycle phase then it simply won't be executed during the build lifecycle.
Note that while execution id's have to be unique among all executions of a single plugin within a POM, they don't
have to be unique across an inheritance hierarchy of POMs. Executions of the same id from different POMs are merged.
The same applies to executions that are defined by profiles.
How about if we have a multiple executions with different phases bound to it?
How do you think will it behave? Let us use the example POM above again, but
this time we shall bind <<<execution2>>> to a phase.
+----+
<project>
...
<build>
<plugins>
<plugin>
...
<executions>
<execution>
<id>execution1</id>
<phase>test</phase>
...
</execution>
<execution>
<id>execution2</id>
<phase>install</phase>
<configuration>
<url>http://www.bar.com/query</url>
<timeout>15</timeout>
<options>
<option>four</option>
<option>five</option>
<option>six</option>
</options>
</configuration>
<goals>
<goal>query</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
</project>
+----+
If there are multiple executions bound to different phases, then the mojo is
executed once for each phase indicated. Meaning, <<<execution1>>> will be
executed applying the configuration setup when the phase of the build is test,
and <<<execution2>>> will be executed applying the configuration setup when
the build phase is already in install.
Now, let us have another mojo example which shows a default lifecycle phase binding.
+----+
@Mojo( name = "query", defaultPhase = LifecyclePhase.PACKAGE )
public class MyBoundQueryMojo
extends AbstractMojo
{
@Parameter(property = "query.url", required = true)
private String url;
@Parameter(property = "timeout", required = false, defaultValue = "50")
private int timeout;
@Parameter(property = "options")
private String[] options;
public void execute()
throws MojoExecutionException
{
...
}
}
+----+
From the above mojo example, <<<MyBoundQueryMojo>>> is by default bound to the package phase
(see the <<<@phase>>> notation). But if we want to execute this mojo during the install
phase and not with package we can rebind this mojo into a new lifecycle phase
using the <<<\<phase\>>>> tag under <<<\<execution\>>>>.
+----+
<project>
...
<build>
<plugins>
<plugin>
<artifactId>maven-myquery-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<id>execution1</id>
<phase>install</phase>
<configuration>
<url>http://www.bar.com/query</url>
<timeout>15</timeout>
<options>
<option>four</option>
<option>five</option>
<option>six</option>
</options>
</configuration>
<goals>
<goal>query</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
</project>
+----+
Now, <<<MyBoundQueryMojo>>> default phase which is package has been overridden by
install phase.
<<Note:>> Configurations inside the <<<\<executions\>>>> element used to differ from those that are outside
<<<\<executions\>>>> in that they could not be used from a direct command line
invocation because they were only applied when the lifecycle phase they were
bound to was invoked. So you had to move a configuration section
outside of the executions section to apply it globally to all invocations
of the plugin.
Since Maven 3.3.1 this is not the case anymore as you can specify on the command line
the execution id for direct plugin goal invocation. Hence if you want to
run the above plugin and it's specific execution1's configuration from the
command-line, you can execute:
------
mvn myquery:query@execution1
------
** {Using the <<<\<dependencies\>>>> Tag}
You could configure the dependencies of the Build plugins, commonly to use a more recent dependency version.
For instance, the Maven Antrun Plugin version 1.2 uses Ant version 1.6.5, if you want to use the latest Ant version
when running this plugin, you need to add <<<\<dependencies\>>>> element like the following:
+----+
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.2</version>
...
<dependencies>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
<version>1.7.1</version>
</dependency>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant-launcher</artifactId>
<version>1.7.1</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
...
</project>
+----+
** {Using the <<<\<inherited\>>>> Tag In Build Plugins}
By default, plugin configuration should be propagated to child POMs, so to break the inheritance, you could use
the <<<\<inherited\>>>> tag:
+----+
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.2</version>
<inherited>false</inherited>
...
</plugin>
</plugins>
</build>
...
</project>
+----+
* {Configuring Reporting Plugins}
The following is only to configure Reporting plugins in the <<<\<reporting\>>>> element.
** {Using the <<<\<reporting\>>>> Tag VS <<<\<build\>>>> Tag}
Configuring a reporting plugin in the <<<\<reporting\>>>> or <<<\<build\>>>> elements in the pom does not exactly have the same results.
[<<<mvn site>>>] Since maven-site-plugin 3.4, it uses the parameters defined in the <<<\<configuration\>>>> element of each reporting Plugin
specified in the <<<\<reporting\>>>> element, in addition to the parameters defined in the
<<<\<configuration\>>>> element of each plugin specified in <<<\<build\>>>> (parameters from <<<\<build\>>>> section were previously ignored).
[<<<mvn aplugin:areportgoal>>>] It <<ignores>> the parameters defined in the <<<\<configuration\>>>> element of each
reporting Plugin specified in the <<<\<reporting\>>>> element; only parameters
defined in the <<<\<configuration\>>>> element of each plugin specified in <<<\<build\>>>> are used.
[]
** {Using the <<<\<reportSets\>>>> Tag}
You can configure a reporting plugin using the <<<\<reportSets\>>>> tag. This is most commonly used to generate
reports selectively when running <<<mvn site>>>. The following will generate only the project team report.
+----+
<project>
...
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>2.1.2</version>
<reportSets>
<reportSet>
<reports>
<report>project-team</report>
</reports>
</reportSet>
</reportSets>
</plugin>
</plugins>
</reporting>
...
</project>
+----+
<<Notes>>:
[[1]] To exclude all reports, you need to use:
+----+
<reportSets>
<reportSet>
<reports/>
</reportSet>
</reportSets>
+----+
[[2]] Refer to each Plugin Documentation (i.e. plugin-info.html) to know the available report goals.
[]
** {Using the <<<\<inherited\>>>> Tag In Reporting Plugins}
Similar to the build plugins, to break the inheritance, you can use the <<<\<inherited\>>>> tag:
+----+
<project>
...
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>2.1.2</version>
<inherited>false</inherited>
</plugin>
</plugins>
</reporting>
...
</project>
+----+