ACA Blog

ACA Blog

March 2021


Creating an esrow package with Maven

Dorien JorissenDorien Jorissen

Due to various contractual & legal circumstances you might sometimes be required to provide an escrow package to your customer. With regards to software this means you need to provide enough data for the client to be able to continue maintenance of the code in case of bankruptcy of your company or failure to comply to the terms of the contract. In this case the word data comprises several things:

Because our Java projects always use Maven for builds, releases and dependency management it would be nice to be able to use Maven to build an escrow package as this would ensure that it is an automated and repeatable process. As a lazy developer I of course first searched around to find an existing Maven plugin that already does what I want and I was able to find exactly 1, the escrow-maven-plugin, but sadly it’s just an empty project. As there isn’t a ready made plugin available our next option is to try and combine several other plugins in such a way that we achieve the desired goal. After a lot of trial and error this was achieved using the following plugins:


While there are a number of public Maven repositories available (Maven CentralSonatype,JBoss<, etc…) it is always useful to have your own Maven repository at company level to proxy other repositories, provide storage for your own released artifacts, etc… and usually also to store artifacts that aren’t available in public repositories. It is this last reason that poses a problem in our escrow scenario, because if all dependencies would be publicly available you’d only need to provide your product’s sources (containing your POM files) and a simple mvn clean package should produce a working binary.

But when your project uses non-public dependencies the story is a bit more complicated as you’ll also need to provide all the dependencies for the build to succeed. Using the maven-dependency-plugin we’re able to retrieve all these dependencies, in Maven repository format, so that the maven-assembly-plugin is able to pick them all up and put them together into a subdirectory of your escrow package. Someone that has this escrow package will then just have to simply copy over the contents of the mentioned subdirectory to his own (local) Maven repository and then the build will be able to pick them up correctly.

To enable this behaviour you just need to add the following XML piece to the build plugins section of the root POM of your Maven multi-module:

Putting this plugin in the root POM will make sure it gets triggered for all modules. If you have some modules for which you don’t want it or need it to be triggered you can just add a plugin configuration to the modules that sets the plugin’s skip property to true. The plugin will produce a mini Maven repository, by means of the copyPomand useRepositoryLayout properties that are set to true in the plugin configuration, in adependencies subdirectory of each module’s target directory that will be used by the assembly plugin later in the escrow package project. If you like you can also use theexcludeGroupIds property to exclude the module artifacts themselves from the dependencies directory.


A custom assembly is the main part that does the heavy lifting in creating the escrow package. This versatile Maven plugin allows you to define, by means of an XML based assembly descriptor (it’s Maven so what else did you expect), how you want to package the different pieces of you multi-module project into 1 or more assemblies.

We’ll define this custom assembly descriptor in a separate submodule named escrow of our project with its packaging type set to pom. You’ll need to add this module as the last module in the list of modules of the root POM to make everything work. If the module isn’t last in the list the Maven livecycle will create problems and the escrow package building will fail because some artifacts won’t be available yet.

Before we get to the actual content of the assembly descriptor 2 other things need to present in the escrow module POM for everything to work correctly. Firstly the maven-assembly-plugin needs to be called:

Adding this build section to the escrow module POM will make sure the plugin gets called during the package phase using the custom assembly descriptorsrc/assembly/assembly.xml (also located in the escrow module) and giving the resulting escrow package a certain name.

Secondly you’ll also need to define all other modules, of which you want to use the sources & dependencies in your escrow package, as dependencies of the escrow module. Important to note here is that each of these dependencies needs to have a valid type tag (usually containing the values jar, war or ear):

Now we only need to define our custom assembly descriptor XML file. You can do this by adding a file assembly.xml to the src/assembly directory of the escrow module (create it if necessary) with the following content:

  • formats: the result is a ZIP file
  • moduleSets: the sources of all modules should be included and some unnecessary files should be excluded (IDE files, etc…)
  • fileSets: copies over the dependencies of all the modules defined as a separate fileSet here and what should be included (all file types in a Maven repo: jar, pom & xml) and excluded
  • files: included the root POM

Creating & using the escrow package

After all this configuration and setup, creating the escrow package is as easy as executing the command mvn clean package in the root of your project. This will create a ZIP file in the targetdirectory of the escrow module. If you provide this ZIP file to a customer they can easily recreate everything by just unzipping it, copying over the contents of the dependencies subdirectory to their local Maven repository (located in the .m2/repository directory in the user home directory) and also executing mvn clean package from the root of the unzipped package.

This type of escrow package has only 1 potential drawback: it relies on a set of dependencies, especially those use by Maven itself, being available in public repositories. If this isn’t satisfactory for you client analternative could be to remove the dependency plugin configuration (also the part that copies them over in the assembly descriptor), clean your local Maven repository, run mvn clean package and make a second ZIP file of the state of your local repository. The combination of both ZIP files, the source ZIP that Maven will create and the ZIP of your local Maven repository, should resolve your clients issues.