How to use Quasar with Scala under sbt? - scala

I wish to use Quasar in my SBT project. Since Scala is not yet supported the only viable option left is to have SBT compile some java classes that use of Quasar.
I tried putting
javaOptions += "-javaagent:PATH_TO_JAR/quasar-core-0.5.0.jar"
and
fork := true
as I read that for using e.g. JRebel one must insert both these statements into build.sbt
But it does not seem to work either as using a Quasarish class (QuasarExample) yields:
[error] IllegalArgumentException: : Fiber class HelloWorldSpec$$anonfun$1$$anonfun$apply$3$$anon$1 has not been instrumented. (Fiber.java:151)
[error] co.paralleluniverse.fibers.Fiber.<init>(Fiber.java:151)
[error] co.paralleluniverse.fibers.Fiber.<init>(Fiber.java:171)
[error] co.paralleluniverse.fibers.Fiber.<init>(Fiber.java:448)
A piece of code that's expected to be running without errors after successful instrumentation:
new Fiber<Integer>() {
#Override
protected Integer run() throws SuspendExecution, InterruptedException {
return 0;
}
}.start();
See also this repository for a starter.

As per the comment from #mjaskowski, Dou you plan to instrument bytecode produced by Scala compiler?, Scala is not a supported language yet.
Short answer is: absolutely. Longer answer is, yes, but not very soon.
Scala is a very (very, very, very, very) complex language (oh my god,
it's so incredibly complex!), and it would take a long time to test
Quasar with the many (many-many-many) Scala features. Given the
relatively small number of Scala developers, and the heavy integration
costs, this may take some time. We do, however support Clojure (much
simpler integration), and will soon probably (or maybe we already do)
support Kotlin (trivial integration).
Follow along to see the possible ways to have the javaagent set up in sbt.
This is my first encounter with Quasar so the steps are really basic however they should give you a head start.
Running Quasar's javaagent in JVM alone
It's only with the following command to be able to run Quasar's javaagent without any Scala/sbt's jars.
java -cp
/Users/jacek/.ivy2/cache/org.ow2.asm/asm-util/jars/asm-util-5.0.1.jar:/Users/jacek/.ivy2/cache/org.ow2.asm/asm-commons/jars/asm-commons-5.0.1.jar:/Users/jacek/.ivy2/cache/org.ow2.asm/asm/jars/asm-5.0.1.jar -javaagent:/Users/jacek/.ivy2/cache/co.paralleluniverse/quasar-core/jars/quasar-core-0.5.0.jar
-help
It appears it's not self-contained and needs additional jars on the CLASSPATH.
Running Quasar's javaagent with scala
The following command makes scala and Quasar's javaagent happy.
scala -debug -usebootcp -toolcp
/Users/jacek/.ivy2/cache/org.ow2.asm/asm-tree/jars/asm-tree-5.0.1.jar:/Users/jacek/.ivy2/cache/org.ow2.asm/asm-util/jars/asm-util-5.0.1.jar:/Users/jacek/.ivy2/cache/org.ow2.asm/asm-commons/jars/asm-commons-5.0.1.jar:/Users/jacek/.ivy2/cache/org.ow2.asm/asm/jars/asm-5.0.1.jar:/Users/jacek/.ivy2/cache/org.ow2.asm/asm-analysis/jars/asm-analysis-5.0.1.jar
-J-javaagent:/Users/jacek/.ivy2/cache/co.paralleluniverse/quasar-core/jars/quasar-core-0.5.0.jar
Initial attempts to run Quasar with sbt
Add the necessary dependencies of Quasar in build.sbt:
val quasarDeps = Seq(
"quasar-core",
"quasar-actors",
"quasar-galaxy"
)
libraryDependencies := quasarDeps.map("co.paralleluniverse" % _ % "0.5.0")
It boils down to augmenting libraryDependencies with necessary jars. I chose all available.
I checked in Scala console that the libraries are available.
➜ quasar-sbt xsbt
[info] Loading global plugins from /Users/jacek/.sbt/0.13/plugins
[info] Set current project to quasar-sbt (in build file:/Users/jacek/sandbox/quasar-sbt/)
> console
Welcome to Scala version 2.10.4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_60).
Type in expressions to have them evaluated.
Type :help for more information.
scala> import co.paralleluniverse.fibers._
import co.paralleluniverse.fibers._
scala> Fiber.DEFAULT_STACK_SIZE
res0: Int = 32
You will also have to add the java agent. Add the following to build.sbt:
// FIXME the path to quasar-core should be simpler
javaOptions in Test += "-javaagent:/Users/jacek/.ivy2/cache/co.paralleluniverse/quasar-core/jars/quasar-core-0.5.0.jar"
fork in Test := true
// only needed for Specs2 so I could test the test setup
libraryDependencies += "org.specs2" %% "specs2" % "2.3.13" % Test
scalacOptions in Test ++= Seq("-Yrangepos")
reload the build changes.
> reload
[info] Loading global plugins from /Users/jacek/.sbt/0.13/plugins
[info] Set current project to quasar-sbt (in build file:/Users/jacek/sandbox/quasar-sbt/)
Write a test to make sure all's set up properly. I used the HelloWorldSpec from [Specs2][2] with some changes:
import org.specs2.mutable._
import co.paralleluniverse.fibers._
class HelloWorldSpec extends Specification {
"Quasar" should {
"Fiber.DEFAULT_STACK_SIZE defaults to 32" in {
Fiber.DEFAULT_STACK_SIZE === 32
}
}
}
It's not a very extensive test, so tweak it for your needs. Save the file under src/test/scala.
Execute test.
> test
objc[27427]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.7.0_60.jdk/Contents/Home/jre/bin/java and /Library/Java/JavaVirtualMachines/jdk1.7.0_60.jdk/Contents/Home/jre/lib/libinstrument.dylib. One of the two will be used. Which one is undefined.
[info] HelloWorldSpec
[info]
[info] Quasar should
[info] + Fiber.DEFAULT_STACK_SIZE defaults to 32
[info]
[info] Total for specification HelloWorldSpec
[info] Finished in 40 ms
[info] 1 example, 0 failure, 0 error
[info] Passed: Total 1, Failed 0, Errors 0, Passed 1
[success] Total time: 4 s, completed Jul 13, 2014 2:04:13 PM
It works!

Related

Scala: Sbt can run project, but calling the jar results in ClassNotFoundError

I have a project that will compile/package/run with SBT, but when I call the jar from the command line with Scala, I get a 'java.lang.ClassNotFoundException'.
build.sbt:
name := "coloring"
version := "0.1"
scalaVersion := "2.12.5"
libraryDependencies ++= Seq("org.scala-graph" %% "graph-core" % "1.12.5")
running sbt run results in:
[info] Compiling 1 Scala source to /path/to/dir/coloring/target/scala-2.12/classes ...
[warn] there was one feature warning; re-run with -feature for details
[warn] one warning found
[info] Done compiling.
[info] Packaging /path/to/dir/coloring/target/scala-2.12/coloring_2.12-0.1.jar ...
[info] Done packaging.
[info] Running Main
[success] Total time: 6 s, completed May 21, 2018 12:55:19 PM
However running scala target/scala-2.12/coloring_2.12-0.1.jar results in
java.lang.ClassNotFoundException: scalax.collection.GraphBase$InnerNode
What could be going wrong here? How is it possible that sbt run works, but when you call the jar directly, it fails?
EDIT: I solved the problem using sbt-assembly, but (1) I don't think this should be necessary, and (2) in similar projects in the past, I have used the exact same build.sbt and library/imports/etc and the project works when called from the command line.
If you don't want to assemble an uber-jar or similar, you'll need to have the dependencies on the classpath.
From the command line, that looks like:
scala -classpath my_1st.jar:my_2nd.jar:my_3rd.jar <whatever command>
So in your case, I imagine that looks like:
scala -classpath path/to/scala-graph.jar target/scala-2.12/coloring_2.12-0.1.jar
You can shorten -classpath to -cp
Here are quite a few other options: Include jar file in Scala interpreter
Libraries that you use need to be in the Java classpath. If you don't want to use assembly to include dependent libraries into a fat jar, you need to add them to the classpath some other way. For example via command line:
java -cp yourApp.jar:somelib.jar:someotherlibjar your.main.Class
java -cp yourApp.jar:libs/* your.main.Class

Changes to build.sbt to enable ScalaTest tests to run with Scala Play

I am following the docs here, and this does not seem to work at all; but I'm not even sure what am I doing wrong here.
For a start, just adding the given snippet in a project/Build.scala file causes a compile error; so that's a non-start.
Wrapping it inside an object which extends Build (as in the SBT example) does not cause a compile error, but the tests are not run.
Eventually, I've added the following to my build.sbt
libraryDependencies ++= Seq(
"org.scalatestplus" %% "play" % "1.0.0" % "test",
...
this is marginally better, but in IntelliJ, my ApplicationSpec has all sorts of compilation error:
import org.scalatestplus.play._
import scala.collection.mutable.Stack
class ApplicationSpec extends PlaySpec {
"A Stack" must {
"pop values in last-in-first-out order" in {
val stack = new Stack[Int]
stack.push(1)
stack.push(2)
stack.pop() mustBe 2
stack.pop() mustBe 1
}
"throw NoSuchElementException if an empty stack is popped" in {
val emptyStack = new Stack[Int]
a [NoSuchElementException] must be thrownBy {
emptyStack.pop()
}
}
}
}
must, mustBe and a are not recognized.
Finally, if I try to run activator test I get:
sentinel/test:definedTests
java.lang.NoSuchMethodError: org.specs2.runner.Fingerprints$.fp1()Lorg/specs2/runner/SpecificationFingerprint;
at org.specs2.runner.Specs2Framework.fingerprints(SbtRunner.scala:23)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at sbt.TestFramework$.getFingerprints(TestFramework.scala:113)
at sbt.Tests$$anonfun$discover$1.apply(Tests.scala:242)
at sbt.Tests$$anonfun$discover$1.apply(Tests.scala:242)
at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:251)
at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:251)
at scala.collection.immutable.List.foreach(List.scala:318)
at scala.collection.TraversableLike$class.flatMap(TraversableLike.scala:251)
at scala.collection.AbstractTraversable.flatMap(Traversable.scala:105)
at sbt.Tests$.discover(Tests.scala:242)
at sbt.Defaults$$anonfun$detectTests$1.apply(Defaults.scala:556)
...
[error] (sentinel/test:definedTests) java.lang.reflect.InvocationTargetException
Essentially, an epic fail - it would be great if the docs were a bit more specific in what is required and what is expected for all the machinery to work: as things stand, it's kinda difficult to untangle the mess.
I've been googling and looking here on stack overflow for hours today, looked at the ScalaTestPlus docs (well, the whole two paragraphs of it...) and tried many variations, all to no avail.
The full project's code is on github.
Worth noting that if I give in to the "power-of-bad-documentation" and I use Specs2, then tests run correctly (at least from inside Intellij, and as far as the 'hello world' example goes).
I would still much prefer to using ScalaTest (can't really see why I need to learn TWO testing frameworks, really) - so, any help would be appreciated.
In the end, it turned out it was indeed a library version mismatch, but one I hadn't anticipated.
It revolves around the fact that I have a sub-project in my sbt build, which works just fine, but was importing ScalaTest 2.2.1, while I was using 2.1.7 to make it work with ScalaTest+ 1.1.0 - however, using ScalaTest 2.1.7 (which, indeed works with ST+ 1.1.0) only for the 'top-level' project was causing the weirdness around the abstract class, etc.
The Versions, Versions, Versions page has now been updated by Bill, and the fix has been to use ScalaTest 2.2.1, ScalaTestPlus 1.2.0 and Play 2.3.0 - which all play nice together.
Updated - the above still caused tests to fail via sbt/activator test, I could only run the tests via IntelliJ: the fix has been to update the build.sbt to use Scala 2.11
In the end, to make this work, this is what I have in my build.sbt:
name := "sentinel"
version := "0.2-SNAPSHOT"
organization := "AlertAvert.com"
scalacOptions ++= Seq("-deprecation", "-feature", "-language:postfixOps")
// The REST project depends on Core Sentinel classes
lazy val sentinel_core = project
lazy val sentinel = (project in file("."))
.enablePlugins(PlayScala)
.aggregate(sentinel_core)
.dependsOn(sentinel_core)
scalaVersion := "2.11.1"
libraryDependencies ++= Seq(
"org.scalatest" %% "scalatest" % "2.2.1" % "test",
"org.scalatestplus" %% "play" % "1.2.0" % "test",
cache
)
(I'm reproducing it in its entirety, so that if someone else has the same problem, they'll see it - it infuriates me when people only paste a fragment and some key essentials are omitted :)
Major credits to Bill Venners for the help and guidance.
Appears you have library version mismatch somewhere.
I have been using Scalatest with Play and haven't had any issues.
I am using Play 2.3.4, ScalaTest 2.2.1.
activator "test-only com.abc.tests.controllers.ApplicationSpec"
[info] ApplicationSpec:
[info] A Stack
[info] - must pop values in last-in-first-out order
[info] - must throw NoSuchElementException if an empty stack is popped
[info] ScalaTest
[info] Run completed in 1 second, 119 milliseconds.
[info] Total number of tests run: 2
[info] Suites: completed 1, aborted 0
[info] Tests: succeeded 2, failed 0, canceled 0, ignored 0, pending 0
[info] All tests passed.

Running tests from jar with "sbt testOnly" in SBT?

As part of a CI setup the very first step is to create a package/jar using SBT dist. The following steps are to run unit, integration and functional tests with the dist-created jar.
Is it possible to do that with SBT?
Normally I use sbt testOnly "Unit.*", but that works in the context of a project. I can't find any documentation showing how to do this when there is already a jar.
I'm using ScalaTest and I know there is a runner for it I could use http://www.scalatest.org/user_guide/using_the_runner. But using SBT would be simpler, if that is possible.
As an example, something like this is what I am looking for:
sbt testOnly "Unit.* -jar myjar.jar"
Will my tests even be included in the jar when I use the following:
sbt dist
?
EDIT
I created a new folder
I added build.sbt with the following content:
name := "abc"
version := "1.0-SNAPSHOT"
scalaVersion := "2.10.0"
I added the lib folder and copied my tests jar into it
I ran sbt testOnly Unit.*
It could not find any tests
EDIT 2
I tried with the following "proper" SBT file:
name := "ihs2tests"
version := "1.0-SNAPSHOT"
scalaVersion := "2.10.0"
unmanagedBase in Test := new java.io.File(".")
and moved test.jar into the root of the project. Again, no tests found.
Normally I use sbt testOnly "Unit.*", but that works in the context of a project. I can't find any documentation showing how to do this when there is already a jar.
The test-family tasks in SBT (with testOnly as an example) work with compile task that returns a list of compiled files through an sbt.inc.Analysis instance. I couldn't figure out how to amend it and inject the changed Analysis instance to testOnly so it knows the test I'm going to run exists.
I'm proposing another solution - a trick.
Package the tests classes to a jar with test:package task as follows:
[test-lib]> test:package
[info] Updating {file:/Users/jacek/sandbox/so/test-lib/}test-lib...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Compiling 1 Scala source to /Users/jacek/sandbox/so/test-lib/target/scala-2.10/test-classes...
[info] Packaging /Users/jacek/sandbox/so/test-lib/target/scala-2.10/test-lib_2.10-0.1-SNAPSHOT-tests.jar ...
[info] Done packaging.
[success] Total time: 9 s, completed Mar 4, 2014 11:34:13 PM
When you have the test jar, you can execute the test framework on the command line without SBT (I assume you use ScalaTest given the scalatest tag, but I'll use Specs2). Read the documentation of the test framework on how to do it and for Specs2 it's specs2.run as described in Console output.
Executing tests from the test jar requires defining a proper CLASSPATH that may or may not be easy to get right. That's where SBT can be of great help - to manage dependencies and hence the CLASSPATH.
Create another SBT project and save the test jar in lib subdirectory to have it on CLASSPATH (as described in Unmanaged dependencies).
Dependencies in lib go on all the classpaths (for compile, test, run, and console).
Add a sample build.sbt where you define your test framework as a dependency of the project. For Specs2 it's as follows (I used the default configuration as described in the Specs2 home page):
libraryDependencies += "org.specs2" %% "specs2" % "2.3.8" % "test"
scalacOptions in Test ++= Seq("-Yrangepos")
The trick is to execute the main class of the test framework, e.g. specs2.run for Specs2, as if the class were executed on the command line. SBT helps with test:runMain.
[my-another-project]> test:runMain specs2.run HelloWorldSpec
[info] Running specs2.run HelloWorldSpec
HelloWorldSpec
The 'Hello world' string should
+ contain 11 characters
+ start with 'Hello'
+ end with 'world'
Total for specification HelloWorldSpec
Finished in 62 ms
3 examples, 0 failure, 0 error
Exception: sbt.TrapExitSecurityException thrown from the UncaughtExceptionHandler in thread "run-main-0"
[success] Total time: 5 s, completed Mar 4, 2014 11:15:14 PM
Don't worry about this Exception as it comes from SBT that catches exit from Specs2 (after test execution) so SBT remains up.
It seems that SBT can't read jar file without any additional/manual setup - I might be wrong but I didn't find anything in the docs. So I tried something like this to make the task simpler:
unzip some-test.jar
java -jar sbt-launch.jar \
'set scalaSource in Test := new java.io.File(".")' \
'set fullClasspath in Test += Attributed.blank(file("."))' \
'test'
This runs without errors but does not find tests.
If I add 'set includeFilter in (Test, unmanagedSources) := "*Suite*.class"' to force it to find tests it obviously fails because it expects *.scala files, not the compiled *.class files.
I'm not an SBT expert, but I think this must be close to a solution. There must be a way to read all files from a jar path programmatically and then tell test framework to use *.class files.
At this point is seems more reasonable to run tests using a Scalatest test runner or from sbt using the project.
If you wish to dig deeper take a look at SBT source code and the default sbt shell script that does lots of setup before it runs the sbt launcher jar.

MissingResourceException: Can't find bundle for base name com/sun/rowset/RowSetResourceBundle (SBT project)

Running sbt test via console (v0.13.1 on Windows) throws a MissingResourceException: : Can't find bundle for base name com/sun/rowset/RowSetResourceBundle, locale en_CA when I try to create an instance of com.sun.rowset.CachedRowSetImpl object. The same code runs great if I use IntelliJ to run a Specs test; it only fails when trying to run via SBT console.
Here is the specs2 test I'm trying to run:
import org.specs2.mutable.SpecificationWithJUnit
import javax.sql.rowset.CachedRowSet;
import com.sun.rowset.CachedRowSetImpl
class DatabaseTest extends SpecificationWithJUnit {
"CachedRowSet Test" should {
"Create a new CachedRowSetImpl instance" in {
val rowSet: CachedRowSet = new CachedRowSetImpl()
rowSet must_!= null
}
}
}
And the resulting exception:
[error] MissingResourceException: : Can't find bundle for base name com/sun/rowset/RowSetResourceBundle, locale en_CA (null:-1)
[error] com.sun.rowset.JdbcRowSetResourceBundle.<init>(Unknown Source)
[error] com.sun.rowset.JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle(Unknown Source)
[error] com.sun.rowset.CachedRowSetImpl.<init>(Unknown Source)
[error] test.DatabaseTest$$anonfun$1$$anonfun$apply$1.apply(DatabaseTest.scala:10)
[error] test.DatabaseTest$$anonfun$1$$anonfun$apply$1.apply(DatabaseTest.scala:9)
Update: build.sbt contents:
scalacOptions ++= Seq("-deprecation", "-unchecked", "-feature")
scalaVersion := "2.10.3"
scalacOptions ++= Seq("-Yrangepos")
javacOptions ++= Seq("-source", "1.6", "-target", "1.6", "-Xlint:deprecation", "-Xlint:unchecked")
libraryDependencies in ThisBuild ++= Seq(
"postgresql" % "postgresql" % "9.1-901.jdbc4" withSources(),
"org.specs2" %% "specs2" % "2.3.7" withSources()
)
lazy val root = project.in(file("."))
I had this issue when running ScalaTest using SBT. In IntelliJ the tests ran clean but in SBT the late bound implementation for CachedRowSet did not get resolved and the following exception was thrown,
MissingResourceException: : Can't find bundle for base name
com/sun/rowset/RowSetResourceBundle, locale en_GB
The problem appears to be that the SBT thread does not resolve run time class loads back to the JVM (the missing resources are provided by rt.jar and resources.jar).
This can be fixed by forcing the SBT thread to fork new threads for each test by putting the following instruction into the main body of the SBT build file,
fork in Test := true
CachedRowSetImpl is an internal class in some version of the JDK runtime but is not officially part of the JDK. You can tell it is internal because its package starts with "com.sun", not "java". It's likely that your Windows machine has a completely different JDK that lacks this internal class.
I highly recommend avoiding the use of "com.sun" classes and find the idiomatic way to get the job done with the existing JDK.
Provided you use Java 7...
As of Java 7 there're few classes and methods that shield you from errors like yours. Develop against interfaces (with some help from providers) and life becomes easier.
import org.specs2.mutable.SpecificationWithJUnit
import javax.sql.rowset._
class DatabaseTest extends SpecificationWithJUnit {
"CachedRowSet Test" should {
"Create a new CachedRowSetImpl instance" in {
val rsf = RowSetProvider.newFactory
val rowSet: CachedRowSet = rsf.createCachedRowSet
rowSet must_!= null
}
}
}
With the Specs2 test, test worked fine for me.
> test
[info] DatabaseTest
[info]
[info] CachedRowSet Test should
[info] + Create a new CachedRowSetImpl instance
[info]
[info] Total for specification DatabaseTest
[info] Finished in 41 ms
[info] 1 example, 0 failure, 0 error
[info] Passed: Total 1, Failed 0, Errors 0, Passed 1
BTW: The missing resources are in lib/resources.jar in JRE, but couldn't figure out why they're reported as missing (even when they ended up in lib directory of a project).
Having the same issue. Not in Scala, but Java.
com.sun.rowset.JdbcRowSetResourceBundle loads resource with context classloader.
In my case context classloader is a URLClassLoader.
And it looks like a really weird limitation of URLClassLoader - when looking for resources it does not consult parent classloader, it checks only its own URLs list.
Hope that helps.

how to set main class in SBT 0.13 project

Could you guys please explain to me how to set main class in SBT project ? I'm trying to use version 0.13.
My directory structure is very simple (unlike SBT's documentation). In the root folder I have build.sbt with following content
name := "sbt_test"
version := "1.0"
scalaVersion := "2.10.1-local"
autoScalaLibrary := false
scalaHome := Some(file("/Program Files (x86)/scala/"))
mainClass := Some("Hi")
libraryDependencies ++= Seq(
"org.scalatest" % "scalatest_2.10" % "2.0.M5b" % "test"
)
EclipseKeys.withSource := true
And I have subfolder project with single file Hi.scala which contains following code
object Hi {
def main(args: Array[String]) = println("Hi!")
}
I'm able to compile it by calling sbt compile but sbt run returns
The system cannot find the file C:\work\externals\sbt\bin\sbtconfig.txt.
[info] Loading project definition from C:\work\test_projects\sbt_test\project
[info] Set current project to sbt_test (in build file:/C:/work/test_projects/sbt_test/)
java.lang.RuntimeException: No main class detected.
at scala.sys.package$.error(package.scala:27)
[trace] Stack trace suppressed: run last compile:run for the full output.
[error] (compile:run) No main class detected.
[error] Total time: 0 s, completed Apr 8, 2013 6:14:41 PM
You need to put your application's source in src/main/scala/, project/ is for build definition code.
Try to use an object and extend it from App instead of using class
object Main extends App {
println("Hello from main scala object")
}
Here is how to specify main class
mainClass in (Compile,run) := Some("my.fully.qualified.MainClassName")
For custom modules in SBT (0.13), just enter on the SBT console:
project moduleX
[info] Set current project to moduleX (in build file:/path/to/Projects/)
> run
[info] Running main
to switch scope to moduleX, as define in Built.scala. All main classes within that scope will be detected automatically. Otherwise you get the same error of no main class detected.
For God's sake, SBT does not tell you that the default scope is not set. It has nothing to do with default versus non default source folders but only with SBT not telling anything that it doesn't know which module to use by default.
Big Hint to typesafe: PLEASE add a default output like:
[info] Project module is not set. Please use ''project moduleX'' set scope
or set in Built file (LinkToDocu)
at the end of SBT start to lower the level of frustration while using SBT on multi module projects.....
I had the same issue: was mode following the tutorial at http://www.scala-sbt.org/0.13/docs/Hello.html, and in my opinion, as a build tool sbt's interaction and error messages can be quite misleading to a newcomer.
It turned out, hours of head scratching later, that I missed the critical cd hello line in the example each time. :-(
If you have multiple main methods in your project you can add the following line to your build.sbt file:
val projectMainClass = "com.saeed.ApplicationMain"
mainClass in (Compile, run) := Some(projectMainClass)
If you want to specify the class that will be added to the manifest when your application is packaged as a JAR file, add this line to your build.sbt file:
mainClass in (Compile, packageBin) := Some(projectMainClass)
You can also specify main class using run-main command in sbt and activator to run:
sbt "run-main com.saeed.ApplicationMain"
or
activator "run-main com.saeed.ApplicationMain"
There are 4 options
you have 1 main class
sbt run and sbt will find main for you
you have 2 or more main classes
sbt run and sbt will propose to select which one you want to run.
Multiple main classes detected, select one to run:
[1] a.b.DummyMain1
[2] a.b.DummyMain2
Enter number:
You want to set main class manually.
mainClass in run := Some("a.b.DummyMain1")
You could run with main class as parameter
sbt runMain a.b.DummyMain1
If the Main class is in a different project then by setting the below command in build.sbt would work:
addCommandAlias("run", "; project_folder/run")
I had the same issue. Resolved it after adding PlayMinimalJava plugin in build.sbt.
Not sure how it got fixed, if someone can highlight how PlayMinimalJava solves it, would be great.
enablePlugins(PlayMinimalJava)
My build.sbt looks like this
organization := "org"
version := "1.0-SNAPSHOT"
scalaVersion := "2.13.1"
libraryDependencies += guice
enablePlugins(PlayMinimalJava)
Log
C:\Users\KulwantSingh\repository\pdfdemo>sbt run
Java HotSpot(TM) Client VM warning: ignoring option MaxPermSize=256m; support was removed in 8.0
[info] Loading settings for project pdfdemo-build from plugins.sbt ...
[info] Loading project definition from C:\Users\KulwantSingh\repository\pdfdemo\project
[info] Loading settings for project pdfdemo from build.sbt ...
[info] Set current project to pdfdemo (in build file:/C:/Users/KulwantSingh/repository/pdfdemo/)
[warn] There may be incompatibilities among your library dependencies; run 'evicted' to see detailed eviction warnings.
--- (Running the application, auto-reloading is enabled) ---
[info] p.c.s.AkkaHttpServer - Listening for HTTP on /0:0:0:0:0:0:0:0:9000
(Server started, use Enter to stop and go back to the console...)
[info] Compiling 6 Scala sources and 2 Java sources to C:\Users\KulwantSingh\repository\pdfdemo\target\scala-2.13\classes ...
[info] p.a.h.EnabledFilters - Enabled Filters (see <https://www.playframework.com/documentation/latest/Filters>):
play.filters.csrf.CSRFFilter
play.filters.headers.SecurityHeadersFilter
play.filters.hosts.AllowedHostsFilter
[info] play.api.Play - Application started (Dev) (no global state)
Incase if someone made a silly mistake like I did.
Check if your project is sbt-multi project.
If it is make sure to provide sbt moduleName/run instead sbt run
I keep making this mistaken when I switch between multi and single projects.