Avoid the pain of uberjar/shade

So you want an executable jar. It’s got lots of dependent jars. What’s a geek to do?

There is the uberjar plugin for maven. But it doesn’t seem to be supported any more, it’s not in maven central, and some people report classloader issues (it works some classloader magic).

There is the Shade plugin for maven. But it unpacks (slowly) all jars into one, and has to resolve “overlapping” resources (e.g. “spring.handler” files).

But don’t despair! There is a third way! Jar files can be given a classpath via the manifest file and Maven can generate it for you…

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <configuration>
          <archive>
            <manifest>
              <addClasspath>true</addClasspath>
              <classpathPrefix>lib/</classpathPrefix>
              <mainClass>foo.bar.Baz</mainClass>
            </manifest>
          </archive>
        </configuration>
      </plugin>

Maven can also copy dependencies to a suitable location…

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <version>2.2</version>
        <executions>
          <execution>
            <id>copy-dependencies</id>
            <phase>package</phase>
            <goals>
              <goal>copy-dependencies</goal>
            </goals>
            <configuration>
              <outputDirectory>${project.build.directory}/lib</outputDirectory>
            </configuration>
          </execution>

Then to run it just…

java -jar myapp.jar

To deploy it requires copying more than one file, but that’s not necessarily a bad thing. In fact, 8/10 jar files prefer it. Jar. File. Fact.

Leave a Reply Cancel reply

Exit mobile version
%%footer%%