Beyond mvn install: A Deep Dive into Maven Plugin Core Principles
This article explains that Maven is essentially a plugin framework, details how plugins like flatten-maven-plugin and exec-maven-plugin are configured and executed, introduces the MOJO concept, walks through creating a custom Maven plugin, and shows how to bind plugin goals to the build lifecycle.
Maven itself is just the core framework that manages plugins; the plugins perform the actual operations such as creating JAR/WAR files, compiling code, running tests, and generating documentation.
In a typical
<build><plugins>…</plugins></build>section of a pom.xml, Maven’s standard plugins enable basic commands like clean and compile even when no explicit plugin is declared, using default configurations.
flatten-maven-plugin example
The flatten-maven-plugin flattens a project’s dependencies by resolving all version placeholders and writing a simplified POM. Its configuration includes:
outputDirectory : directory for the generated flattened POM.
flattenMode : set to resolveCiFriendliesOnly, allowing placeholders such as ${revision}, ${sha1}, ${changelist} to be supplied via mvn -Drevision=2.0.0-SNAPSHOT clean package.
updatePomFile : updates the generated flattened POM.
ignoreTransitiveDependencies : excludes transitive dependencies from the flattened POM.
Two <execution> blocks are defined: one bound to the generate-resources phase with goal flatten, and another bound to the clean phase with goal clean. Running mvn generate-resources creates a .flattened-pom.xml in the specified directory.
exec-maven-plugin example
This plugin runs external programs during the build. The example configures it to invoke the Allatori obfuscation tool:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<id>obfuscate</id>
<phase>package</phase>
<goals><goal>exec</goal></goals>
<configuration>
<executable>java</executable>
<arguments>
<argument>-jar</argument>
<argument>path/to/allatori.jar</argument>
<argument>-config</argument>
<argument>path/to/allatori-config.xml</argument>
<argument>-in</argument>
<argument>${project.build.directory}/${project.build.finalName}.jar</argument>
<argument>-out</argument>
<argument>${project.build.directory}/${project.build.finalName}-obfuscated.jar</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>When the package phase runs, Maven executes java -jar path/to/allatori.jar -config …, producing an obfuscated JAR whose class names may be changed (e.g., to VAR series) depending on the Allatori configuration.
Maven plugin fundamentals – MOJO
A Maven plugin is composed of one or more MOJOs (Maven Plain Old Java Objects). Each MOJO is a Java class, typically extending org.apache.maven.plugin.AbstractMojo, and defines one or more goals that can be invoked from the Maven lifecycle.
MOJOs use annotations such as @Mojo(name="goalName") to declare a goal and @Parameter to expose configuration fields. Maven maps XML elements in the pom.xml directly to these fields (e.g., <url> maps to a field annotated with @Parameter(property="url")).
@Mojo(name = "query")
public class MyQueryMojo extends AbstractMojo {
@Parameter(property = "query.url", required = true)
private String url;
@Parameter(property = "timeout", defaultValue = "50")
private int timeout;
@Parameter(property = "options")
private String[] options;
@Override
public void execute() throws MojoExecutionException {
// ...
}
}To use this MOJO, the plugin is referenced in the project’s pom.xml and its configuration elements ( <url>, <timeout>, <options>) are supplied, which Maven injects into the MOJO fields before invoking execute().
Creating a custom Maven plugin
To build a plugin named hello-maven-plugin that prints “Hello, world.”, first create a Maven project with packaging set to maven-plugin and add the necessary dependencies and maven-plugin-plugin in pluginManagement. Then implement a MOJO:
package org.example;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Mojo;
/**
* Says "Hi" to the user.
*/
@Mojo(name = "sayhi")
public class GreetingMojo extends AbstractMojo {
@Override
public void execute() throws MojoExecutionException {
getLog().info("Hello, world.");
}
}Run mvn install to install the plugin into the local repository. It can then be invoked from another project either directly:
mvn sample.plugin:hello-maven-plugin:1.0-SNAPSHOT:sayhior bound to a lifecycle phase (e.g., before clean) by adding an <execution> with <phase>clean</phase> and <goal>sayhi</goal> in the consuming project’s pom.xml. When mvn clean runs, the plugin’s goal executes automatically.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
