Beginner's Guide to Creating a Maven Plugin
In this article, we'll learn how to build a Maven plugin and test it. Read on to get started!
Join the DZone community and get the full member experience.
Join For FreeMaven plugins are software components that allow for the reuse of common build logic across multiple projects or modules. In this article, I would like to demonstrate how to build a Maven plugin and test it.
Creating a Maven Plugin Project
This article assumes that you have already installed Maven. In this article, I am going to create a small plugin which creates a zip file for multiple files listed in a directory. Create a Maven project using the command maven-archetype-mojo
.
Provide a suitable GroupId and ArtifactId. Make sure your GroupId and ArtifactId follow the guidelines provided here. This is important if you want to publish your plugin to a Maven Central repository.
Continue by clicking Next. Once you click Finish, you will see that a POM file and a Mojo
class have been created. Mojo
is a goal in Maven. We can define metadata such as the goal's name, its lifecycle phase, and so on within a Mojo
class.
In pom.xml, make sure to add the following plugin to be able to use Maven plugin annotations.
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.6.0</version>
<scope>provided</scope>
</dependency>
Add the Maven project plugin. I will explain the purpose of this plugin in a bit.
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-project</artifactId>
<version>2.2.1</version>
</dependency>
This Mojo
class always extends an abstract class, AbstractMojo, which provides the infrastructure to implement a plugin.
When we create a Maven project in an IDE, the default name for the Mojo
class will be something like MyMojo
. I have renamed it to FileZipMojo
since our plugin will be about creating a zip file.
@Mojo (name = "zip", defaultPhase = LifecyclePhase.GENERATE_RESOURCES)
public class FileZipMojo extends AbstractMojo {
The goal name for this plugin is "zip" and lifecycle phase is GENERATE_RESOURCES because it generates a zip file. I will show you how to use it in a bit later in this article.
In the next step, I will define three parameters required for our plugin execution.
@Parameter (required = true)
private File input;
@Parameter
private File zipName;
/**
* @parameter default-value="${project}"
* @required
* @readonly
*/
@Parameter(defaultValue = "${project}", required = true, readonly = true)
MavenProject project;
The parameter input
is mandatory which accepts file directory path. The plugin scans this directory path and creates a zip file. The parameter zipName
is zip file name which is optional. If not provided, we will use the default name.
If we want to use project information where this plugin is included, we can define MavenProject to get access to the project information such as project name, version and so on. Therefore, we included maven-project plugin.
Let us complete our plugin execution. Here is the complete code.
/*
* 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.
*/
package com.techshard;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* Main class for creating file zip.
*
* @author Swathi Prasad
*
*/
@Mojo (name = "zip", defaultPhase = LifecyclePhase.GENERATE_RESOURCES)
public class FileZipMojo extends AbstractMojo {
@Parameter (required = true)
private File input;
@Parameter
private File zipName;
/**
* @parameter default-value="${project}"
* @required
* @readonly
*/
@Parameter(defaultValue = "${project}", required = true, readonly = true)
MavenProject project;
private static final String FILE_EXTENSION= ".zip";
public void execute() throws MojoExecutionException {
getLog().info("Zipping files in \"" + input.getPath() + "\".");
final String outputFileName = zipName != null ? zipName + FILE_EXTENSION : project.getName() + "-" + project.getVersion() + FILE_EXTENSION;
try {
final File dir = new File(input.getPath());
final File[] files = dir.listFiles();
if (files != null) {
final FileOutputStream fos = new FileOutputStream(outputFileName);
final ZipOutputStream zipOut = new ZipOutputStream(fos);
for (final File file : files) {
final String fileName = file.getName();
getLog().info("Zipping File " + fileName);
final FileInputStream fis = new FileInputStream(file);
final ZipEntry zipEntry = new ZipEntry(file.getName());
if (file.isDirectory()){
if (fileName.endsWith("/")){
zipOut.putNextEntry(new ZipEntry(fileName));
} else {
zipOut.putNextEntry(new ZipEntry(fileName + "/"));
}
} else {
zipOut.putNextEntry(zipEntry);
}
final byte[] bytes = new byte[2048];
int length;
while((length = fis.read(bytes)) >= 0) {
zipOut.write(bytes, 0, length);
}
fis.close();
}
zipOut.close();
fos.close();
}
} catch(final FileNotFoundException e) {
throw new MojoExecutionException("No file found", e);
} catch(final IOException e) {
throw new MojoExecutionException("Exception reading files", e);
}
}
}
Now that we have completed the execution code. Let us install the plugin in our local repository.
In pom.xml, I have included some additional plugins to generate sources and documentation. In addition to these plugins, I have added information about GitHub repository URL, license, and so on. Here is the complete POM.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.techshard.filezip</groupId>
<artifactId>filezip-maven-plugin</artifactId>
<packaging>maven-plugin</packaging>
<version>1.0-SNAPSHOT</version>
<name>filezip-maven-plugin Maven Mojo</name>
<url>http://maven.apache.org</url>
<scm>
<connection>scm:git:https://github.com/swathisprasad/filezip-maven-plugin.git</connection>
<developerConnection>scm:git:https://github.com/swathisprasad/filezip-maven-plugin.git</developerConnection>
<url>https://github.com/swathisprasad/filezip-maven-plugin</url>
<tag>HEAD</tag>
</scm>
<licenses>
<license>
<name>Apache 2.0 License</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.html</url>
<distribution>repo</distribution>
</license>
</licenses>
<issueManagement>
<system>Github</system>
<url>https://github.com/swathisprasad/filezip-maven-plugin/issues</url>
</issueManagement>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.6.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-project</artifactId>
<version>2.2.1</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>${project.basedir}</directory>
<includes>
<include>LICENSE*</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.4</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
<executions>
<execution>
<id>attach-javadoc</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
We are now ready to install the plugin in our local Maven repository. Run mvn clean install
in your terminal.
Testing the Maven Plugin
I will create a simple maven project to test our filezip-maven-plugin.
In pom.xml, let us add the following section.
<build>
<plugins>
<plugin>
<groupId>com.techshard</groupId>
<artifactId>filezip-maven-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<executions>
<execution>
<configuration>
<input>${project.basedir}/src/main/resources</input>
<zipName>test</zipName>
</configuration>
<goals>
<goal>zip</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
We have specified the goal as zip in "goals" section and provided required and optional parameters in the "executions" section. This is just an example, we can include the plugin wherever required.
Create some text files in project resources folder which would be used for creating zip file.
Run mvn clean install
. Once the build is complete, navigate to the project root folder and we should see test.zip file.
Conclusion
I hope this article serves as a starting reference point for anyone who wants to create a Maven plugin. The plugin described in this article is just an example. Let me know if you have any suggestions or comments.
The example explained in this article can be found on GitHub repository.
Published at DZone with permission of Swathi Prasad, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments