Search code examples
mavenmaven-assembly-plugin

Maven assembly: generate a resource zip file and include it into the main assembly zip file


How can I proceed to include a generated zip file into a main zip file with the Maven Assembly plugin?

For example, I have the following folder structure:

./folderA/
./file1

and I want to generate a zip file where the content is like this:

folderA.zip
file1

Here my simplified config':

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project >
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <appendAssemblyId>false</appendAssemblyId>
                    <descriptor>${basedir}/assembly-zipFolderA.xml</descriptor>
                    <finalName>folderA.zip</finalName>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <appendAssemblyId>false</appendAssemblyId>
                    <descriptor>${basedir}/assembly.xml</descriptor>
                    <finalName>${module-zipFinalName}</finalName>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

assembly-zipFolderA.xml

<assembly>
    <id>folderA-zip</id>
    <includeBaseDirectory>false</includeBaseDirectory>
    <formats>
        <format>zip</format>
    </formats>

    <fileSets>
        <fileSet>
            <directory>folderA</directory>
            <outputDirectory>/</outputDirectory>
        </fileSet>
    </fileSets>
</assembly>

assembly.xml

<assembly>
    <id>main</id>
    <includeBaseDirectory>false</includeBaseDirectory>
    <formats>
        <format>zip</format>
    </formats>

    <files>
        <file>
            <source>file1</source>
        </file>
        <file>
            <source>folderA.zip</source>
        </file>
    </files>
</assembly>

===> with this config, Maven complains that it can't find folderA.zip...


Solution

  • Don't declare the plugin twice; instead, you need to declare two executions of the maven-assembly-plugin.

    The first execution will create the first assembly and then, the second execution will use this assembly to create the final one. Both of those executions will be bound to the package phase, and Maven will invoke the plugin's execution in the order of declaration in the POM.

    <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>2.6</version>
        <executions>
            <execution>
                <id>make-folderA</id>
                <goals>
                    <goal>single</goal>
                </goals>
                <phase>package</phase>
                <configuration>
                    <appendAssemblyId>false</appendAssemblyId>
                    <descriptors>
                        <descriptor>${basedir}/assembly-zipFolderA.xml</descriptor>
                    </descriptors>
                    <finalName>folderA</finalName> <!-- name without extension -->
                    <attach>false</attach>
                </configuration>
            </execution>
            <execution>
                <id>make-assembly</id>
                <goals>
                    <goal>single</goal>
                </goals>
                <phase>package</phase>
                <configuration>
                    <appendAssemblyId>false</appendAssemblyId>
                    <descriptors>
                        <descriptor>${basedir}/assembly.xml</descriptor>
                    </descriptors>
                    <finalName>${module-zipFinalName}</finalName>
                </configuration>
            </execution>
        </executions>
    </plugin>
    

    A couple of notes:

    • The <finalName> should not contain the extension, so a finalName of folderA will produce the archive folderA.zip after the ZIP assembly is made.
    • The first assembly will be created inside the build directory, which is target by default. As such, the second one needs to reference it there with:

      <file>
          <source>${project.build.directory}/folderA.zip</source>
      </file>
      

      in its assembly descriptor.

    • Since the first assembly is not the final one, you probably don't want it attached, i.e. as an additional artifact produced by your project. You can disable this by setting attach to false. This will make sure only the last final one is considered when deploying or releasing.

    • descriptor is a deprecated parameter, you should use descriptors instead.

    With such a configuration, running mvn clean package will produce the correct archive inside the build folder.