Step by Step Guide to Developing a Custom Maven Plugin
Maven is a plugin execution framework where plugins do the heavy-lifting in the build process. This article demonstrates how to create a custom maven plugin and use it in a maven project
Maven at its core is a plugin execution framework. Its plugins let users do all the tasks that need to be done in a maven project. Maven provides a set of core plugins to execute the frequently occurring task. For example, compiling the java files, packaging project artifacts or generate Javadocs for the project.
However, the list of core plugins provided by the maven is limited and heavily focused on the common need of the community. Most often, developers need to perform custom tasks that are specific to the project and there is no readily available plugin. To compensate for this limitation, Maven empowers the developer community with tools to develop custom plugins as per the need and let include it in the build process.
This article demonstrates the fundamental concepts of building a custom maven plugin with the utilities provided by maven. As part of this, we will develop a lightweight Maven plugin to convert an XML document to a JSON document.
Setting up the Maven Project
In this section, we will set up a maven project. You need to have either Apache maven installed in your local machine or integrated into your IDE to set up the project. We will develop a simple maven-plugin named xmltojson-maven-plugin.
By convention, core Maven plugins provided by Maven are named as maven-<taskName>-plugin. Maven encourages custom plugins to be named as <taskName>-maven-plugin. Note that using maven-<taskName>-plugin pattern is an infringement of the Apache Maven Trademark
Create a maven project as shown below. You need to select the archetype as maven-archetype-mojo and provide the groupid, artifactid and, version as shown below. I am using Intellij IDEA to develop this project. Similar steps can be followed in Eclipse, STS or in other IDEs as well. Following is the project metadata:
Follow the steps as guided by the IDE and finish the project set up. In the project pom.xml file, you can find the provided project metadata and project packaging type as maven-plugin. This indicates that this maven project is a maven-plugin and needs to be built as a plugin instead of other commonly used packaging types — jar or war. Also, a dependency named maven-plugin-api is added to provide the necessary APIs to develop the custom plugin.
Below is the final pom.xml configuration file. I have added two additional plugins — maven-source-plugin and maven-javadoc-plugin.
Creating the MOJO
MOJO stands for Maven Old Java Object. As a Java developer, you must have heard of POJO — Plain Old Java Object. POJOs generally contain the domain objects of a project with accessors and mutators. In a similar manner, a Mojo is a goal in Maven context, and maven plug-ins consist of any number of goals (Mojos). Mojos can be defined as annotated Java classes or Beanshell script. A Mojo specifies metadata about a goal: a goal name, which phase of the lifecycle it fits into, and the parameters it is expecting.
A mojo is an executable goal in Maven, and a plugin is a distribution of one or more related mojos
A Mojo is annotated by @Mojo annotation and extends the AbstractMojo class as shown in the following code snippet. The below class is self-explanatory with the relevant details. The goal performed by the mojo is provided inside the @Mojo annotation, which in this example is XmlToJson.
The action performed by the mojo is wrapped inside the execute method and the required parameters are obtained through @Parameter annotations. Parameters marked with required as true must be configured while this plugin is in use.
Execute method can potentially throw MojoExecutionException and MojoFailureException. A MojoExecutionException is thrown if an unexpected problem occurs. Throwing this exception causes a “BUILD ERROR” message to be displayed. A MojoFailureExceptionthrown if an unexpected problem such as a compilation failure occurs. Throwing this exception causes a “BUILD FAILURE” message to be displayed in the console.
This completes the development of this demonstration maven plugin. In an enterprise-grade application, custom plugins do many other additional tasks. However, to understand the concept, this example is sufficient.
A maven plugin can consist of many mojos (goals). The execute method is the set of actions performed by a mojo
We have successfully developed a custom maven plugin. But how do we use it? The answer is we need to build this maven project and let maven install the plugin in the repository. By default executing mvn clean install command builds and installs this plugin into the local repository. It will then be available to use in the local machine.
In an enterprise application, you might be deploying the plugin into your enterprise artifactory and made it available to other developers or build environments in a similar manner as other dependencies.
Execute the following command to build the plugin:-
mvn clean install javadoc:javadoc
The above command also generates a nice Javadoc file for the plugin as shown below as we are using maven-javadoc-plugin and the associated goal
We will now create another maven project to use this newly created custom plugin. Create a new maven project and add this plugin in the pom.xml file as shown below.
In this plugin, we are converting an XML document into a JSON file. Hence, we need to provide an XML file. Create an XML file and provide the absolute path in the sourceXmlFilePath parameter. Similarly, provide the absolute path of the destinationJsonFilePath where the JSON file needs to be generated.
Careful observation of the execution section of the plugin reveals that the goal is the same as configured in the @Mojo annotation and the configuration section contains the list of parameters required by the mojo.
Execute the following command to use the plugin:
mvn clean install
You should find a JSON file created in the supplied destinationJsonFilePath location.
Offering developers to develop a custom maven plugin as per the need is an extremely powerful and flexible option. This allows for developing a clean and modular build process. It not only lets us automate the redundant build tasks but also empowers the developers with the power of Java to develop quality plugins.