37

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?

talk to frank
  • 1,821
  • 4
  • 20
  • 21

2 Answers2

48

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

Resu
  • 64
  • 7
Rich Seller
  • 83,208
  • 23
  • 172
  • 177
  • 1
    is there a way to have the file created in the project with the foobar extension? – talk to frank Sep 15 '09 at 15:14
  • 1
    and do you mean MET-INF or META-INF? – talk to frank Sep 15 '09 at 15:14
  • I think to do that you'd have to replace the jar archiver with a custom implementation, or alternatively use a lifecycle.xml to bind an assembly-plugin invocation to a phase (as per your other question: http://stackoverflow.com/questions/1427740/how-do-i-execute-a-set-of-goals-before-my-maven-plugin-runs/1427783#1427783) – Rich Seller Sep 15 '09 at 15:16
  • ok thanks, I think this might be enough. I'll check and get back to you – talk to frank Sep 15 '09 at 15:17
  • 2
    If you use package `maven-plugin` you get `No mojo definitions were found for plugin` message as explained [here](http://jira.codehaus.org/browse/MPLUGIN-109). I had to use `jar` package instead. – fglez May 16 '11 at 10:43
  • This is good, but if I use an assembly at the package stage then at the install phase it ignores the assembly product and installs an almost empty jar instead. How do I get it to pick up the assembly product at the install phase? – AutomatedMike Dec 14 '11 at 08:58
  • Is it possible to define a default configuration for the plugins invoked by the custom type? For example if I define a `bigjar` type adding the shade plugin to the standard lifecycle, I'd like to set `true` by default without configuring the shade plugin in every project using the custom type. – Emmanuel Bourg Jun 14 '16 at 20:20
  • @EmmanuelBourg did you ever find a way to specify a default configuration for plugins bound to the phases of an extension? Also when specifying shade configuration in plugin management it seems like I have to bind the shade plugin to a phase resulting in multiple invocations... Any tips on how to set up the plugin configuration properly? – Christoffer Soop Sep 21 '17 at 07:00
  • @ChristofferSoop Yes somewhat, I created a wrapper plugin bound to my custom lifecycle that invokes the other plugin with the parameters I need (the syntax looks like `executeMojo(plugin("com.foo", "bar"), "bar", configuration(element("property", "value"),...), getExecutionEnvironment());` – Emmanuel Bourg Sep 21 '17 at 07:11
  • @EmmanuelBourg thanks for the rapid feedback! I found, however, that by [specifying a default id of the execution](https://maven.apache.org/guides/mini/guide-default-execution-ids.html) of the plugin configuration placed in a parent pom is sufficient for my needs, i.e. for the maven-shade-plugin using an execution id of `default-shade` did the trick for the maven-shade-plugin! – Christoffer Soop Sep 22 '17 at 07:07
  • So one _must_ write some Java code, ie. implement the `name.seller.rich.maven.plugins:maven-foobar-plugin` as well as `src/main/resources/META-INF/plexus/components.xml` - right? The components.xml cannot be used alone to modify the lifecycle - correct? – Ed Randall Jan 30 '21 at 07:08
6

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.

Ed Randall
  • 6,887
  • 2
  • 50
  • 45
KomodoDave
  • 7,239
  • 10
  • 60
  • 92
  • 2
    Using `jar` packaging in this case is correct. Because it has no mojos, what you're creating is an extension, not a plugin. You therefore need to load it through the [``](http://maven.apache.org/pom.html#Extensions) section of the POM instead of the [``](http://maven.apache.org/pom.html#Plugins) section. Doing so will prevent the "plugin descriptor not found" error. – Sam Hanes Feb 19 '13 at 22:32
  • @SamHanes Thank you for this correction. I've removed the relevant "..should use JAR.." from my post. – KomodoDave Feb 20 '13 at 15:21