Petr Kozelka

How to build a ZIP output artifact in Maven

22 October 2009 -

It's quite a common situation that you have a bunch of files, most or all of them committed in svn, and need to make a release of this so that it can be reused with the Maven's dependency mechanism.

There are several ways how to accomplish that:

  • use maven-assembly-plugin
  • use maven-antrun-plugin to build and build-helper-maven-plugin to attach
  • create custom plugin that handles both packaging and attaching

Each of them has its advantages in some situations, but my favorite is the second option for most cases.

Real life example - artifact with various svn output files

In some of my projects, I need to check that the code works properly with xml output files from Subversion. I could easily put such files among test resources, but the it would be there many times, and I would always have to check if it is "representative" enough etc.

So I decided to create a module, which will create the data during its build (see the maven-antrun-plugin).

These data are packaged into a zip file which is then marked as output artifact with type "zip" (see the build-helper-maven-plugin).

Look at this pom excerpt  (complete pom.xml is available here):

<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/xsd/maven-4.0.0.xsd">
  <groupId>net.sf.buildbox.testdata</groupId>
  <artifactId>svn-mvn-testdata</artifactId>
  <version>1-SNAPSHOT</version>
  <packaging>pom</packaging>
...
  <build>
    <outputDirectory>target/output</outputDirectory>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-antrun-plugin</artifactId>
        <version>1.3</version>
        <executions>
          <execution>
... phase=package, goal=run
            <configuration>
              <tasks>
                <mkdir dir="${project.build.outputDirectory}"/>
                <exec executable="svn" failonerror="true" dir="${project.build.outputDirectory}" taskname="svn-checkout">
...
                </exec>
...
                <zip destfile="${project.build.directory}/${project.build.finalName}.zip">
...
                </zip>
              </tasks>
            </configuration>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>build-helper-maven-plugin</artifactId>
        <version>1.2</version>
        <executions>
... phase=package, goal=attach-artifact
            <configuration>
              <artifacts>
                <artifact>
                  <file>${project.build.directory}/${project.build.finalName}.zip</file>
                  <type>zip</type>
                </artifact>
              </artifacts>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

What are the advantages over other mentioned alternatives ?

  • extensibility - the "generator" part is straightforward, so, as long as ant is enough for us it costs just a few lines of ant code
  • compactness - we could reach similar result with several invocations of exec-maven-plugin for preparing data, plus maven-assembly-plugin to pack and attach it, but that would be far far more verbose and harder to maintain

Just for completenes, it's good to say when using the other approaches is more relevant:

  • custom maven plugin - when the algorithm for generating data is too complex to be written in ant, or needs other sources that are not reachable from antrun, like dependencies
  • maven-assembly-plugin - when we need to control file permissions in tgz/gz packages while running the build on windows

Do you have experience in this area ? Then please post your comments...

Fork me on GitHub
Fork me on GitHub