1

I have a project where I am trying to create a fat jar using the sbt-assembly plugin. When I attempt to run my main class from the jar using the java -jar command, I get the error message: Error: Could not find or load main class com.gordon.timeshare.apps.TimeShareLauncher.

I only have one main class in my project (I use the extends App syntax to accomplish this), so I do not specify the path to the main class explicitly, although I have tried that and it did not help.

Below are all the settings I have in my build.sbt file.

ThisBuild / version := "0.1.0-SNAPSHOT"
ThisBuild / organization := "com.gordon.timeshare.apps"
ThisBuild / scalaVersion := "2.13.5"

lazy val app = (project in file("app"))
  .settings(
    assembly / mainClass := Some("com.gordon.timeshare.apps.TimeShareLauncher"),
    assembly / assemblyJarName := "TimeShareLauncher.jar"
  )

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

I have also tried other strategies like deduplicate, but that would give me an error when trying to make the .jar.

Additionally, when making the .jar, I get a warning:

[warn] Could not create directory C:\Users\dgord\workspace\new-timeshare\timeshare\target\streams\_global\assembly\_global\streams\assembly\88fbe735ce5abc6987fbc59b072404628cdc94b4_a99f2fe2a42747ed9809d4f62f51a9e1b336dde8_da39a3ee5e6b4b0d3255bfef95601890afd80709\META-INF\versions\9: java.nio.file.FileAlreadyExistsException: C:\Users\dgord\workspace\new-timeshare\timeshare\target\streams\_global\assembly\_global\streams\assembly\88fbe735ce5abc6987fbc59b072404628cdc94b4_a99f2fe2a42747ed9809d4f62f51a9e1b336dde8_da39a3ee5e6b4b0d3255bfef95601890afd80709\META-INF\versions\9

And in case you want to know what my main class looks like:

package com.gordon.timeshare.apps

object TimeShareLauncher extends App
  • sbt: 1.4.7 (also tried 1.5.5)
  • sbt-assembly: 1.1.0
  • scala 2.13.5

I have also tried this on WSL and had the same result.

DanGordon
  • 671
  • 3
  • 8
  • 26
  • 1
    Your error says it's looking for `com.gordon.apps.TimeShareLauncher` but your class is `com.gordon.timeshare.apps.TimeShareLauncher` – Gaël J Nov 15 '21 at 20:33
  • @GaëlJ fixed that, I still have the same issue. I've updated what my build file looks like. – DanGordon Nov 15 '21 at 20:42
  • 2
    @DanGordon Could you unzip the content of the fat jar and make sure that the following holds. 1. there is file `com/gordon/timeshare/apps/TimeShareLauncher.class`. 2. There is a file `META-INF/Manifest.txt` with content `Main-Class: com.gordon.timeshare.apps.TimeShareLauncher` – Ivan Stanislavciuc Nov 15 '21 at 21:57
  • 1
    Dont forget to `reload` the build.sbt file after modification – ccheneson Nov 15 '21 at 23:04
  • @IvanStanislavciuc the manifest file has `Main-Class: com.gordon.timeshare.apps.TimeShareLauncher`, however the class does not appear to be in the .jar, which makes sense that it's not finding it. I just don't understand why it's not being added to the .jar. – DanGordon Nov 16 '21 at 00:36
  • Answered my own question below. The issue was with `lazy val app = (project in file("app"))`. Should have been `lazy val app = (project in file("."))` – DanGordon Nov 16 '21 at 18:11
  • Does this answer your question? [How to set main class in build?](https://stackoverflow.com/questions/6467423/how-to-set-main-class-in-build) – Tomer Shetah Nov 21 '21 at 22:10

1 Answers1

1

The issue is with lazy val app = (project in file("app")). Assuming a single module project with no module named app, sbt-assembly will create a directory named app and attempt to stuff the build in there. However, since the main class is not in the app bundle, the class will not be added to the jar file.

The correct way to do this is:

lazy val app = (project in file(".")), which specifies the current directory as the one to look for the main class. So this was not really an issue with knowing how to use the sbt-assembly plugin, but a more general issue with specifying projects in an sbt build.

DanGordon
  • 671
  • 3
  • 8
  • 26