Search code examples
mavenmaven-assembly-plugin

Maven: Three Jars in one project. Trying to use an assembly, but not getting pom.xml and pom.properties embedded in the jars


I have a project that produces three different jar files:

  • Server.jar: This contains all classes and resources. A standard jar
  • Client.jar: This contains only a few external classes and no resources.
  • ServerSDK.jar: This contains all the classes, resources, test classes, and other configuration files.

I've decided to do all three jars in a single project, so a change in any of the sources spawns a Jenkins build and deploys all three at once. I build the Server.jar as my standard pom.xml jar. Then, I use assemblies to build the Client.jar and the ServerSDK.jar.

I have the assemblies that build the other two jars, and everything is 99% of the way I like it, but there is bit of munging I'd like to do.

  1. We add a few entries in our MANIFEST.MF file to incorporate the Jenkins build information and project information.
  2. In a standard Maven jar, the pom.xml and pom.properties are embedded in the META-INF directory.

The first one I have managed to do via the <assembly> configuration in my maven-assembly-plugin. The second one I can't seem to get to work even though I have <addMavenDescriptor> set to true in my <assembly> configuration.

Here's my maven-assembly-plugin section in my pom.xml

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>2.6</version>
    <configuration>
        <archive>
            <addMavenDescriptor>true</addMavenDescriptor>
            <manifestSections>
                <manifestSection>
                    <name>Build-Information</name>
                    <manifestEntries>
                        <Project-Name>${env.JOB_NAME}</Project-Name>
                        <Build-Number>${env.BUILD_NUMBER}</Build-Number>
                        <SVN-Revision>${env.SVN_REVISION}</SVN-Revision>
                    </manifestEntries>
                </manifestSection>
                <manifestSection>
                    <name>Module-Information</name>
                    <manifestEntries>
                        <Group-ID>${project.groupId}</Group-ID>
                        <Artifact-ID>${project.artifactId}</Artifact-ID>
                        <Version>${project.version}</Version>
                    </manifestEntries>
                </manifestSection>
            </manifestSections>
        </archive>
    </configuration>
    <executions>
        <execution>
            <id>Client</id>
            <configuration>
                <finalName>Client</finalName>
                <appendAssemblyId>true</appendAssemblyId>
                <descriptors>
                    <descriptor>src/assembly/client.xml</descriptor>
                </descriptors>
            </configuration>
            <phase>package</phase>
            <goals>
                <goal>single</goal>
            </goals>
        </execution>
    </executions>
</plugin>

The <manifestSections> work just fine, but the <addMavenDescriptor> doesn't seem to be working although I've explicitly set it to true.

According to the documentation on the maven-archiver-plugin:

Whether the created archive will contain these two Maven files:

  • The pom file, located in the archive in META-INF/maven/${groupId}/${artifactId}/pom.xml
  • A pom.properties file, located in the archive in META-INF/maven/${groupId}/${artifactId}/pom.properties

The default value is true.

According the maven-assembly-plugin page:

<archive>
This is a set of instructions to the archive builder, especially for building .jar files. It enables you to specify a Manifest file for the jar, in addition to other options. See Maven Archiver Reference

Is there something simple I'm missing here?


Solution

  • The Maven Assembly Plugin actually ignores the addMavenDescriptor parameter, and will never include the Maven descriptor in the resulting assembly. This can be seen in the source code: only the META-INF/MANIFEST.MF file is possibly added to the JAR archive.

    I couldn't find an existing JIRA issue about this, so I went ahead and created MASSEMBLY-835 to track this.


    A work-around for now would be to add the files yourself in the assembly descriptor:

    <assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
      <id>client</id>
      <formats>
        <format>jar</format>
      </formats>
      <includeBaseDirectory>false</includeBaseDirectory>
      <files>
        <file>
          <source>pom.xml</source>
          <outputDirectory>META-INF/maven/${project.groupId}/${project.artifactId}</outputDirectory>
        </file>
        <file>
          <source>${project.build.directory}/maven-archiver/pom.properties</source>
          <outputDirectory>META-INF/maven/${project.groupId}/${project.artifactId}</outputDirectory>
        </file>
      </files>
      <!-- rest of your configuration -->
    </assembly>
    

    This adds a <files> configuration that adds the pom.xml and the generated pom.properties into the target directory.

    Note that the pom.properties is generated by the Maven Archiver component during the default package goal into the target/maven-archiver directory; therefore, in order for it to be present when making your assembly, the Assembly Plugin has to be bound to the phase package (or later in the lifecycle), and the current Maven project needs to be of packaging JAR / WAR / EAR / EJB / RAR... but not POM which doesn't package an archive. The primary artifact of the Maven project also needs to be built (if you skip the generation of the primary JAR of a JAR project, the pom.properties won't be generated).

    This works in a large majority of cases. But if you want a bullet-proof solution, you can just create the file yourself. Create a pom.properties somewhere in your project (example, base directory) with the following content:

    #Generated by Apache Maven ${maven.version}
    version=${project.version}
    groupId=${project.groupId}
    artifactId=${project.artifactId}
    

    and in the previous assembly descriptor, have instead:

    <file>
      <source>pom.properties</source>
      <outputDirectory>META-INF/maven/${project.groupId}/${project.artifactId}</outputDirectory>
      <filtered>true</filtered>
    </file>
    

    This would correctly replace the placeholders inside the pom.properties that was created, and mimic what Maven Archiver would do.