Maven plug-in notes

Russell Bateman
July 2021
last update:



Maven comes from Yiddish meyvn, "one who understands." Extrapolated due to usage, a maven is someone who is an expert.

Apache Maven is an Apache Software Foundation project that is used primarily to build and manage Java-based projects, but it can be used for C#, Ruby, Scala and many other languages.

Maven is basically a plug-in execution framework. Everthing that happens in the build process happens because some plug-in accomplishes it. There is a core if limited set of plug-ins provided when Maven is installed, but there are also important third-party plug-ins.

Any time a developer nees to perform custom tasks just a bit out of the ordinary, such as create WAR or NAR files, often it's a third-party developer that wrote it.

Mojo

Mojo is, inspired by Java's POJO, short for "Maven old Java object." A mojo is a goal in Maven context. Plug-ins consist of one or more goals.

They can be defined as annotated Java classes (using @Mojo). They specify metadata about a goal including a name, which phase of the Maven lifecycle the mojo fits into and the parameters it's expecting.

One plug-in is a distribution of one or more related mojos. A mojo is an executable goal in Maven.

Purpose of these notes...

At some point, I want to write a tutorial on implementing a Maven plug-in. There are many, about one-half are badly written, leave much information out or don't work unless you already know enough to fix or go beyond what they say. I want to correct that, but I'm far from having the time or being able to do so.

In the meantime, I'm going to make notes on crucial points—things that will make you fail when you write a plug-in.


Useful links

Google search string: "how to write a maven plugin"


Steps to set up a plug-in development project

As noted, I haven't undertake to write a tutorial yet. Pick one from those I listed in the links above. I particularly recommend the Omnifaces one for its ease.

(Because I'm an old guy used to doing things old ways, I tend to set up any new project by writing its pom.xml, creating all the subdirectories I know I'll need, then in IDEA I do File → New → Project from Existing Sources..., then I navigate to the root of my new project and choose it. At some point, some IDEA/Maven thing will pop up and ask me if I want to Recreate something, that's confusing, but I click to do that and it's all good from there-on.)

Your mileage may vary, but using some Maven artifact command might be what you want to do; some of the tutorials give that to you, others leave you on your own.


Command-line invocation shorthand

In the Baeldung tutorial, you learn that there is a long, formal way to invoke the plug-in from the command line, but, as a super Maven champion, you would also know of a shorthand. However, this never worked for me.

(Formal pattern:)
$ mvn groupId:artifactId:version:goal

(Example:)
$  mvn com.baeldung:counter-maven-plugin:0.0.1-SNAPSHOT:dependency-counter

(Shorthand—doesn't work for me:)
$  mvn counter:dependency-counter

Debugging steps

Here's how to set up IntelliJ IDEA to debug your plug-in. Let's say you've got your project on the path /home/russ/dev/hello and you've done the Omnifaces hello-world project from the links above.

  1. At the command line, install your plug-in in Maven (goes into ~/.m2/repository/...).
    $ mvn clean install
    
  2. Your plug-in project running in IDEA.
  3. Create a run/debug configuration:
    1. Run → Edit Configurations...
    2. Click the + sign, look for Remote JVM Debug.
    3. Name: the configuration, something like Hello plug-in.
    4. Leave Host: as localhost.
    5. Set the Port: to 8000.
  4. At the command line, run your plug-in thus:
    $ mvnDebug org.omnifaces.example:hello-maven-plugin:hello
    Preparing to execute Maven in debug mode
    Listening for transport dt_socket at address: 8000
    
  5. Now go back to IDEA and set a breakpoint in your setLog() or execute() method.
  6. Click Run → Debug....
  7. Choose the debug configuration you made.
  8. You should find yourself halted at one of your breakpoints—likely the one in setLog(), if you set it, because that method, of the several you have coded to, is the first one to be called. Note that method execute() is the one that does the heavy lifting.

Failed to execute goal

If this is what you get when beginning to test a plug-in you're writing, it means you'ce screwed something up.

[ERROR] Failed to execute goal groupId:artifactId:version:goal (default-cli) on project project-name: etc.

What's screwed up? One of the following:

Formally, you must have the following in your plug-in's pom.xml:

If the first two don't match the package paths in your plug-in source code, you'll get the error above. My example here uses the Baeldung tutorial:

Plug-in's pom.xml:

<groupId>com.windofkeltia.maven.plugin</groupId>
<artifactId>counter-maven-plugin</artifactId>
<version>1.0.0</version>
<packaging>maven-plugin</packaging>

The filesystem of your project:

src
└── main
    └── java
        └── com                ✓
            └── windofkeltia   ✓
                └── maven      ✓
                    └── plugin ✓
                        └── FirstMojo.java

Compare the above from the line containing com with the groupId defined in pom.xml.

Invoking a plug-in from the command line will also give the error above. The format to invoke locally is:

mvn groupId:artifactId:version:goal

Here are two sample invocations:

$  mvn      com.windofkeltia.maven.plugin:counter-maven-plugin:1.0.0:dependency-counter
$  mvnDebug com.windofkeltia.maven.plugin:counter-maven-plugin:1.0.0:dependency-counter

Command execution failed

This is about consuming a plug-in, not developing one. This problem occurs when you invoke Maven in a consuming project.

[ERROR] Failed to execute goal groupId:artifactId:version:goal (default-cli) on project project-name: \
    Command execution failed.: Process exited with an error: 1 (Exit value: 1) -> [Help 1]

This usually means that something is broken in the configuration of the plug-in, a bad parameter, execution, configuration, etc.

Maven errors are not the most informative on this planet. I don't always find invocation option -X to be helpful—it just creates a lot more crap to sort through. The best thing is just to use your brain. However, if you don't know what Maven's up to when it blows up in the first place (which is a problem most of us suffer from), then, by definition, it's a bad-hair day and you have my sincerest sympathy.