maven-plugin-plugin

After the Mojo has been compiled and packaged into a JAR, Maven can invoke it as a plugin. The main difference between a common JAR and a plugin JAR lies in a file named plugin.xml, stored inside the JAR's directory, META-INF/maven/plugin.xml.

In a plugin's JAR artifact, this file is the plugin descriptor. It contains all the information that Maven needs to recognize a JAR as a plugin's JAR artifact:

  • The list of Mojo classes
  • The list of plugin's configurations
  • The list of dependencies and requirements needed

Manually writing all the information can be a long and error-prone task. Fortunately, Maven provides a plugin for doing this dirty work. The maven-plugin-plugin provides the descriptor goal to generate the plugin descriptor file. The following sample shows how to configure maven-plugin-plugin to generate a descriptor:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-plugin-plugin</artifactId>
  <version>3.2</version>
  
  <executions>
    <execution>
      <id>mojo-descriptor</id>
      <goals>
        <goal>descriptor</goal>
      </goals>
    </execution>
  </executions>
  <configuration>
    <skipErrorNoDescriptorsFound>
      true
    </skipErrorNoDescriptorsFound>
  </configuration>
</plugin>

The next sample shows the head section of the generated plugin descriptor:

<plugin>
  <name>mantis-plugin Maven Mojo</name>
  <description></description>
  <groupId>com.example.mojo</groupId>
  <artifactId>mantis-maven-plugin</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <goalPrefix>mantis</goalPrefix>
  <isolatedRealm>false</isolatedRealm>
  <inheritedByDefault>true</inheritedByDefault>

The plugin descriptor also contains one section for each goal covered by the plugin. Each of these sections contain the goal execution's requirements and configurations. In the following sample, we can see the configurations related to the mark-resolved goal:

<mojos>
    <mojo>
      <goal>mark-resolved</goal>
      <description>
        Goal touching a timestamp file.
      </description>
      <requiresDirectInvocation>
        false
      </requiresDirectInvocation>
      <requiresProject>true</requiresProject>
      <requiresReports>false</requiresReports>
      <aggregator>false</aggregator>
      <requiresOnline>true</requiresOnline>
      <inheritedByDefault>true</inheritedByDefault>
      <phase>package</phase>
      <implementation>
        com.example.mojo.plugin.MarkResolved
      </implementation>
      <language>java</language>
      <instantiationStrategy>
        per-lookup
      </instantiationStrategy>
      <executionStrategy>
        once-per-session
      </executionStrategy>
      <threadSafe>true</threadSafe>
      <parameters>
        <parameter>
          <name>basedir</name>
          <type>java.io.File</type>
          <required>true</required>
          <editable>true</editable>
          <description>The base directory.</description>
        </parameter>

The plugin's configurations represent the Mojo fields. In the following sample, we can see how, for each parameter, we declare its type and, optionally, its default value:

      <configuration>
        <basedir implementation="java.io.File">
          ${basedir}
        </basedir>
        <databaseUrl implementation="java.lang.String">
          ${databaseUrl}
        </databaseUrl>
        <projectDescription>
            implementation="java.lang.String"
            default-value="${project.description}">
          ${project.description}
        </projectDescription>
        <projectId implementation="java.lang.String"
            default-value="${project.artifactId}">
          ${projectId}
        </projectId>
        <projectVersion
            implementation="java.lang.String"
            default-value="${project.version}">
          ${projectVersion}
        </projectVersion>
        <rsName implementation="java.lang.String">
          ${rsName}
        </rsName>
      </configuration>

The preceding sample shows the dependencies of our plugin. As we can see, the dependencies declaration is the same as the one used for normal projects:

<dependencies>
    <dependency>
      <groupId>org.apache.maven</groupId>
      <artifactId>maven-plugin-api</artifactId>
      <type>jar</type>
      <version>3.2.1</version>
    </dependency>
    <dependency>
      <groupId>org.apache.maven</groupId>
      <artifactId>maven-model</artifactId>
      <type>jar</type>
      <version>3.2.1</version>
    </dependency>

All plugins have a useful help goal explaining how to use that plugin, and which configurations it needs. Since every plugin goal is a Mojo, it would be expensive work to implement a custom Mojo only to satisfy the help goal. In order to realize this task, we can take advantage of a maven-plugin-plugin goal named helpmojo, as follows:

<plugin>      
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-plugin-plugin</artifactId>
  <version>3.2</version>
  <execution>
    <id>generated-helpmojo</id>
    <goals>
      <goal>helpmojo</goal>
    </goals>
  </execution>
 </executions>
</plugin>

After executing a compile command, we will find a new Mojo class generated by the helpmojo goal at the following location:

target
  |
  |-generated-source
     |
     |-our packaging directory structure
      |
      |-HelpMojo.java

The generated class, HelpMojo, is a standard Mojo class, with all its necessary fields and a preimplemented execute method, where the goal task logic is implemented:

@Mojo( name = "help", requiresProject = false, threadSafe = true )
publicclass HelpMojo extends AbstractMojo
/**
     * If <code>true</code>, display all settable properties for each goal.
     *
     */
    @Parameter( property = "detail", defaultValue = "false" )
    private boolean detail;

    /**
     * The name of the goal for which to show help. If unspecified, all goals will be displayed.
     *
     */
    @Parameter( property = "goal" )
    private java.lang.String goal;

    /**
     * The maximum length of a display line, should be positive.
     *
     */
    @Parameter( property = "lineLength", defaultValue = "80" )
    private int lineLength;

    /**
     * The number of spaces per indentation level, should be positive.
     *
     */
    @Parameter( property = "indentSize", defaultValue = "2" )
    private int indentSize;

The only task in charge to the help goal, is to print out all the information related to the implemented plugin. All the information is extracted from an XML file located at the following location:

META-INF
  |
  |-maven
  |
  |-com.example.mojo
    |
    |-mantis-maven-plugin
      |
      |-plugin-help.xml

To check whether the help Mojo generated by maven-plugin-plugin has all the correct information, we need to perform mvn install on our project (a previous build is needed in order to make a successful install possible). After a successful return of the install command, we can execute mvn help ourPluginGroupId:ourpluginArtifactId:help.

If all the previous operations were successful, we can read the help information as follows:

[INFO] mantis-plugin Maven Mojo 0.0.1-SNAPSHOT
This plugin has 3 goals:
mantis:help
  Display help information on mantis-maven-plugin.
  Call mvn mantis:help -Ddetail=true -Dgoal=<goal-name> to display parameter details.

mantis:issue-info
  Passing module articaftId return all open mantis issue, if exist any, for that project.

mantis:mark-resolved
  Perform an update on all issue attached to projectId passed as configuration parameter.

All the information related to a single goal is written in the class comments of the matching Mojo definition, as shown in the following example:

/**
 * Passing module artifactId return all open
 * mantis issue, if there exist any, for that project. 
 * 
 * 
 */
@Mojo(name = "issue-info", defaultPhase = LifecyclePhase.NONE, requiresOnline = true, requiresProject = true, threadSafe = true)
public class IssueInfo extends MarkResolved

To launch our plugin's help goal (mvn mantis:help) with user friendly notation, we have to edit the settings.xml file and add our plugin group to the pluginGroups tag:

<pluginGroups>
    <pluginGroup>com.example.mojo</pluginGroup>
</pluginGroups>

In this way, we can execute all goals for our plugin with user-friendly notation.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset