views:

1721

answers:

3

Hi, I'm using the Maven 2 assembly plug-in to build a jar-with-dependencies and make an executable JAR file. My assembly includes Spring, and the CXF library.

CXF includes copies of META-INF files spring.schemas and spring.handlers which end up clobbering the similar files from the spring-2.5.4 jar.

By hand, I can update those two files within the jar-with-dependencies.

What I'm looking for is some way in the Maven POM to direct the assembly plug-in to get the correct version of those two files.

The assembly plug-in documentation talks about file filtering, but doesn't seem to have configuration for or parameters, without going to the trouble of creating a custom assembly descriptor.

Is making a custom assembly descriptor my only hope in this instance?

+1  A: 

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.

Mojo
+1  A: 

I would suggest using the maven-shade-plugin instead. If you look at the pom for the cxf-bundle (http://svn.apache.org/repos/asf/cxf/trunk/distribution/bundle/all/pom.xml) you can see how you can use the shade transformers to merge the spring.schemas and other necessary files.

Daniel Kulp
This is also described nicely at http://www.hagelnx.com/prog/814.
Andrew Swan
+1  A: 

You can also work around the problem by getting the spring.schemas and spring.handlers files from the spring distro you want and put them in your projects src/main/resources/META-INF directory. Since those are packaged last, you'll get the version you want. I found the idea here

harschware