Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Maven 2 assembly plugin clobbers some META-INF files

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?

like image 860
Mojo Avatar asked Jun 09 '09 16:06

Mojo


5 Answers

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>
like image 192
magiconair Avatar answered Nov 10 '22 07:11

magiconair


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>
like image 42
amir Avatar answered Nov 10 '22 06:11

amir


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.

like image 25
Daniel Kulp Avatar answered Nov 10 '22 08:11

Daniel Kulp


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.

like image 22
Mojo Avatar answered Nov 10 '22 08:11

Mojo


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

like image 42
harschware Avatar answered Nov 10 '22 08:11

harschware