Chapter 11: Writing Plugins | Maven: The Complete Reference

Writing Plugins

11.1. Introduction

While this chapter covers an advanced topic, don’t let the idea of writing a Maven plugin intimidate you. For all of the theory and complexity of this tool, the fundamental concepts are easy to understand and the mechanics of writing a plugin are straightforward. After you read this chapter, you will have a better grasp of what is involved in creating a Maven plugin.

11.2. Programming Maven

Most of this book has dealt with using Maven, and for a book on Maven, you haven’t seen too many code examples dealing with Maven customization. In fact, you haven’t yet seen any. This is by design, 99 out of 100 Maven users will never need to write a custom plugin to customize Maven; there is an abundance of configurable plugins, and unless your project has particularly unique requirements, you will have to work to find a reason to write a new plugin. An even smaller percentage of people who end up writing custom plugins will ever need to crack open the source code for Maven and customize a core Maven component. If you really need to customize the behavior of Maven, then you would write a plugin. Modifying the core Maven code is as far out of scope for most developers as modifying the TCP/IP stack on an operating system, it is that abstract for most Maven users.

On the other hand, if you are going to start writing a custom plugin, you are going to have to learn a bit about the internals of Maven: How does it manage software components? What is a Plugin? How can I customize the lifecycle? This section answers some of those questions, and it introduces a few concepts at the core of Maven’s design. Learning how to write a custom Maven plugin is the gateway to customizing Maven itself. If you were wondering how to start understanding the code behind Maven, you’ve found the proper starting line.

11.2.1. What is Inversion of Control?

At the heart of Maven is an Inversion of Control (IoC) container named Plexus. What does it do? It is a system for managing and relating components. [...] Your application’s code isn’t responsible for managing the state of components, Plexus is. Even though it sounds very cheesy, when you start up Maven, it is starting Plexus and managing a system of related components just like your stereo system.

11.2.2. Introduction to Plexus

The most important feature of an IoC container implemented in Java is a mechanism called dependency injection. [...] In the case of Plexus, system components are defined with an XML document that is found in META-INF/plexus/components.xml.

11.2.3. Why Plexus?

Spring does happen to be the most popular IoC container at the moment, and there’s a good argument to be made that it has affected the Java "ecosystem" for the better. [...] Just because Maven is based on Plexus doesn’t mean that the Maven community is "anti-Spring" (we’ve included a whole chapter with a Spring example in this book).

11.2.4. What is a Plugin?

A Maven Plugin is a Maven artifact which contains a plugin descriptor and one or more Mojos. A Mojo can be thought of as a goal in Maven, and every goal corresponds to a Mojo. [...]

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. [...]

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.

groupId, artifactId, version. As with everything else in Maven, plugins need to have a unique set of coordinates.

goalPrefix. This element controls the prefix used to reference goals in a particular plugin.

11.3.2. Mojo Configuration

Next is the declaration of each Mojo. Each mojo element contains the following configuration elements:

goal: This is the name of the goal.

description: Contains a short description of the goal to display to the user.

phase: If you don’t bind this goal to a specific phase, this element defines the default phase for this 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.

11.4. Writing a Custom Plugin

When you write a custom plugin, you are going to be writing a series of Mojos (goals). Every Mojo is a single Java class which contains [...]

11.4.1. Creating a Plugin Project

To create a plugin project, you should use the Maven Archetype plugin. [...]

11.4.2. A Simple Java Mojo

In this chapter, we’re going to introduce a Maven Mojo written in Java. Each Mojo in your project is going to implement the org.apache.maven.plugin.Mojo interface.

11.4.3. Configuring a Plugin Prefix

Specifying the groupId, artifactId, version, and goal on the command-line is cumbersome. [...]

11.4.4. Logging from a Plugin

Maven takes care of connecting your Mojo to a logging provider by calling setLog() prior to the execution of your Mojo. [...]

11.4.5. Mojo Class Annotations

EchoMojo specifies the @goal annotation, here is a list of other annotations you can place on your Mojo implementation.

11.5. Mojo Parameters

Just as important as the execute() method and the Mojo annotations, a Mojo is configured via parameters. [...]

11.5.1. Supplying Values for Mojo Parameters

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

11.5.2. Multi-valued Mojo Parameters

Plugins can have parameters which accept more than one value. [...]

11.5.3. Depending on Plexus Components

A Mojo is a component managed by an IoC container called Plexus. [...]

11.5.4. Mojo Parameter Annotations

Unless you insist on writing your Plugin descriptors by hand, you’ll never have to write that XML. [...]

11.6. Plugins and the Maven Lifecycle

In this section, you are going to learn how you can customize the lifecycle from a custom Maven plugin. [...]

11.6.1. Executing a Parallel Lifecycle

Let’s assume you write some goal that depends on the output from a previous build. [...]

11.6.2. Creating a Custom Lifecycle

A custom lifecycle must be packaged in the plugin under the META-INF/maven/lifecycle.xml file. [...]

11.6.3. Overriding the Default Lifecycle

Once you’ve created your own lifecycle and spawned it from a Mojo. [...]