How to make an executable jar file for deployment in scala

Reading Time: 3 minutes

The importance of writing this blog is to solve the following problem(creating executable jar file) which I faced during my project. In this blog, we see a simple scala application i.e “HelloWorld”

object HelloWorld extends App {
  println("Hello , This is knoldus world")
}

Problem:

We all know that the “sbt package” command is used to create a jar file of a scala application. When I tried to run a jar file it shows the following error.

knoldus@knoldus-Vostro-3559:~/IdeaProjects/HelloWorld$ java -jar target/scala-2.13/helloworld_2.13-0.1.jar
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.NoClassDefFoundError: scala/Function0
        at java.lang.Class.getDeclaredMethods0(Native Method)
        at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
        at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
        at java.lang.Class.getMethod0(Class.java:3018)
        at java.lang.Class.getMethod(Class.java:1784)
        at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544)
        at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526)
Caused by: java.lang.ClassNotFoundException: scala.Function0
        at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        ... 7 more

The created jar file is not executable.

Solution:

Now, before going to see the solution we first understand why this problem occurs. When you uses Simple Build Tool Command ‘sbt package’, it creates a jar file that includes the class files from your source code and also the content from your src/main/resources folder.

But there are mainly two things which is important to execute jar file, are not included

  1. Your project dependencies (JAR files in your project’s lib folder or managed dependencies declared in build.sbt).
  2. Libraries from the Scala distribution that are needed to execute the JAR file with the java command.

This made difficult for me to use that jar file in a Dockerfile for the purpose of deployment.

There are two or maybe more things you can do to solve this problem: we see the following two by using which I solved my problem.

  1. Use an SBT plug-in such as sbt-assembly to build a single, complete JAR file that can be executed with a simple java command. This requires that Java is installed on client systems.

Steps:

  1. Add the given plugin in plugins.sbt file of your project.
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.6")

2. Create a jar file using ‘sbt assembly’ command.

knoldus@knoldus-Vostro-3559:~/IdeaProjects/HelloWorld$ sbt assembly

If you run ‘sbt assembly’ command before adding plugin it shows errors.

knoldus@knoldus-Vostro-3559:~/IdeaProjects/HelloWorld$ sbt assembly
[info] Loading global plugins from /home/knoldus/.sbt/1.0/plugins
[info] Loading project definition from /home/knoldus/IdeaProjects/HelloWorld/project
[info] Loading settings for project helloworld from build.sbt ...
[info] Set current project to HelloWorld (in build file:/home/knoldus/IdeaProjects/HelloWorld/)
[error] Expected ';'
[error] Not a valid command: assembly
[error] Not a valid project ID: assembly
[error] Expected ':'
[error] Not a valid key: assembly
[error] assembly
[error]         ^

3. Run jar file

knoldus@knoldus-Vostro-3559:~/IdeaProjects/HelloWorld$ java -jar target/scala-2.13/HelloWorld-assembly-0.1.jar
Hello , This is knoldus world

2. Distribute all the JAR files necessary with a script that builds the classpath and executes the JAR file with the scala commands. This requires that Scala be installed on client systems.

The .jar file created by SBT is executable by scala interpreter or scala commands but not by the java command(i.e java -jar name-of-file.jar). The reasion behind this , jar created by ‘sbt package’ have dependency on scala class files which are not included in the file. so java command is not able to execute this jar file where scala is !

Steps:

  1. We take the same example mention above. Run ‘sbt package’
knoldus@knoldus-Vostro-3559:~/IdeaProjects/HelloWorld$ sbt package
[info] Loading global plugins from /home/knoldus/.sbt/1.0/plugins
[info] Loading settings for project helloworld-build from plugins.sbt ...
[info] Loading project definition from /home/knoldus/IdeaProjects/HelloWorld/project
[info] Loading settings for project helloworld from build.sbt ...
[info] Set current project to HelloWorld (in build file:/home/knoldus/IdeaProjects/HelloWorld/)
[success] Total time: 1 s, completed 15 Dec, 2019 6:01:03 PM

2. Try using java command to run this file. It gives error

Error: Unable to access jarfile target/helloworld_2.13-0.1.jar

3. Run using ‘sbt run’ command .

knoldus@knoldus-Vostro-3559:~/IdeaProjects/HelloWorld$ sbt run target/scala-2.13/helloworld_2.13-0.1;
[info] Loading global plugins from /home/knoldus/.sbt/1.0/plugins
[info] Loading settings for project helloworld-build from plugins.sbt ...
[info] Loading project definition from /home/knoldus/IdeaProjects/HelloWorld/project
[info] Loading settings for project helloworld from build.sbt ...
[info] Set current project to HelloWorld (in build file:/home/knoldus/IdeaProjects/HelloWorld/)
[info] running HelloWorld 
Hello , This is knoldus world
[success] Total time: 1 s, completed 15 Dec, 2019 6:22:59 PM

So, this is all about executable jar file, Now if you want to deploy jar artifact using docker, you can Learn here!

1 thought on “How to make an executable jar file for deployment in scala4 min read

Comments are closed.