avatar

Andres Jaimes

How to create a self-contained jar file (fat jar) using sbt

By Andres Jaimes

- 2 minutes read - 339 words

A fat jar is a jar file that contains any dependencies required by a Java or Scala program. Deployment becomes an easy task if we only have to deal with one single file. In this article we’ll go through the steps required to create a fat jar using Scala and sbt.

The following procedure has been tested using Scala 2.12.8, sbt 1.2.8 and jdk 11.

1. project/assembly.sbt

Create project/assembly.sbt and add the following line:

addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.6")

2. Optional step: project/resolvers.sbt

I had to add a library resolver to my project because my computer was using artifactory as a default repository. Without this file, I kept getting the following error every time I tried to create the self-contained file:

[error] Unable to find credentials for [Artifactory Realm @ example.com]

If you’re experimenting a similar issue, you can force sbt to use a specific repository by creating this file project/resolvers.sbt and adding the following line into it:

externalResolvers := Seq("central repository".at("https://repo1.maven.org/maven2/"))

3. build.sbt

Define your main class in build.sbt:

...
mainClass := Some("com.example.Main")

Optionally, you may want to add the following line as well in case you’re having the issue described in step 2:

externalResolvers := Seq("central repository".at("https://repo1.maven.org/maven2/"))

You can try to go on without it because externalResolvers may not be necessary in build.sbt. Unless of course you’re having an issue similar to the one described in step 2.

4. Create the self-contained jar

Use the following command to create the file:

sbt assembly

The resulting .jar file will be created into target/scala-2.12. We can now run it using:

java -jar fat-jar.jar

5. Troubleshooting

Depending on the libraries we are using, there is a chance we run into the following error:

java.lang.RuntimeException: deduplicate: different file contents found in the following:

According to this StackOverflow question adding the following lines to our build.sbt file should fix it.

assemblyMergeStrategy in assembly := {
 case PathList("META-INF", xs @ _*) => MergeStrategy.discard
 case x => MergeStrategy.first
}

Happy coding.

References