Maven 2 assembly plugin clobbers some META-INF files

For some reason the solution that Mojo and the others are suggesting still doesn't work for me. I've created my custom spring.handlers and spring.schemas files and put them under src/main/resources/META-INF. However, when using the unpackOptions my files are not included as well. When I don't use the unpackOptions my files aren't the ones in the jar.

What I ended up doing is to reference the files directly. This finally put my files into the JAR.

<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
    <!-- TODO: a jarjar format would be better -->
    <id>jar-with-dependencies</id>
    <formats>
        <format>jar</format>
    </formats>
    <includeBaseDirectory>false</includeBaseDirectory>
    <dependencySets>
        <dependencySet>
            <outputDirectory>/</outputDirectory>
            <unpack>true</unpack>
            <unpackOptions>
                <excludes>
                    <exclude>META-INF/spring.handlers</exclude>
                    <exclude>META-INF/spring.schemas</exclude>
                </excludes>
            </unpackOptions>
            <scope>runtime</scope>
        </dependencySet>
    </dependencySets>
    <files>
        <file>
            <source>${project.basedir}/src/main/resources/META-INF/spring.handlers</source>
            <outputDirectory>META-INF</outputDirectory>
        </file>
        <file>
            <source>${project.basedir}/src/main/resources/META-INF/spring.schemas</source>
            <outputDirectory>META-INF</outputDirectory>
        </file>
    </files>
</assembly>

I would suggest using the maven-shade-plugin instead. If you look at the pom for the cxf-bundle (https://github.com/apache/cxf/blob/master/pom.xml) you can see how you can use the shade transformers to merge the spring.schemas and other necessary files.


I tried the shade plugin approach and it worked very nicely. Here is all you need to put in your POM (no assembly plugin needed).

      <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>1.4</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <transformers>
                            <transformer
                                implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                <mainClass>org.example.Runner</mainClass>
                            </transformer>
                            <transformer
                                implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                <resource>META-INF/spring.handlers</resource>
                            </transformer>
                        </transformers>
                    </configuration>
                </execution>
            </executions>
        </plugin>

I worked it out, and here are the details:

First, there's no way to specify file includes or excludes if you use the built-in assembly descriptor jar-with-dependencies.

The assembly plug-in documentation gives the sample jar-with-dependencies descriptor here.

I copied and pasted that descriptor to a file in my project directory called exec-jar.xml. Then in the pom, I changed the assembly plug-in to reference that descriptor. Here's the excerpt:

<build>
  <plugins>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>2.2-beta-3</version>
        <configuration>
            <descriptors>
                <descriptor>exec-jar.xml</descriptor>
            </descriptors>
            <archive>
                <manifest>
                    <mainClass>com.package.MyMainClass</mainClass>
                </manifest>
            </archive>
        </configuration>
        <executions>
            <execution>
                <id>make-assembly</id>
                <phase>package</phase>
                <goals>
                    <goal>single</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
  </plugins>
</build>

That bit of descriptor binds the assembly to the package phase of the life-cycle, and references the exec-jar.xml descriptor. Doing that package confirmed that the jar was built just as it was with the predefined descriptor.

So then it becomes a matter of modifying exec-jar.xml to exclude the CXF files that conflict with the Spring files. Here is my assembly descriptor that accomplished that:

<assembly>
  <id>jar-with-dependencies</id>
  <formats>
    <format>jar</format>
  </formats>
  <includeBaseDirectory>false</includeBaseDirectory>
  <dependencySets>
    <dependencySet>
      <unpack>true</unpack>
      <unpackOptions>
        <excludes>
            <exclude>cxf*/META-INF/spring.handlers</exclude>
            <exclude>cxf*/META-INF/spring.schemas</exclude>
        </excludes>
      </unpackOptions>
      <scope>runtime</scope>
    </dependencySet>
  </dependencySets>
  <fileSets>
    <fileSet>
      <directory>${project.build.outputDirectory}</directory>
    </fileSet>
  </fileSets>
</assembly>

Now here's the rub. If you do this with the currently released assembly plug-in, version 2.1, it will fail on the tag as "unexpected." The tag is supported in unreleased version 2.2 of the plug-in. Note in my pom file excerpt above, I specify maven-assembly-plugin version 2.2-beta-3 which was the latest at the time of writing.

This successfully built an executable jar, and Spring had all of the handlers and schemas it needed to initialize my app.