Create a Maven Plugin
Introduction#
Maven allows you to implement and use custom plugins. These plugins allow additional behaviour to be bound to any phase of the Maven lifecycle.
Each Maven goal is created by implementing a MOJO (Maven Ordinary Java Object): a Java class implemented with annotations that describes how to invoke it.
The goal prefix of a plugin is derived from its artifact name. An artifact hello-world-plugin
creates a goal prefix hello-world
. The hello
goal can then be run with mvn hello-world:hello
.
Remarks#
A Maven plugin is a JAR containing a maven/plugins.xml
that describes the plugin metadata. This file is generated by the maven-plugin-plugin
.
Declaring a Maven artifact as a Maven plugin
An artifact built by Maven can be declared as a Maven plugin by specifying the packaging as maven-plugin
in the pom.xml
.
<packaging>maven-plugin</packaging>
You need to declare a dependency on the plugin API and annotations.
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>3.3.9</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.5</version>
<scope>provided</scope>
</dependency>
You need to add a plugin to generate the metadata.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<version>3.5</version>
</plugin>
Creating a goal
Goals are implemented by creating a MOJO. This is a class file annotated with annotations from maven-plugin-annotations
.
@Mojo(name = "hello")
public final class HelloWorldMojo extends AbstractMojo {
public void execute() throws MojoExecutionException, MojoFailureException {
getLog().info("Hello world");
}
}
Using plugin configuration
Plugins can be configured by annotating fields with @Parameter
. The MOJO is then injected with the configuration.
@Mojo(name = "greet")
public final class GreetMojo extends AbstractMojo {
@Parameter(required = true)
public String name;
public void execute() throws MojoExecutionException, MojoFailureException {
getLog().info("Hello " + name);
}
}
The name
parameter can be configured in the POM:
<plugin>
<groupId>com.mattunderscore</groupId>
<artifactId>hello-world-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<configuration>
<name>Matt</name>
</configuration>
</plugin>
If the greet
goal is run as a standalone goal the name
parameter can be defined as property on the command line:
mvn <plugin name>:greet -Dname=Geri
Accessing the project information
The plugin can, among others, access information about the current Maven project being built.
@Mojo(name = "project")
public final class ProjectNameMojo extends AbstractMojo {
@Parameter(defaultValue = "${project}", readonly = true, required = true)
private MavenProject project;
public void execute() throws MojoExecutionException, MojoFailureException {
getLog().info("Hello, this is " + project.getName());
}
}
The above example would print in the console the name of the Maven project it is run on, which is specified in the <project>/<name>
element of its POM.
The MavenProject
class used in the plugin requires a dependency of maven-core
with a (default) compile
scope in the plugin’s POM:
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>3.3.9</version>
</dependency>
Furthermore, using annotations requires the following dependency in the plugin’s POM:
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.5</version>
<scope>provided</scope> <!-- annotations are needed only to build the plugin -->
</dependency>
Declare a default phase for a goal
@Mojo(name = "hi", defaultPhase = LifecyclePhase.COMPILE)
Get the build directory as a file
@Parameter(defaultValue = "${project.build.directory}")
private File buildDirectory;