How to inherit a Mojo from another plugin in Maven

I’m trying to inherit from the default CompilerMojo from Maven and execute this new Mojo as newcompile goal.

My setup:

pom.xml of new-compiler-plugin

<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>test.plugins</groupId>
    <artifactId>new-compiler-plugin</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>maven-plugin</packaging>

    <dependencies>
        <dependency>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.5.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-plugin-api</artifactId>
            <version>3.0.5</version>
        </dependency>
    </dependencies>
</project>

NewCompilerMojo.java

import org.apache.maven.plugin.compiler.CompilerMojo;

/**
 * Goal which touches a timestamp file.
 *
 * @goal newcompile
 * 
 * @phase compile
 */
public class NewCompilerMojo extends CompilerMojo {

}

So I created a second Maven project to test the new-compiler-plugin. Its pom.xml looks like this:

<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>test.plugins</groupId>
    <artifactId>test-new-compiler-plugin</artifactId>
    <version>1.0-SNAPSHOT</version>

    <build>
        <plugins>
            <plugin>
                <groupId>test.plugins</groupId>
                <artifactId>new-compiler-plugin</artifactId>
                <version>1.0-SNAPSHOT</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>newcompile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

Now I run mvn clean package -e with the test-new-compiler-plugin:

Caused by: java.lang.NullPointerException
        at org.apache.maven.plugin.compiler.AbstractCompilerMojo.execute(AbstractCompilerMojo.java:481)
        at org.apache.maven.plugin.compiler.CompilerMojo.execute(CompilerMojo.java:129)
        at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:101)

Apparently Maven didnt initialized the @Component or @Parameter variables in the original CompilerMojo from Maven.

Somebody knows how to fix this or if its even possible to inherit in such a way from a Mojo of another plugin?

I added the complete POMs and I’m getting the NullPointer with this exact code (using Maven 3.0.5). Whole idea is to override the execute method to start a logger and log all output (especially the warnings) during the compile goal by calling the super execute method. After that generating a report during the site phase.

Answer

The issue is that you’re declaring your MOJO with the @goal and @phase tag inside the Javadoc instead of using annotations. The maven-compiler-plugin is using annotations to configure itself, so you need to use them also:

With annotations, your Mojo super class does not any more require to be in the same project. Provided that the super class also uses annotations, it can now come from reactor projects or external dependencies.

Add the following dependency to the POM of your Maven plugin:

<dependency>
    <groupId>org.apache.maven.plugin-tools</groupId>
    <artifactId>maven-plugin-annotations</artifactId>
    <version>3.4</version>
    <scope>provided</scope>
</dependency>

and configure it with

import org.apache.maven.plugin.compiler.CompilerMojo;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.ResolutionScope;

@Mojo(name = "newcompile", defaultPhase = LifecyclePhase.COMPILE, requiresDependencyResolution = ResolutionScope.COMPILE)
public class NewCompilerMojo extends CompilerMojo {

}

Reinstalling the Maven plugin and testing it inside a sample project, the logs shows that it is correctly invoked:

[INFO] --- new-compiler-plugin:1.0-SNAPSHOT:newcompile (default) @ test ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 3 source files to ...targetclasses

Leave a Reply

Your email address will not be published. Required fields are marked *