Reputation: 5825
I am creating a executable uber jar with the maven shade plugin, it has a dependency on some classes in a local system jar (mobile-dock-support.jar) that I want it to include during the package phase, so I have the shade plugin configured like so
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>uk.xxx.mobiledock.PCSyncApplication</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>uk.xxx</groupId>
<artifactId>mobile-dock-support</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>system</scope>
<systemPath>${project.build.directory}/../src/main/libs/mobile-dock-support.jar</systemPath>
</dependency>
</dependencies>
</plugin>
It seems to package the jar fine but when I run the jar using java -jar xxx.jar
it gives me the following
java.lang.NoClassDefFoundError: uk/xxx/mobiledock/MobileDockException
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Unknown Source)
at java.lang.Class.privateGetMethodRecursive(Unknown Source)
at java.lang.Class.getMethod0(Unknown Source)
at java.lang.Class.getMethod(Unknown Source)
at sun.launcher.LauncherHelper.validateMainClass(Unknown Source)
at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)
Caused by: java.lang.ClassNotFoundException: uk.xxx.mobiledock.MobileDockException
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 7 more
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main"
I've also setup the exec maven plugin, and running mvn exec:java -Dexec.mainClass=uk.xxx.mobiledock.PCSyncApplication
runs the program as expected.
Here's how exec maven plugin is setup
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.4.0</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<includePluginDependencies>true</includePluginDependencies>
<mainClass>uk.xxx.mobiledock.PCSyncApplication</mainClass>
</configuration>
<dependencies>
<dependency>
<groupId>uk.xxx</groupId>
<artifactId>mobile-dock-support</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>system</scope>
<systemPath>${project.build.directory}/../src/main/libs/mobile-dock-support.jar</systemPath>
</dependency>
</dependencies>
</plugin>
Upvotes: 4
Views: 5096
Reputation: 3204
I believe your approach may work but it is incorrect. The correct way is to use the install maven plugin to build in all the 3party dependencies you have. Here is an example with a proper way on how you can achieve it:
<dependencies>
<dependency>
<groupId>uk.xxx</groupId>
<artifactId>mobile-dock-support</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.0</version>
<executions>
<execution>
<phase>package</phase>
<id>shade-my-jar</id>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.handlers</resource>
</transformer>
<transformer
implementation="org.springframework.boot.maven.PropertiesMergingResourceTransformer">
<resource>META-INF/spring.factories</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.schemas</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>io.Adrestus.Backend.App</Main-Class>
</manifestEntries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<id>id0</id>
<phase>initialize</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<file>
${project.basedir}/../src/main/libs/mobile-dock-support.jar
</file>
<groupId>uk.xxx</groupId>
<artifactId>mobile-dock-support</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Upvotes: 1
Reputation: 5825
OK then it appears the issue is the shade plugin doesn't copy system dependencies to the uber jar. There are a couple of 'correct' ways of fixing this
Install the dependency to your local maven repository using mvn install
Use a repository manager such as Nexus
If however you're like me and didn't have the option of the above two as it's a collaborative project and there was no option for something like Nexus, then here is what I did to get it working
Use the maven dependency plugin to copy any system dependencies to somewhere relative to the packaged jar, eg.
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<includeArtifactIds>mobile-dock-support</includeArtifactIds>
</configuration>
</execution>
</executions>
</plugin>
Add the copied jars as part of the class path in the uber jar's manifest file eg.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>uk.xxx.mobiledock.PCSyncApplication</Main-Class>
<Class-Path>lib/mobile-dock-support-${mobile-dock-support.version}.jar</Class-Path>
</manifestEntries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
Upvotes: 2