scala sbt assembly "no main manifest attribute" - scala

I use assembly plugin in sbt to assemble my project. But errors happen when run by "java -jar xx.jar" -
"no main manifest attribute".
I think it's because there are two files in my src/main/scala/ directory and each with an object extending Application which means there are two main entry in the project. But I need two applications, one is the server and the other is the test client.
How to handle this two-main-entry problem in scala sbt. Thanks in advance.

In your SBT build file, define the main class.
If you are using build.sbt, then that would be:
mainClass in assembly := Some("com.domain.Main")
If you are using Build.scala then you could do something like:
lazy val app = (project in file("app")).
settings(assemblySettings: _*)
settings(mainClass in assembly := Some("com.domain.Main"))

You can use -cp instead of -jar
java -cp xx.jar com.domain.AnyClassName

I had this issue while testing out Lagom.
To deploy in Lagom you can just access the -impl project and run this:
./sbt "project <your-project>-impl" dist
This will generate a zip with the executable inside.

Related

Scala's build.sbt not recognised by IntelliJ

I'm having an issue where my build.sbt file is not being picked up properly using IntelliJ (Ultimate 2020.2.3). I create a new Scala sbt project using the IntelliJ wizard (file > new > project > scala / sbt) and add a new dependancy to the buid.sbt file but when I try to import it into one of my class files, IntelliJ will not compile my project due to a dependancy issue.
The sbt tool window picks up the external dependancies but my project "external dependancies" doesn't contain the library at all, even after I refresh the project. Also, my build.sbt file has a bunch of errors in it like it's not being recognised properly by IntelliJ but I've installed the Scala plugin so I don't know what else I could do?
Here you can see that I've added the org.slf4j dependancy into my build.sbt; It's picked up by the sbt tool window (on the right) but not by my project (on the left)
When I hover over the libraryDependencies in the build.sbt file it doesn't seem to recognise the sbt syntax:
I cannot import the library into my class file and the project wont build:
I'm new to Scala and I'm simply trying to create a basic hello world project but I can't seem to get past this frustrating issue.
You can try first to create an SBT project manually in some directory. build.sbt alone would be enough.
Then run sbt in that directory to see that SBT shell works properly. Try some commands like sbt compile, sbt run with some helloworld app. When you create helloworld app mind the directory structure where you put it, i.e.: src/main/scala/HelloWorld.scala.
If all that works go to IntelliJ and import/open project from there - select build.sbt.
When you create or import SBT project from IntelliJ it takes a while to bootstrap everything and download compiler, etc. Just leave it until it's done. Same goes for first time compilation when the compiler needs to be compiled :).
To setup a sample project you can issue these shell commands:
mkdir untitled
cd untitled/
echo 'name := "untitled"
version := "0.1"
scalaVersion := "2.13.3"
libraryDependencies ++= Seq(
"org.slf4j" % "slf4j-simple" % "1.7.26",
)
' > build.sbt
mkdir -p src/main/scala/
echo 'object HelloWorld {
def main(args: Array[String]): Unit = {
println("Hello World")
}
}
' > src/main/scala/HelloWorld.scala
sbt run
If there are not issues with these steps then import build.sbt into IntelliJ.
I was finally able to get past this issue. I'm not 100% sure what solved it in the end unfortunately but disabling a bunch of plugins I wasn't using seemed to fix the issue for me.
I suspect it may have been the Gradle plugin since I saw some errors in the idea.log file but after re-enabling the Gradle plugin to test everything is still working so not sure.

How to run jar generated by sbt package via sbt

I have a jar that was created by running sbt package
I've already set the main file in the jar in build.sbt
mainClass in (Compile, packageBin) := Some("com.company.mysql.Main")
addCommandAlias("updatemysql", "runMain com.company.mysql.Main")
I've tried
sbt "runMain target/scala-2.12/update-mysql_2.12-0.1-SNAPSHOT.jar"
sbt target/scala-2.12/update-mysql_2.12-0.1-SNAPSHOT.jar com.company.mysql.Main
sbt target/scala-2.12/update-mysql_2.12-0.1-SNAPSHOT.jar:com.company.mysql.Main
sbt update-mysql-assembly-0.1-SNAPSHOT.jar/run
sbt run update-mysql-assembly-0.1-SNAPSHOT.jar
^ this gives No main class detected even though main class is set in build.sbt as shown a few lines above.
I need to run the jar through sbt because it's the only way I know how to overwrite config file that is contained in the jar using -Dpath.to.config.param=new_value
In sbt run and runMain use classpath containing all the dependencies as well as folders with outputs of compilation tasks - which means that none of them takes JAR as an argument.
I think it would be possible to run this particular JAR from sbt by writing a custom task that would depend on output of package task (that is JAR filepath value) and run it as external process... though from the question it seems that this is not the actual problem.
The actual problem is running the JAR with flags passed into JVM instead of program itself which can be achieved by something like:
# clean assembly ensures that there is only 1 JAR in target
# update-mysql_2.12-*.jar picks the only JAR no matter what is its version
# -D arguments NEED to be passed before -jar to pass it to JVM and not the JAR
sbt clean assembly && \
java -Dpath.to.config.param=new_value -jar target/scala-2.12/update-mysql_2.12-*.jar

build and executable jar using SBT

I have a simple Scala command line App that I want to package using SBT.
object Transform extends App {
val source = scala.io.Source.fromFile(args(0))
...
}
I can't seem to find anything in the SBT docs or an online example of a SBT configuration/command that would allows me to create a standalone executable jar (java -jar ...) with the appropriate manifest and dependencies included.
I did find SBT Assembly, but it looks to be a plugin for SBT < 0.13.5.
sbt-onejar was created for exactly this use case.

Create Simple Project SBT 0.10.X

(This is a follow up to sbt not creating projects correctly. The question wasn't answered.)
Basically, that question says "I don't know how to create a project under the new sbt. With the old one, I just ran sbt in a new folder and there was a guided wizard that led me through the setup."
The accepted answer does not explain how to create a new project, it just points to the documentation, which also doesn't explicitly say how to create a new project -- only how to write a build.sbt file.
So I tried first writing a build.sbt and then running sbt in the directory with the build.sbt file, but I still don't see a src directory to work with.
Could someone post a simple step-by-step (I'm assuming there are like 3 steps at most) guiding how to create a new project under sbt 0.10.X?
I found the answer I was looking for at this webpage: Scala 2.9.1, sbt 0.10 and ScalaTest step-by-step.
The high-level steps are:
mkdir my_project make a folder for your project
Create a simple my_project/build.sbt file, e.g.:
name := "A Project"
version := "0.1"
scalaVersion := "2.9.1"
libraryDependencies ++= Seq(
"org.scalatest" %% "scalatest" % "1.6.1" % "test"
)
Create a file my_project/src/main/scala/HelloWorld.scala, where you create all the directories you need as you go (e.g. create the directory structure src/main/scala/)
object Main extends App {
Console.println("Hello World!")
}
Execute your sbt commands: e.g. sbt run
I am surprised that noone gave another solution which is the closest to the old way (as mentioned by #dsg) to create a simple project in sbt:
Just run sbt in your project directory, then issue the following commands in the sbt REPL:
> set name := "MyProject"
> set version := "1.0"
> set scalaVersion := "2.9.0"
> session save
> exit
Granted, it is only mildly useful as it will just create the build.sbt file (enough to make it a proper sbt project) with the corresponding properties set, and you might as well create the file by hand (I usually prefer to do so myself). It won't create the src directory either.
Just a few days ago np (new project) plugin to sbt was released. It intended to dealt exactly with that problem:
Initial release. Provides a minimal interface for generating new sbt
projects via,... sbt.
Basic use is to install the plugin globally and start up a new project
with
$ sbt
$ np name:my-project org:com.mypackage version:0.1.0-SNAPSHOT
This will generate a simple build.sbt project for you along with the
standard project directory structure for main and test sources.
For more advanced usage, see the project's readme for more info
You can use https://github.com/n8han/giter8 to generate project layout using various templates
In newer versions of sbt, you can just install sbteclipse:
// ~/.sbt/plugins/build.sbt
addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.1.0")
then from sbt's console you can run:
eclipse with-source=true
In version 0.10.x I think this post can help you:
http://dcsobral.blogspot.fr/2011/06/very-quick-guide-to-project-creation-on.html
I've been using https://github.com/ymasory/sbt-prototype skeleton. See also my other answer.
It was the first one that just worked and I've been a quite happy with it since then.
Don't forget the recent sbt 0.13.3 new command:
Example:
First, you need sbt’s launcher version 0.13.13 or above.
Normally the exact version for the sbt launcher does not matter because it will use the version specified by sbt.version in project/build.properties; however for new sbt’s launcher 0.13.13 or above is required as the command functions without a project/build.properties present.
Next, run:
$ sbt new eed3si9n/hello.g8
....
name [hello]:
scala_version [2.11.8]:
Template applied in ./hello
This ran the template eed3si9n/hello.g8 using Giter8, prompted for values for “name” and “scala_version” (which have defaults “hello” and “2.11.8”, which we accepted hitting [Enter]), and created a build under ./hello.
Check out the GitHub repo Scala SBT Template. In particular the buildt.sbt file.
Just clone the repo, go to that directory, then call the sbt command.
$ git clone git://github.com/dph01/scala-sbt-template.git
$ cd scala-sbt-template
$ ./sbt
From inside of sbt, you can type run to execute provided code. Have fun!
An alternative way to generate the project structure using Intellij:
Create the directory for the project and include there a basic sbt file. You just need to specify the project name.
name := "porjectName"
With Intellij import the project. During the process check the options "Use auto-import" and "Create directories for empty content roots automatically"
That will create for you the basic skeleton for the sbt project.

How to declare a project dependency in SBT 0.10?

I use SBT 0.10.0.
How do I download/retrieve project dependencies?
For example, for slf4s only this line is mentioned:
val slf4s = "com.weiglewilczek.slf4s" %% "slf4s" % "1.0.6
Where do I need to put this line, and how do I get the library?
I presume you're using SBT 0.10.0, because earlier versions will put your deps in lib_managed automatically.
In build.sbt, put the following line:
retrieveManaged := true
You create a project/build subdirectory in your project and put a scala file with the above content there.
Then when you start sbt from your project root directory the
update
command will retrieve your dependencies.
Note that it will only analyse your project configuration once by default. If you change it, you have to call reload
UPDATE:
let the project class extend DefaultProject:
class SomeProjectName(info: ProjectInfo) extends DefaultProject(info)
I don't know which version of sbt you are using.
For 0.10, Daniel C. Sobral made a blog post about creation of an sbt project:
dcsobral-project-creation-guide
Maybe this helps.