It turns out the root of my problem was a conflict with the javax.ws.rs.ext.Providers file, which occurs when the maven build plugin creates a jar. (This file can be found in uberjar at META-INF → services → javax.ws.rs.ext.Providers)
The Providers file contains a list of available provider classes. In the dependencies of my project, this file exists in more than one place, and different copies contain different lists of providers. The maven build plugin simply selects one version to be included in the jar, and therefore, at run time, the required "writer" class cannot be found: this class is not specified in the Providers file in the jar.
I used the maven shade plugin to solve this problem. The shadow plugin contains a tool for selectively combining duplicate files contained in a dependency tree. Inside pom.xml:
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <resource>META-INF/services/javax.ws.rs.ext.Providers</resource> </transformer>
Tells maven to merge, adding any duplicates of javax.ws.rs.ext.Providers.
In addition, by installing the maven shade plugin to execute during the package phase of my build, and then the maven build plugin to execute during the install phase, I was able to create an executable uberjar and then a package that is uberjar in the .zip file, all with a simple call to mvn clean install .
Here is what my pom.xml looks like:
<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"> <modelVersion>4.0.0</modelVersion> <parent> ... </parent> <groupId>com.foo.bar</groupId> <artifactId>my-app</artifactId> <packaging>jar</packaging> <version>2.1.0.0-SNAPSHOT</version> <name>My App</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <issues-product>MyApp</issues-product> <issues-component>MY-APP</issues-component> </properties> <dependencies> ... </dependencies> <build> <finalName>${project.artifactId}</finalName> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>2.1</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <createDependencyReducedPom>false</createDependencyReducedPom> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>com.foo.bar.MyMainClass</mainClass> </transformer> <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <resource>META-INF/services/javax.ws.rs.ext.Providers</resource> </transformer> </transformers> <filters> <filter> <artifact>*:*</artifact> </filter> </filters> </configuration> </execution> </executions> </plugin> <plugin> <artifactId>maven-assembly-plugin</artifactId> <version>2.2.2</version> <configuration> <finalName>${project.artifactId}</finalName> <appendAssemblyId>false</appendAssemblyId> <descriptors> <descriptor>src/assembly/my-app-assembly.xml</descriptor> </descriptors> </configuration> <executions> <execution> <phase>install</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </project>
And here is my-app-assembly.xml:
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/2.2.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/2.2.2 http://maven.apache.org/xsd/assembly-2.2.2.xsd"> <id>bin</id> <formats> <format>zip</format> </formats> <includeBaseDirectory>false</includeBaseDirectory> <fileSets> <fileSet> <directory>${project.basedir}</directory> <outputDirectory/> <includes> <include>Readme.pdf</include> <include>config\</include> <include>input\</include> <include>output\</include> </includes> </fileSet> <fileSet> <directory>${project.build.directory}</directory> <outputDirectory>bin\java\</outputDirectory> <includes> <include>my-app.jar</include> </includes> </fileSet> </fileSets> </assembly>
caffreyd
source share