Play Version
PlayScala#2.7.2
JDK (Oracle 1.8.0_72, OpenJDK 1.8.x, Azul Zing)
$ java -version
openjdk version "1.8.0_212"
OpenJDK Runtime Environment (Zulu 8.38.0.13-CA-linux64) (build 1.8.0_212-b04)
OpenJDK 64-Bit Server VM (Zulu 8.38.0.13-CA-linux64) (build 25.212-b04, mixed mode)
Expected Behavior
make your sbt project as 'root'
add sub-project as 'buildA'
add sub-project as 'appA'
buildA include a appA.routes
-> Yay, you can create some builds in one root project !!
Actual Behavior
My child-project (buildA) can NOT load grand-chid-project(appA)' s routing.
$ tree -L 2
.
├── build.sbt
├── build-app
│ ├── app
│ ├── build.sbt
│ ├── conf
│ │ ├── application.conf
│ │ ├── logback.xml
│ │ └── routes
├── core
│ ├── app
│ ├── build.sbt
│ ├── conf
│ │ └── core.routes
│ ├── src
├── project
├── plugins.sbt
build.sbt
lazy val buildApp = project.in(file("build-app"))
lazy val root = project.in(file("."))
build-app/build.sbt
lazy val core = project.in(file("../core")).enablePlugins(PlayScala)
lazy val buildApp = (project in file("."))
.enablePlugins(PlayScala)
.dependsOn(core)
build-app/conf/routes
GET / controllers.app.HomeController.index
-> /core core.Routes
core/conf/core.routes
GET / controllers.core.HomeController.index
$ sbt "project buildApp" compile
[error] /home/sizer/go/src/github.com/sizer/hello-sbt-multiproject/build-app/conf/routes:3:1: not found: value core
[error] -> /core core.Routes
Can NOT load core.routes :sob:
Am I Wrong or Is it correct behaviour??
my project is below.
https://github.com/sizer/hello-sbt-multiproject/tree/playframework_failedExample
Related
This is my folder structure and I am trying to load the "grammar.txt" file from resources folder but I get not found error.
val source = Source.fromResource("grammar.txt")
Folder structure:
➜ cfg-tools tree -L 4
.
├── build.sbt
├── src
│ ├── main
│ │ └── scala
│ │ ├── Builer.scala
│ │ ├── Driver.scala
│ │ ├── tokens.scala
│ │ └── Tools.scala
│ ├── resources
│ │ └── grammar.txt
build.sbt
name := "cfg-tools"
version := "0.1"
scalaVersion := "3.0.2"
Compile / unmanagedResourceDirectories += sourceDirectory.value / "resources"
You don't need the custom SBT configuration: just use the standard place for resources which is src/main/resources (note that it's in main subfolder compared to your current structure).
I have been developing a common library for my team, where I need to provide mock data for end users to write unit-test code. Ideally, the mock object should only be available to tests of packages referencing mine, but I am not sure how to do this.
My package structure is:
├── common
│ ├── src
│ │ ├── main
│ │ │ ├── resources
│ │ │ └── scala
│ │ └── test
│ │ ├── resources
│ │ └── scala
│ │ └── MockData.scala // <--- object defined here
├── build.sbt
In my build.sbt, I have
Test / publishArtifact := true
Test / publish := true
packageBin / publishArtifact := true
And I use sbt clean; sbt compile; sbt publishLocal to publish my library locally.
In the project referencing the above library, I added the following to the build.sbt:
ThisBuild / libraryDependencies ++= Seq(
"org.my" %% "common" % "0.0.1",
"org.my" %% "common" % "0.0.1" % Test,
)
but when writing tests, I cannot find objects defined in MockData.scala.
Please provide some hints, much appreciated.
------------------ UPDATE ------------------
After googling around, I'd decided to write a separate module for publishing test data only. So my package structure becomes:
├── common
│ ├── src
│ │ ├── main
│ │ │ ├── resources
│ │ │ └── scala
│ │ └── test
│ │ ├── resources
│ │ └── scala
├── common-testkit
│ ├── src
│ │ └── main
│ │ ├── resources
│ │ └── scala
│ │ └── MockData.scala // <--- object defined here
├── build.sbt
The issue is in the way you ask to retrieve the test code in your other project.
"org.my" %% "common" % "0.0.1" % Test means to depends on the "main" code of project common when running the tests of your other project. That's what the scope Test (after the version) means.
What you want is to depend on the "test code" of common project when running your tests. This is done by specifying what is called a "classifier" in sbt:
"org.my" %% "common" % "0.0.1" % Test classifier "tests"
I have a project that uses akka in version 2.11_2.5.21 which is assembly in my fat jar.
I have download the scala binary 2.11.12 and it is shipped with a lib/akka-actor_2.11-2.3.16.jar (next to bin/scala)
When I run my project : scala -cp target/scala-2.11/project-assembly-2.4.0.jar foo.MyClass I get
java.lang.NoSuchMethodError: akka.actor.OneForOneStrategy.withMaxNrOfRetries(I)Lakka/actor/OneForOneStrategy;
If i remove lib/akka-actor_2.11-2.3.16.jar in my scala directory it works.
Of course it also works with sbt run as sbt used its own scala version.
Why does scala binary use its own akka version instead of the one shipped in the fat jar?
Assuming by "Scala binary" you are referring to the decompressed structure of say https://downloads.lightbend.com/scala/2.11.12/scala-2.11.12.tgz
➜ scala-2.11.12 tree -L 2
.
├── bin
│ ├── fsc
│ ├── fsc.bat
│ ├── scala
│ ├── scala.bat
│ ├── scalac
│ ├── scalac.bat
│ ├── scaladoc
│ ├── scaladoc.bat
│ ├── scalap
│ └── scalap.bat
├── doc
│ ├── LICENSE.md
│ ├── License.rtf
│ ├── README
│ ├── licenses
│ └── tools
├── lib
│ ├── akka-actor_2.11-2.3.16.jar
│ ├── config-1.2.1.jar
│ ├── jline-2.14.3.jar
│ ├── scala-actors-2.11.0.jar
│ ├── scala-actors-migration_2.11-1.1.0.jar
│ ├── scala-compiler.jar
│ ├── scala-continuations-library_2.11-1.0.2.jar
│ ├── scala-continuations-plugin_2.11.12-1.0.2.jar
│ ├── scala-library.jar
│ ├── scala-parser-combinators_2.11-1.0.4.jar
│ ├── scala-reflect.jar
│ ├── scala-swing_2.11-1.0.2.jar
│ ├── scala-xml_2.11-1.0.5.jar
│ └── scalap-2.11.12.jar
└── man
└── man1
then everything inside lib/ will take precedence over what you specify with -cp. To see this analyse the following snippet of bin/scala runner script
execCommand \
"${JAVACMD:=java}" \
$JAVA_OPTS \
"${java_args[#]}" \
"${classpath_args[#]}" \
-Dscala.home="$SCALA_HOME" \
$OVERRIDE_USEJAVACP \
"$EMACS_OPT" \
$WINDOWS_OPT \
scala.tools.nsc.MainGenericRunner "$#"
Note that "${classpath_args[#]}" which holds jars from lib precedes the last "$#" which holds your arguments such as -cp. Finally JVM will pick the first matching class it finds on the classpath which in your case will be the one from lib/akka-actor_2.11-2.3.16.jar. For example
scala -cp target/scala-2.11/project-assembly-2.4.0.jar
would expand to something like
java -Xbootclasspath/a:/scala-2.11.12/lib/akka-actor_2.11-2.3.16.jar ... scala.tools.nsc.MainGenericRunner -cp target/scala-2.11/project-assembly-2.4.0.jar
hence Xbootclasspath would take precedence over -cp.
I have a play project that I'd like to build with a common library that handles things like clients, services, utilities, etc...
My dir structure is like so:
.
├── build.sbt
├── myapp
│ ├── app
│ │ ├── controllers
│ │ │ └── HomeController.scala
│ │ └── views
│ │ ├── index.scala.html
│ │ └── main.scala.html
│ ├── conf
│ │ ├── application.conf
│ │ ├── logback.xml
│ │ ├── messages
│ │ └── routes
│ ├── public
│ │ ├── images
│ │ │ └── favicon.png
│ │ ├── javascripts
│ │ │ └── main.js
│ │ └── stylesheets
│ │ └── main.css
│ └── test
│ └── controllers
│ └── HomeControllerSpec.scala
├── myapp-common
│ └── src
│ └── main
│ └── TesterObject.scala
└── project
├── build.properties
├── plugins.sbt
└── scaffold.sbt
My build.sbt is configured as follows:
lazy val commonSettings = Seq(
version := "1.0-SNAPSHOT",
scalaVersion := "2.12.3"
)
lazy val root = (project in file("."))
.settings(commonSettings)
.aggregate(myapp, `myapp-common`)
.dependsOn(myapp, `myapp-common`)
lazy val `myapp-common` = project
.settings(commonSettings)
lazy val myapp = project
.enablePlugins(PlayScala)
.settings(commonSettings)
.settings(libraryDependencies += guice)
.settings(libraryDependencies += "org.scalatestplus.play" %% "scalatestplus-play" % "3.1.2" % Test)
.dependsOn(`myapp-common`)
While I am able to successfully run the play project with sbt myapp/run, it fails when I try to import a package defined in myapp-common.
For instance, if I have myapp-common/src/main/TesterObject.scala:
package tester
Object TesterObject {
val testMe = 3
}
If I try to import tester._ and then use TesterObject.testMe in myapp/app/controllers/HomeController.scala, the project fails during compilation since it can't find the package.
Can anyone point me in the right direction here? The sbt guide on multi-projects is a bit tough for me to parse for this particular problem. It seems like my dependencies are appropriately set up.
I've managed to get cucumber-scala up and running on a Play/Scala. Now I want to run the entire play application so that I can use something like Selenium to test my application.
My Current attempts have lead me to
val app = new FakeApplication()
val port = 3333
lazy val browser: TestBrowser = TestBrowser.of(webDriverClass, Some("http://localhost:" + port))
lazy val server = TestServer(port, app)
Of course this FakeApplication() is not configured in any way... Am I approaching this incorrectly? This application is also multi-module and Ideally I would like to have the feature tests run per module (see output from tree below)
├── README.md
├── build.sbt
├── conf
│ ├── application.conf
│ └── routes
├── logs
│ └── application.log
├── modules
│ ├── module1
│ │ ├── app
│ │ ├── conf
│ │ ├── target
│ │ └── test
│ └── module2
│ ├── app
│ ├── conf
│ └── target
└── project
├── build.properties
├── plugins.sbt
├── project
│ └── target
└── target
├── config-classes
├── resolution-cache
├── scala-2.10
└── streams
I am aware that Play has a selenium integration which can be used to drive my tests. However I have a business requirement for feature files, as they are used as a reporting mechanism. I am not absolutely tied to Cucumber so if anyone is aware of a way of driving browser based tests using Feature files that would also be acceptable to me?
Thanks,
Ben
Update:
I was running through IntelliJ, which causes a server to run with no routes or anything provided. I assume this is because it runs with a default blank application.
However When running through sbt test I get the following output:
Caused by: com.google.inject.ProvisionException: Unable to provision, see the following errors:
1) Error in custom provider, Configuration error: Configuration error[Router not found: admin.Routes]
while locating play.api.inject.guice.FakeRouterProvider
while locating play.api.routing.Router
for parameter 0 at play.api.http.JavaCompatibleHttpRequestHandler.<init>(HttpRequestHandler.scala:200)
while locating play.api.http.JavaCompatibleHttpRequestHandler
while locating play.api.http.HttpRequestHandler
for parameter 4 at play.api.DefaultApplication.<init>(Application.scala:221)
at play.api.DefaultApplication.class(Application.scala:221)
while locating play.api.DefaultApplication
while locating play.api.Application
If you're using the default configuration settings for IntegrationTest in sbt, and ScalaTestPlusPlay, here are the directories to use:
src/it/scala – scala IT code
src/it/java – java IT code
src/it/resources – resources, including configuration
Place your application.conf and routes files in the resources directory and FakeApplication will pick it up. You can also set the paths in your sbt script to some other place.
If all of your development/integration testing machines are Unix-like and you use git for VC, you can use a relative symlink1 to your real routes file.
For Windows or other VCS's, you'll likely have to copy the routes file and do double maintenance.
1 symlink using a relative path to the original, e.g., ../../../conf/routes.