How to create a self-contained jar file (fat jar) using sbt
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
- Alexander, Alvin. Scala/SBT: How to deploy a single, executable Jar file (sbt-assembly).