Building a Maven Complex Release Artifact: Difference between revisions

From NovaOrdis Knowledge Base
Jump to navigation Jump to search
No edit summary
Line 7: Line 7:
=Overview=
=Overview=


This article describes the procedure of configuring Maven to build one complex release artifact, containing multiple individual artifacts, possibly produced by multiple modules, as well as arbitrary files from the project, dependencies, and so on, or otherwise what is known to Maven as an [[Maven_assembly_Plugin#Assembly|assembly]].
This article describes the procedure of configuring Maven to build one complex elease artifact, containing multiple individual artifacts, possibly produced by multiple modules, as well as arbitrary files from the project, dependencies, and so on, or otherwise what is known to Maven as an [[Maven_assembly_Plugin#Assembly|assembly]].


=Don't Follow your Intuition=
=Don't Follow your Intuition=

Revision as of 18:40, 30 November 2016

Internal

Overview

This article describes the procedure of configuring Maven to build one complex elease artifact, containing multiple individual artifacts, possibly produced by multiple modules, as well as arbitrary files from the project, dependencies, and so on, or otherwise what is known to Maven as an assembly.

Don't Follow your Intuition

An intuitive approach to assemble the release artifact of a multi-module project into one release file would be to build the final assembly in the project root. However, this approach does not work well in practice. Among the problems:

Root Module Builds First

... so if the "final" assembly depends on the artifacts of the children modules, we'll get into a deadlock.

Repeated Execution

Because the assembly plug-in is specified in the parent POM, the plug-in will be executed for each module (including root) at the specified phase, usually "package". When executing, the module will try to resolve the specified descriptor relative to the module root, so if we have the following declaration and layout:

<project>
   </build>
        <plugins>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <descriptors>
                        <descriptor>assembly.xml</descriptor>
                    </descriptors>
                </configuration>
                ...
            </plugin>
        </plugins>
    </build>
</project>
<pre>

<pre>
  .
  +-- pom.xml
  |
  +-- assembly.xml   (1)
  |
  +-- module-1
       |
       +-- pom.xml
       |
       +-- assembly.xml (2)

then the root module will create its assembly based on assembly.xml (1) and module-1 will create its assembly based on assembly.xml (2).

Recommended Approach

Dedicated Release Module

Create a separated module called "release", dedicated to building the final release assembly, and make it a dependent of all other modules that contribute artifacts to the final release bundle.

The Public Release Version

... will be maintained as the dedicated release module's <version>. This allows the component modules' versions to evolve independently.

Dedicated Release Module POM

Assuming that the parent project artifact ID is "my-project" (for more on how to name the parent project artifact ID, see the "Multi-Module Maven Projects" section), and other modules are "module-1" and "module-2", then the "release" pom.xml should look similar to:

<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>

    <parent>
        <groupId>my.example.group</groupId>
        <artifactId>my-project</artifactId>
        <version>0</version>
    </parent>

    <artifactId>release</artifactId>
    <packaging>pom</packaging>
    <version>...</version>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.6</version>
                <configuration>
                    <finalName>my-public-application-name-${project.version}</finalName>
                    <appendAssemblyId>false</appendAssemblyId>
                    <descriptors>
                        <descriptor>src/assembly/release.xml</descriptor>
                    </descriptors>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>my.example.group</groupId>
            <artifactId>module-1</artifactId>
            <version>...</version>
        </dependency>
        <dependency>
            <groupId>my.example.group</groupId>
            <artifactId>module-2</artifactId>
            <version>...</version>
        </dependency>
    </dependencies>
</project>

The "release" module must be declared in the project parent pom.xml, amongst the project's modules.

Conventionally, we name the artifactId of a release module "release", we use a <finalName> as shown above, to specify the name of the release artifact, for reasons described in the "Name of a Release Artifact - <finalName>" section.

Custom Assembly File

A working example of a custom example file used to build the release assembly of a multi-module project is available below:

https://github.com/NovaOrdis/events/blob/master/release/src/assembly/release.xml