How do I create a new packaging type for Maven?

I have a requirement to create jar files with Maven, but they need to be installed to the repository with a "foobar" extension , and it would be nice if they could have their own packaging type so we can identify those artifacts by the packaging.

Can I set up a new packaging type to do this?


Solution 1:

To do as you described, create a Maven project with packaging jar (as stated here, as there won't be mojo definitions). In the src/main/resources/META-INF/plexus sub-folder create a components.xml with the following contents (assuming you want the packaging type to be "my-custom-type", change it to "foobar" if you wish).

<component-set>
  <components>
    <component>
      <role>org.apache.maven.lifecycle.mapping.LifecycleMapping</role>
      <role-hint>my-custom-type</role-hint>
      <implementation>
        org.apache.maven.lifecycle.mapping.DefaultLifecycleMapping
      </implementation>
      <configuration>
    <phases>
      <!--use the basic jar lifecycle bindings, add additional 
          executions in here if you want anything extra to be run-->          
      <process-resources>
        org.apache.maven.plugins:maven-resources-plugin:resources
      </process-resources>
      <package>
        org.apache.maven.plugins:maven-jar-plugin:jar
      </package>
      <install>
        org.apache.maven.plugins:maven-install-plugin:install
      </install>
      <deploy>
        org.apache.maven.plugins:maven-deploy-plugin:deploy
      </deploy>
    </phases>
      </configuration>
    </component>
    <component>
      <role>org.apache.maven.artifact.handler.ArtifactHandler</role>
      <role-hint>my-custom-type</role-hint>
      <implementation>
        org.apache.maven.artifact.handler.DefaultArtifactHandler
      </implementation>
      <configuration>
        <!--the extension used by Maven in the repository-->
        <extension>foobar</extension>
        <!--the type used when specifying dependencies etc.-->
        <type>my-custom-type</type>
        <!--the packaging used when declaring an implementation of 
          the packaging-->
        <packaging>my-custom-type</packaging>
      </configuration>
    </component>
  </components>
</component-set>

Then in a pom that is to have the custom packaging, declare the required type in the packaging element, and ensure you have specified the plugin so the custom packaging can be contributed. Declaring <extensions>true</extensions> tells Maven that the plugin contributes packaging and/or type handlers to Maven.

<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>name.seller.rich</groupId>
  <artifactId>test</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>my-custom-type</packaging>
  <build>
    <plugins>
      <plugin>
        <groupId>name.seller.rich.maven.plugins</groupId>
        <artifactId>maven-foobar-plugin</artifactId>
        <version>0.0.1</version>
        <!--declare that this plugin contributes the component extensions-->
        <extensions>true</extensions>
      </plugin>
    </plugins>
  </build> 
</project>

When the project is packaged, it will be a jar, with a .jar extension, however when it is installed/deployed, Maven will deliver the file to the repository with the ".foobar" extension as specified in components.xml

Solution 2:

Following up on Rich Seller's original answer:

If as he recommends you use a packaging type jar then most likely in the project where you reference your plugin you'll receive:

[INFO] ------------------------------------------------------------------------
[ERROR] FATAL ERROR
[INFO] ------------------------------------------------------------------------
[INFO] The plugin descriptor for the plugin Plugin [com.ocado.mvn.packaging:Jar-Gem] was not found. Please verify that the plugin JAR /home/ndb/.m2/repository/com/ocado/mvn/packaging/Jar-Gem/1.0.0/Jar-Gem-1.0.0.jar is intact.

This is because no plugin descriptor exists in the JAR you generated.

You can use the following to bypass the No mojo definitions.. error he mentions:

<packaging>maven-plugin</packaging>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-plugin-plugin</artifactId>
            <version>3.1</version>
            <configuration>
                <skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
            </configuration>
        </plugin>
    </plugins>
</build>

This configuration was found in plugin docs example here.

The maven-plugin packaging type lifecycle has the plugin:descriptor goal bound to generate-resources phase. This is specified in Sonatype's official documentation.