How to run a Scala SBT-packaged jar file with Java (the `java` command)

If you want to run/execute a main method from a jar file you created with Scala and the sbt package command, this tutorial shows how to do it. To make things a little more complicated, my Scala project depends on three external jar files, and the main method requires a command-line argument.

Note 1: As I note in the Summary, you’ll probably want to use a tool like sbt-assembly for larger projects.

Note 2: This article was originally written in 2015, and used Scala 2.11. That being said, everything still seems nearly the same in late 2020.

Solution

I’m currently writing a little Scala code to download stock market quotes for my Radio Pi project, and I’m going to deploy the code to a “production” Raspberry Pi server that currently has Java installed on it, but not Scala. (It looks like you can run Scala on an RPI, but for the moment I was curious how to get this working.)

The first step in the solution is to package my Scala project with the SBT package command. I run the following command from the root directory of my Scala project to do that:

$ sbt package

There’s a bunch of output from that command, but the final file it generates has this name:

target/scala-2.11/stockquotes_2.11-1.0.jar

For the purposes of this article I’ll rename that file to:

stockquotes.jar

This jar file depends on these other jar files, which are in my project’s lib folder:

htmlcleaner.jar
lift-json.jar
paranamer.jar

The solution to my problem requires that I use the scala-library.jar file as another dependency, so I find it at /Users/al/bin/scala/lib/scala-library.jar, and copy it to my local folder.

Now, if you assume that (a) I have copied all of those jar files to the current directory; (b) the application requires a configuration file be passed to the app on the command line; (c) the package for the application is com.alvinalexander; and (d) the first line of the application looks like this:

object GetStockQuotes extends App {

then the java command to run my application looks like this:

java -cp \
    "htmlcleaner.jar:lift-json.jar:paranamer.jar:scala-library.jar:stockquotes.jar" \
    com.alvinalexander.GetStockQuotes$delayedInit$body \
    stocks.conf

I put that command in a shell script, and I use the \ characters to spread the full command across multiple lines to make it more readable.

A few “tricks” of this solution are:

  • Knowing how to use the java -cp approach.
  • Knowing that you need include the scala-library.jar file.
  • Knowing that the main method for a Scala object defined with “extends App” will look like com.alvinalexander.GetStockQuotes$delayedInit$body.

(Note that you should not include “.class” after the $body part of that name. For some reason I kept adding “.class” after it today, and of course it kept failing until I saw what I had done.)

Summary

Note that while this solution works for small projects like this, you’ll probably want to use the SBT-Assembly plugin for larger projects. I wrote about how to do that in Recipe 18.14 of the Scala Cookbook.

In summary, if you wanted to see how to execute the main method in a Scala jar file with the java command, where the Scala jar file depends on external dependencies, I hope this example is helpful.