Advanced Module-Set Topics
Quick Note
Some of the topics in this document refer to more general topics or improvements in the assembly descriptor as a whole. For more information, see the Advanced Assembly-Descriptor Topics page.
Including and Excluding Modules using a ModuleSet
As you are no doubt aware, Maven introduces advanced handling of multimodule builds. These are builds which contain multiple, often interrelated projects. In these builds, project hierarchy is established through use of the modules
section of the POM, where parent POMs specify their children in a modules
section. Other relationships, like interdependency, also exist within multimodule builds; however, these are beyond the scope of this document.
When constructing an assembly from any parent-level project in a multimodule build, it's possible to process this parent-POM's descendent modules, and include them in some form within the resulting assembly artifact. By default, the entire module hierarchy below the current project is available for inclusion or exclusion. Also, include/exclude patterns for modules are matched using the artifact-matching rules explained in the Advanced Assembly-Descriptor Topics document.
The following examples describe how to select certain modules in the project hierarchy using basic artifact includes/excludes. It does not describe what to do with the selected modules; to learn about the actions available for selected modules, see including module sources and including module binaries below. For other, more advanced module-handling options, read on!
Example: Select one from a set of child projects
Given the following project structure, and all appropriate module references in the parent POM:
+ parent (groupId: org.test, artifactId: parent) | + child1 (groupId: org.test, artifactId: child1) | + child2 (groupId: org.test, artifactId: child2)
We can select just the child1 module using the following moduleSet
:
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.2.0 http://maven.apache.org/xsd/assembly-2.2.0.xsd"> [...] <moduleSets> [...] <moduleSet> <includes> <include>org.test:child1</include> </includes> </moduleSet> </moduleSets> [...] </assembly>
NOTE: It's important to remember that, if the child1 project itself had children, those children would not be included just because the child1 project was included. Each module is matched separately.
Quick Note on outputFileNameMapping
within ModuleSets
When used from within a moduleSet
, all outputFileNameMapping
configurations with expressions like ${artifactId}
extract information from the artifact in question.
Example: Setting outputFileNameMapping
from moduleSet/binaries
Given a module with the following:
Group Id: org.test Artifact Id: project Version: 1.0.1 Type: jar
The following outputFileNameMapping
:
${module.groupId}-${module.artifactId}-${module.version}.${module.extension}
Will result in a file called org.test-project-1.0.jar
being created within the assembly.
NOTE: The expression ${module.extension}
is mapped to the file extension supplied by the ArtifactHandler for the type jar
. It's important to remember that the file extension need not be .jar.
Including Module Sources
Once you've selected certain modules to be included in the assembly, you have to determine what you want included from each module. This usually depends on the purpose of the assembly. For instance, if you're building a binary assembly, for use in a runtime context, you probably want to include module binaries only (see the Including_Module_Binaries section below). However, if your assembly is meant to include project sources, either as a reference or to allow users to build your project (or for some other reason altogether), then you're probably interested in the sources
section of the moduleSet
.
Processing module sources is a fileSet-based activity. That is, sources are included or excluded based on file-matching patterns, or explicit fileSet
subsections. For backward compatibility only, the <sources/>
section itself supports includes
and excludes
that can help determine which files from a module's directory should be processed. Starting in version 2.2 of the assembly plugin, the <sources/>
section supports a <fileSets/>
subsection, which is the preferred way of selecting module-source files for processing.
Example: including the src
directory from each selected module
In this example, we'll explore how to include the src
directory only for each module selected by the moduleSet. This is useful to provide a source reference for your project to users.
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.2.0 http://maven.apache.org/xsd/assembly-2.2.0.xsd"> [...] <moduleSets> [...] <moduleSet> [...] <sources> <fileSets> <fileSet> <directory>src</directory> </fileSet> </fileSets> </sources> </moduleSet> </moduleSets> </assembly>
Example: Including a buildable project directory for each selected module
In this example, we'll explore how to include an entire buildable project directory, for each selected module, within your assembly. This is useful to give your users the chance to tinker with your project, then build it on their own.
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.2.0 http://maven.apache.org/xsd/assembly-2.2.0.xsd"> [...] <moduleSets> [...] <moduleSet> [...] <sources> <fileSets> <fileSet> <excludes> <exclude>target/**</exclude> </excludes> </fileSet> </fileSets> </sources> </moduleSet> </moduleSets> </assembly>
NOTE: We exclude the target directory, since this is assumed to be temporary storage for files produced during the course of a Maven build. Permanent project files are not meant to reside here...
Consolidating All Module Sources into a Single Directory Structure
Normally, each module processed by the assembly plugin is placed within its own directory structure inside the assembly root directory. For module sources, the default name of this module-specific directory is the module's artifactId
.
However, in some cases you may want to consolidate module sources into the same directory structure, based in the assembly root directory. To do this, simply set the includeModuleDirectory
flag to false
.
Example: Copy all module sources into a single src
directory
When providing a source reference to users, you may want to produce a single, consolidated source directory containing all of the source files from your multimodule hierarchy.
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.2.0 http://maven.apache.org/xsd/assembly-2.2.0.xsd"> [...] <moduleSets> [...] <moduleSet> [...] <sources> <includeModuleDirectory>false</includeModuleDirectory> <fileSets> <fileSet> <outputDirectory>src</outputDirectory> <includes> <include>src/**</include> </includes> </fileSet> </fileSets> </sources> </moduleSet> </moduleSets> </assembly>
Excluding Modules of Modules from Direct Assembly Processing
When dealing with project sources in a complex multimodule build consisting of several layers of module groupings, it's sometimes desirable to process only the top layer of modules, and provide fileSet
specifications to handle sub-modules. This can make it much easier to preserve the project-directory structure, since it doesn't force all modules - regardless of their location within the project hierarchy - through a flat module-processing mechanism. Processing only the first level of modules is the default configuration for the sources
section of a moduleSet
.
To explicitly process modules of modules - sub-modules, that is - simply use the excludeSubModuleDirectories
flag, set to false
.
Example: Providing a shallow source-directory structure for reference
Consider the case where you want to preserve the context of all source files within your project hierarchy, according to the project in which they belong. At the same time, you want to avoid confusing users with a complex nesting of projects within projects, and present a simple list of projects to browse.
If your project hierarchy looks like this:
+ application | + src | + project1 | | | + src | | | + project1-child1 | | | | | + src | | | + project1-child2 | | | | | + src | + project2 | + src | + project2-child1 | + src
You may want it to look like this in the resulting assembly:
+ application | | | + src | + project1 | | | + src | + project1-child1 | | | + src | + project1-child2 | | | + src | + project2 | | | + src | + project2-child1 | + src
To accomplish this restructuring, simply use the excludeSubModuleDirectories
flag, as follows:
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.2.0 http://maven.apache.org/xsd/assembly-2.2.0.xsd"> [...] <moduleSets> [...] <moduleSet> [...] <sources> <excludeSubModuleDirectories>false</excludeSubModuleDirectories> <fileSets> <fileSet> <includes> <include>src/**</include> </includes> </fileSet> </fileSets> </sources> </moduleSet> </moduleSets> </assembly>
Including Module Binaries
WARNING! Using the binaries
section of a moduleSet
definition involves some tricky considerations that are a result of the way Maven sorts and executes project builds within a multimodule context. Please read this FAQ entry if you decide to use them.
In cases where your assembly artifact is meant to be used in a runtime context, you'll most likely want to include the binaries from any modules processed by the assembly plugin. This can be as simple as adding the module's jar artifact to your assembly archive; or, it can involve selectively including the dependencies of that module in addition to the module's own jar.
At any rate, processing module binaries is an artifact-based activity. Accordingly, selection of the appropriate artifacts for a given module follows the artifact inclusion rules explained in the Advanced Assembly-Descriptor Topics document.
Once you've selected which artifacts should be processed for a particular module, you have several options for how to process them. In its simplest form, the binaries
section of a moduleSet
has many of the same characteristics as a dependencySet
. That is, you have the option to specify an outputDirectory
, and you can choose whether to unpack the artifact(s) - the default action will unpack them.
Processing a Module's Attachment Artifacts
Sometimes it's important to have the option to add artifacts from a module that are not the main project artifact. Such artifacts might include javadocs, project sources, or even other assembly artifacts.
Example: Including other assemblies within the current assembly
Suppose we have the following project structure:
+ application | + app-db | + app-web | + app-site
Further, suppose that the assembly plugin is currently executing at the application
level, but that another assembly archive has been created previously for the app-site
project. This other assembly archive is a zip file containing the project website. We want to include a copy of this website in the application distribution assembly, which we are creating now.
Finally, suppose that the website-attachment has a classifier of site
taken from the assemblyId.
Since the zipfile containing the website produced by app-site
is an attached artifact in that module, we'll need to extract that artifact instead of the main project artifact.
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.2.0 http://maven.apache.org/xsd/assembly-2.2.0.xsd"> [...] <moduleSets> <moduleSet> <includes> <include>*:app-site</include> </includes> <binaries> <attachmentClassifier>site</attachmentClassifier> <outputDirectory>doc</outputDirectory> <outputFileNameMapping>website.${module.extension}</outputFileNameMapping> </binaries> </moduleSet> [...] </moduleSets> </assembly>
Excluding Module Dependencies
Just like any binary, modules usually have runtime dependencies, without which they will simply fail to execute. By default, module dependencies are included when the module itself is included. However, as we saw in the above example, there are times when this may not be appropriate.
In the above example, the module binary included was an assembly artifact that contained the website for the application. Other assemblies might embody a completely self-contained version of the module's binaries, with all dependency classes unpacked and inlined within the archive.
In short, sometimes we want to turn off automatic dependency inclusion. We can achieve this by setting the includeDependencies
flag to false
.
Example: Including a jar-with-dependencies
module assembly
Suppose we have the following project structure:
+ application | + app-db | + app-web
Further, suppose that the assembly plugin is currently executing at the app-web
level, but that another assembly archive has been created previously for the app-db
project using the built-in jar-with-dependencies
assembly descriptor. This assembly archive contains all of the module dependencies, so it's not necessary to include this module's dependencies in the current assembly.
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.2.0 http://maven.apache.org/xsd/assembly-2.2.0.xsd"> [...] <moduleSets> <moduleSet> <includes> <include>*:app-db</include> </includes> <binaries> <attachmentClassifier>jar-with-dependencies</attachmentClassifier> <outputDirectory>lib</outputDirectory> <outputFileNameMapping>${module.artifactId}-${module.version}-${module.classifier}.${module.extension}</outputFileNameMapping> </binaries> </moduleSet> [...] </moduleSets> </assembly>
NOTE: The binaries
section still accommodates direct <includes/>
and <excludes/>
subsections, for specifying which module-dependencies to include in the assembly. However, these are deprecated, and only provided for backward compatibility.