javamavenmaven-assembly-plugin

maven-assembly-plugin: How to use appendAssemblyId


I have a multi-module Maven project and in one module I want to create two artifacts during the build:

Here is the code that I use to configure the maven-assembly-plugin plugin:

<plugin>
    <artifactId>
        maven-assembly-plugin
    </artifactId>
    <version>2.4</version>
    <executions>
      <execution>
        <id>dist-assembly</id>
        <phase>package</phase>
        <goals>
          <goal>single</goal>
        </goals>

        <configuration>
          <finalName>bso</finalName>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
          <finalName>helper-${project.version}</finalName>
          <appendAssemblyId>false</appendAssemblyId>
          <archive>
            <manifest>
              <mainClass>HelperMain<mainClass>
            </manifest>
          </archive>
        </configuration>

      </execution>
    </executions>
  </plugin>

I am setting appendAssemblyId to false because otherwise -jar-with-dependencies will be appended to the final name and I do not see the need for it. Omitting it gives a cleaner and easier to use file name.

When I run mvn integration-test then I receive the following warnings:

[WARNING] Configuration options: 'appendAssemblyId' is set to false, and 'classifier' is missing. Instead of attaching the assembly file: [...]/target/helper-5.0.0-SNAPSHOT.jar, it will become the file for main project artifact.

NOTE: If multiple descriptors or descriptor-formats are provided for this project, the value of this file will be non-deterministic!

[WARNING] Replacing pre-existing project main-artifact file: [...]/target/my.module-5.0.0-SNAPSHOT.jar with assembly file: [...]/target/helper-5.0.0-SNAPSHOT.jar

There are two things which irritate me:

  1. Despite the fact that the warning claims it will replace my.module-5.0.0-SNAPSHOT.jar with helper-5.0.0-SNAPSHOT.jar it does not actually do so and when the build has finished both files still have different sizes.

  2. Why does the warning about replacing the artifact appear at all?

  3. It seems that classifier is deprecated why does the warning ask me to use it?


Solution

  • That is because you are mis-interpreting the warnings.


    Let's recap. A Maven project that is not of type pom will always produce, by default, what is called a main artifact. For a JAR, this artifact is the result of packaging the compiled sources into a JAR; for a WAR, it is the result of building the web-application.

    What is important to remember is that this artifact is attached to the project: this terminology is useful when the project is installed (with mvn install), deployed (with mvn deploy) or released (with the maven-release-plugin). Attached means that this artifact will be installed / deployed / released when the project is. Not all files generated during a Maven build (basically, everything under the target folder) are; only the files that were attached. As such, you can very well create a lot of files under target but have a single installed artifact.

    Alongside this main artifact, you may want your build to produce other artifacts to install or deploy. That's the concept of additional or secondary attached artifacts. The main examples are the Javadoc or the sources: typically when a project is released, its Javadoc and its sources also are. And that is where the notion classifier kicks in.

    In a Maven repository, each and every file has to follow the same naming convention: artifactId-version(-classifier).type. Every secondary artifact will have the same GAV (group id, artifact id, version) as the main artifact so if you want to put inside a Maven repo 1 main artifact and 1 attached artifact (like it would be the case for a main JAR along with its JAR Javadoc and JAR sources), you need some way to distinguish them. Which is what the classifier is for: distinguish secondary artifacts from the main artifact.


    Let's go back to your example now. Your Maven project, which is of jar packaging, will produce by default a main JAR artifact called my.module-5.0.0-SNAPSHOT.jar; still by default, this main JAR is attached to the project (and ready to be installed / deployed). Now you're configuring the maven-assembly-plugin to create a new JAR artifact (called helper-5.0.0-SNAPSHOT.jar but it really doesn't matter). The Assembly Plugin, by default, attaches to the project the artifact it produces. So you end up with 2 attached artifacts

    1. having the same artifact id of my.module; the fact that the file on disk inside the target folder is named helper for one is irrelevant, only the GAV coordinates matter
    2. having the same version of 5.0.0-SNAPSHOT
    3. having the same packaging of JAR

    and no classifier to distinguish them. This is what raises the warning: you end up attaching to the project a secondary artifact that effectively replaces the main one, simply because it has the same coordinates. So the result is:

    1. Both files having different names on disk inside target, but that is irrelevant because
    2. Both share the same coordinates so only 1 will survive.

    It is the one produced by the Assembly Plugin that will win the conflict, and replace the attached main artifact.

    If you want to convince yourself of all that, run mvn clean install on the project and check your local repo. You will notice that only the jar-with-dependencies artifact will be installed. The other one (the main artifact) went poof.

    You can also configure a <distributionManagement>:

    <distributionManagement>
        <repository>
            <id>local-repo-test</id>
            <url>file://...</url>
        </repository>
    </distributionManagement>
    

    and invoke mvn clean deploy. You can then check that the only deployed artifact will be the jar-with-dependencies.


    Final note: Yes, the classifier parameter of the Assembly Plugin is deprecated, because you should just use the assembly id as classifier.