Maven - Plugin Development

About

How to develop a maven plugin with Java Annotation. (It's important for the configuration).

The code result of this tutorial is on github. helloworld-maven-plugin

Requirements

This section lists all the things a developer needs to take into account in order to respect the maven plugin mechanism.

Name Convention

<pluginName>-maven-plugin

In this case

hello-maven-plugin

That you get back in the pom.xml. Example: pom.xml

<artifactId>hello-maven-plugin</artifactId>

Packaging

The packaging must be defined in the pom.xml to maven-plugin. Example: pom.xml

<packaging>maven-plugin</packaging>

There are few goals which are defined with the maven-plugin packaging as part of a standard build lifecycle:

Goal Description
compile Compiles the Java code for the plugin and builds the plugin descriptor
test Runs the plugin's unit tests
package Builds the plugin jar
install Installs the plugin jar in the local repository
deploy Deploys the plugin jar to the remote repository

Annotation

Mojo (Plugin Registration)

When processing the source tree to find plugin, plugin-tools registers classes as plugin with either:

Any class with this annotation are included in the plugin configuration file.

Example: GreetingMojoWithParameters.java

/**
 * Says "Hi" to a user given in a parameters
 */
@Mojo(name = "sayhiTo")
public class GreetingMojoWithParameters extends AbstractMojo 

Parameters

From GreetingMojoWithParameters.java

/**
 * The user to display.
 * The parameter annotation identifies the variable as a mojo parameter.
 *
 */
@Parameter( property = "sayhiTo.user", defaultValue = "World" )
private String user;

where:

  • The default value can include expressions which reference the project, such as “${project.version}”. See PluginParameterExpressionEvaluator
  • The property parameter can be used to allow configuration of the mojo parameter from the command line by referencing a system property that the user sets via the -D option.

Interface

A plugin:

This interface defines:

The Execution contract

The execute() method: no parameters, void return type,

public void execute() throws MojoExecutionException {
        getLog().info("Hello, "+this.user+"!");
}

The Exception mechanism

The execute() method may throw only a MojoExecutionException and its derivatives.

public void execute() throws MojoExecutionException {
        getLog().info("Hello, "+this.user+"!");
}

The execute method can throw two exceptions:

  • MojoExecutionException if an unexpected problem occurs. Throwing this exception causes a “BUILD ERROR” message to be displayed.
  • MojoFailureException if an expected problem (such as a compilation failure) occurs. Throwing this exception causes a “BUILD FAILURE” message to be displayed.

The (Log|Result|Feedback) mechanism

Through the function void setLog( org.apache.maven.plugin.logging.Log ), you may inject a logging mechanism

The getLog method (defined in AbstractMojo) returns a log4j-like logger object which allows plugins to create messages at levels of “debug”, “info”, “warn”, and “error”.

public void execute() throws MojoExecutionException {
        getLog().info("Hello, "+this.user+"!");
}

Descriptor

Each Plugin (a packaged set of Mojos) must provide a descriptor (also known as plugin configuration file) called plugin.xml under the path META-INF/maven inside the Plugin jar file that provides metadata about the parameters and other component requirements.

See plugin.xml for its description.

This descriptor is generally generated from plugin sources, using maven-plugin-plugin in the target/classes/META-INF/maven directory.

In the pom.xml. Example: pom.xml

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-plugin-plugin</artifactId>
	<version>3.4</version>
	<configuration>
		<goalPrefix>hello</goalPrefix>
		<skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
	</configuration>
	<executions>
		<execution>
			<id>mojo-descriptor</id>
			<goals>
				<goal>descriptor</goal>
			</goals>
			<phase>process-classes</phase>
		</execution>
		<!-- if you want to generate help goal -->
		<execution>
			<id>help-goal</id>
			<goals>
				<goal>helpmojo</goal>
			</goals>
		</execution>
	</executions>
</plugin>

After calling the package phase, you will find it in the target/classes/META-INF/maven directory.

Archetype Template

You can create your project from scratch or your can use a template (an archetype).

Maven provides the maven-archetype-plugin. See maven-archetype-plugin.

The easiest way is to call the goal archetype:generate and to answer interactively the questions.

mvn archetype:generate    # archetype:create is deprecated since maven 3.0.5 

Then you can filter by artifactId (GroupId doesn't work for me) by entering: maven-archetype-plugin.

Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): : maven-archetype-plugin
Choose archetype:
1: remote -> org.apache.maven.archetypes:maven-archetype-plugin (An archetype which contains a sample Maven plugin.)
2: remote -> org.apache.maven.archetypes:maven-archetype-plugin-site (An archetype which contains a sample Maven plugin site. This archetype can be
    existing Maven plugin project.)
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): : 1

Otherwise, you can call directly the archetypeArtifactId

mvn archetype:generate    # archetype:create is deprecated since maven 3.0.5 
  -DgroupId=sample.plugin 
  -DartifactId=hello-maven-plugin 
  -DarchetypeGroupId=org.apache.maven.archetypes 
  -DarchetypeArtifactId=maven-archetype-plugin

Unfortunately, the generated project contains a deprecated mojo and a pom.xml that doesn't find the maven-invoker-plugin.

Run your plugin

A goal

Without parameters

mvn sample.plugin:hello-maven-plugin:1.0-SNAPSHOT:sayhi
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Sample Parameter-less Maven Plugin 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- hello-maven-plugin:1.0-SNAPSHOT:sayhi (default-cli) @ hello-maven-plugin ---
[INFO] Hello, world.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.371 s
[INFO] Finished at: 2015-12-15T13:29:01+01:00
[INFO] Final Memory: 8M/309M
[INFO] ------------------------------------------------------------------------

With parameters

if the plugin group id is configured to sample.plugin.

mvn hello:sayhiTo -DsayhiTo.user=Nico
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Sample Parameter-less Maven Plugin 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- hello-maven-plugin:1.0-SNAPSHOT:sayhiTo (default-cli) @ hello-maven-plugin ---
[INFO] Hello, Nico!
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.309 s
[INFO] Finished at: 2015-12-15T17:42:44+01:00
[INFO] Final Memory: 8M/309M
[INFO] ------------------------------------------------------------------------

From a pom.xml:

<plugin>
	<groupId>sample.plugin</groupId>
	<artifactId>hello-maven-plugin</artifactId>
	<version>1.0-SNAPSHOT</version>
	<executions>
		<execution>
			<id>execution1</id>
			<configuration>
				<user>Nico</user>
			</configuration>
			<goals>
				<goal>sayhiTo</goal>
			</goals>
		</execution>
	</executions>
</plugin>

Plugin Help

mvn sample.plugin:hello-maven-plugin:1.0-SNAPSHOT:help
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Sample Parameter-less Maven Plugin 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- hello-maven-plugin:1.0-SNAPSHOT:help (default-cli) @ hello-maven-plugin ---
[INFO] Sample Parameter-less Maven Plugin 1.0-SNAPSHOT


This plugin has 3 goals:

hello:help
  Display help information on hello-maven-plugin.
  Call mvn hello:help -Ddetail=true -Dgoal=<goal-name> to display parameter
  details.

hello:sayhi
  Says 'Hi' to the user.

hello:sayhiTo
  Says 'Hi' to a user given in a parameters


[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.350 s
[INFO] Finished at: 2015-12-15T13:30:22+01:00
[INFO] Final Memory: 8M/309M
[INFO] ------------------------------------------------------------------------

IDE

Idea

to configure the javadoc annotations as live templates, download this file, and place it in $USER_HOME/.IntelliJIdea/config/templates

Support

No mojos are created in the plugin descriptor

The mojos are found but they are not added to the descriptor. This may come from the fact that you're directory tree doesn't follow the maven standard.

See also: with Java annotations support added in Maven Plugin Tools 3.0, descriptor cannot be generated before compilation

Documentation / Reference


Powered by ComboStrap