Play 2.1: Logger doesn't work - scala

According to this thread and the source code, logger in Play 2.0 is disabled in test mode. In Play 2.1.x, the if condition seems to have been removed (see source code), so I guess logger can be used in test mode in Play 2.1, but it's not the case for me.
I use play.api.Logger (I program in Scala) and the default configuration. Here is how I use it:
In app/controllers/Application:
package controllers
import play.api.mvc._
import play.api.Logger
object Application extends Controller {
def index = Action {
Logger.error("Here's index!")
Ok(views.html.index("Hello"))
}
}
In conf/routes:
# Home page
GET / controllers.Application.index

The problem was solved by removing duplicated SLF4J and log4j libraries in the classpath, thanks #nico_ekito for his helps!

Related

compilation error when a SIRD is added in the Play application

I have a working project which uses Play's compiled routes. I want to add SIRD route to handle some web services. The compiled routes would stay.
I created a routes.users package and added the following UserRoutes scala class in it.
package routes.users
import javax.inject.Inject
import play.api.mvc._
import play.api.routing.Router.Routes
import play.api.routing.SimpleRouter
import play.api.routing.sird._
import controllers.UserController
class UserRouter #Inject()(controller:UserController) extends SimpleRouter {
override def routes:Routes = {
case GET(p"/users/add") => controller.addUser();
}
When I tried to compile the code, I got the following error.
error] error writing routes/users/UserRouter: C:\...\target\scala-2.12\classes/routes/users/UserRouter.class: C:\...\target\scala-2.12\classes\routes is not a directory
[error] error writing routes/users/UserRouter$$anonfun$routes$1: C:\...\target\scala-2.12\classes/routes/users/UserRouter$$anonfun$routes$1.class: C:\...\target\scala-2.12\classes\routes is not a directory
[error] two errors found
[error] (compile:compileIncremental) Compilation failed
The code compiles and works if I remove routes.users package. What mistake am I making?
Yes, as you commented, the problem is with the name.
I'm not entirely the exact details, but I'm pretty sure routes is used for reverse routing and I have attempted to make my own routes package before and its caused an issue for the same reason you are having right now. Seems like a naming conflict.
From Play Framework Documentation

ScalaTest Plus not recognizing tests

I've been tasked to update and write a series of tests on an app in Scala Play, a language and framework I'm unfamiliar with. Part of what I'd like to do is integrate the ScalaTestPlus library. To get started I have been following the following tutorial:
https://www.playframework.com/documentation/2.2.x/ScalaTestingWithScalaTest
Unfortunately I am not getting very far. I have added a new unit test file to the tests folder:
import org.scalatestplus.play._
class StackSpec extends PlaySpec {
"A Test" must {
"pass" in {
assert(1 == 1)
}
"Fail" in {
assert(1 != 1)
}
}
}
and I have updated my build.sbt to include the scalatestplus library
"org.scalatestplus" % "play_2.37" % "1.2.0" % "test"//,
Using Activator, I am trying to run my test file with test-only. Everything compiles without errors, but activator is not finding any tests
[info] No tests were executed.
I don't believe the issue is with activator, since I can run old test files (from the previous engineer) using the test and test-only commands. A quick sample of one of the previous (working) test files:
import java.util.concurrent.TimeUnit
import com.sun.xml.internal.bind.v2.TODO
import scala.collection.JavaConverters._
import controllers.Application
import models.{Item, PriorityBucket}
import play.api.test._
class WebSpec extends PlaySpecification {
"Home page" should {
"do something" in new WithSeleniumDbData(TestUtil.testApp) {
Redacted.deleteAll()
val ObId = TestUtil.create(Some(PriorityBucket.Low),
Some(Application.ENGLISH))
val item = Item.find(ItemId).get
browser.goTo("/")
browser.await().atMost(2,
TimeUnit.SECONDS).until(Selectors.all_obs).isPresent
}
Any ideas where I've gone astray? Thanks in advance for the help!
I am using scala 2.11
I am using play 2.3.7
EDIT: Possibly relevant, I switched the extension from PlaySpec to FlatSpec and saw the following error when compiling:
SampleSpec.scala:10: value in is not a member of String
[error] "pass" in {
I made sure to import FlatSpec as well, which has me a bit confused--is FlatSpec a member of ScalaTest but not a member of ScalaTestPlus, I don't see why else the compilation would fail.
UPDATE: To further investigate the issue I spun up a brand new Play app and copied over my sample test. After some tooling around with versions I've been able to get my test to run on the activator test command with the rest of the suite. Unfortunately, any other commands like test-only are still returning no tests run.
For those following I ran across the issue...the class name in this case needed to be identical to the file name, otherwise test-only cannot locate it.

Calling into Play framework app from the Scala console

I have a Play Framework 2.3 app. I can drop into a Scala console with activator console. However, when I try to call into code from my app, specifically some helper function which uses WS, which uses the implicit import play.api.Play.current to retrieve the currently running app, I get the error message java.lang.RuntimeException: There is no started application.
What steps do I have to take to be able to load my app into the current console session?
There is a similar existing question, but the accepted answer appears to be using a mock app from the framework's test helpers. Preferably, I would like to run in the context of my actual app. If I must use a fake app, would it be possible to make it match my development environment (what I get when running activator run) rather than my test environment (what I get when running the unit tests)?
Thanks in advance!
In this specific case you can just create an Application instance and use it instead of the implicit one:
// Tested in 2.3.7
import play.api.{Play, Mode, DefaultApplication}
import java.io.File
import play.api.libs.ws.WS
val application = new DefaultApplication(
new File("."),
Thread.currentThread().getContextClassLoader(),
None,
Mode.Dev
)
import scala.concurrent.ExecutionContext.Implicits.global
WS.client(application).url("http://www.google.com").get().map((x) => println(x.body))
For future readers, for Play framework 2.5.x:
import play.api._
val env = Environment(new java.io.File("."), this.getClass.getClassLoader, Mode.Dev)
val context = ApplicationLoader.createContext(env)
val loader = ApplicationLoader(context)
val app = loader.load(context)
Play.start(app)
Source: https://www.playframework.com/documentation/2.5.x/PlayConsole#Launch-the-interactive-console

How to access play configuration from a different module

I have a multi module sbt application, where one of the modules is a play application.
So my module layout is like:
/module1/
/module2/
/module-web <-- this is play 2.x
/module3/
Now in my other modules I am using the typesafe configuration library (com.typesafe.config).
Now I have a module, module3, that will be used inside of my module-web (play) and it will also be used in another project. I will synchronize the application.conf so it is the same in both the play project and in the other project.
My question is, how can I access the play application.conf from inside of module3?
module3 does not have the play framework as a dependency, just the typesaf config library.
I know play lets you do:
Play.current.configuration.getString("db.driver")
Is there something similiar but not using the Play.current method?
You can use the ConfigFactory class (most probably the load method will fit your needs and you can also look at the parseString/parseFile methods), then call toConfig():
import com.typesafe.config.ConfigFactory
import play.api.Configuration
val config = new Configuration(ConfigFactory.load())
config.getString("db.driver") ..etc

'Unable to load a Suite class' while running ScalaTest in IntelliJ

I'm having some issues today with running a simple TestKit test in Intellij. The tests are for Scala code (I have the Scala plug-in for Intellij) and are based on Ray Roestenburg's example.
The Intellij project was created using a "Maven Module" which I then added all the dependencies to and created my project. The tests are located in the following place:
ActorBlast/src/test/scala/basicTest.scala
I'm basically "right-clicking" on the test and selecting "Run". What I get is the following error:
"C:\Program Files\Java\jdk1.7.0_25\bin\java" -Didea.launcher.port=7540...
Testing started at 2:29 PM ...
Unable to load a Suite class. This could be due to an error in your runpath.
Missing class: BasicActorSpec java.lang.ClassNotFoundException:
BasicActorSpec at
java.net.URLClassLoader$1.run(URLClassLoader.java:366) at
java.net.URLClassLoader$1.run(URLClassLoader.java:355) at
java.security.AccessController.doPrivileged(Native Method) at
java.net.URLClassLoader.findClass(URLClassLoader.java:354) at
java.lang.ClassLoader.loadClass(ClassLoader.java:424) at
sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) at
java.lang.ClassLoader.loadClass(ClassLoader.java:357) at
org.scalatest.tools.Runner$$anonfun$35.apply(Runner.scala:2393) at
org.scalatest.tools.Runner$$anonfun$35.apply(Runner.scala:2391) at
scala.collection.TraversableLike$$anonfun$filter$1.apply(TraversableLike.scala:264)
at scala.collection.immutable.List.foreach(List.scala:318) at
scala.collection.TraversableLike$class.filter(TraversableLike.scala:263)
at scala.collection.AbstractTraversable.filter(Traversable.scala:105)
at
org.scalatest.tools.Runner$.doRunRunRunDaDoRunRun(Runner.scala:2391)
at
org.scalatest.tools.Runner$$anonfun$runOptionallyWithPassFailReporter$2.apply(Runner.scala:1006)
at
org.scalatest.tools.Runner$$anonfun$runOptionallyWithPassFailReporter$2.apply(Runner.scala:1005)
at
org.scalatest.tools.Runner$.withClassLoaderAndDispatchReporter(Runner.scala:2659)
at
org.scalatest.tools.Runner$.runOptionallyWithPassFailReporter(Runner.scala:1005)
at org.scalatest.tools.Runner$.run(Runner.scala:845) at
org.scalatest.tools.Runner.run(Runner.scala) at
org.jetbrains.plugins.scala.testingSupport.scalaTest.ScalaTestRunner.runScalaTest2(ScalaTestRunner.java:144)
at
org.jetbrains.plugins.scala.testingSupport.scalaTest.ScalaTestRunner.main(ScalaTestRunner.java:35)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606) at
com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Process finished with exit code 0
I can't figure out what this means. I've done a lot of searching but can't seem to find an answer. Note that the class the runner is complaining about not finding is the class I'm trying to test/run. The basicTest.scala looks like this:
// Testing specific imports
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
import org.scalatest.{ShouldMatchers, WordSpecLike, BeforeAndAfterAll}
import akka.testkit.{TestKit, DefaultTimeout, ImplicitSender}
// Actor specific imports
import akka.actor.{ActorRef, Actor, ActorSystem, Props}
// Misc. needed imports
import scala.concurrent.duration._
import com.typesafe.config.ConfigFactory
// In order to run tests in this module you need to use JUnitRunner (as per scalatest.org)
#RunWith(classOf[JUnitRunner])
class BasicActorSpec extends TestKit(ActorSystem("BasicActorSpec", ConfigFactory.parseString(BasicActorSpec.config)))
with DefaultTimeout with ImplicitSender with WordSpecLike with ShouldMatchers with BeforeAndAfterAll {
import BasicActorSpec._
val echoRef = system.actorOf(Props[EchoActor])
val forwardRef = system.actorOf(Props[ForwardActor])
override def afterAll {
shutdown(system)
}
/**
* The actual tests...
*/
"An EchoActor" should {
"Respond with the same message it receives" in {
within(500 millis) {
echoRef ! "test"
expectMsg("test")
}
}
}
"A Forwarding Actor" should {
"Forward a message it receives" in {
within(500 millis) {
forwardRef ! "test"
expectMsg("test")
}
}
}
}
/**
* Companion object of test class
*/
object BasicActorSpec {
val config =
"""
|akka {
| loglevel = "Warning"
|}
""".stripMargin
/**
* Classes of Actors used in testing
*/
class EchoActor extends Actor {
def receive = {
case msg => sender ! msg
}
}
class ForwardActor(next: ActorRef) extends Actor {
def receive = {
case msg => next ! msg
}
}
}
Any help as to why I am getting this error would be GREATLY appreciated.
Run build the project - It helped me to resolve that issue that could have happened to me when I cleared Cache IDEA :) while trying to tackle another issue
This is how I solved same exception:
--> Right click on your project folder in IDE:
--> Click Add Framework Support
--> Then Check Scala
--> Click OK
My project already had the setup as mentioned by #Rustam Aliyev. Still was getting the same exception. Rebuilding the project did not help either. Quite weird ; but Restarting the IDE helped to solve the issue
This issue happened to me recently when I was trying to run tests in an inherited Scala project using IntelliJ IDEA 2018 (Community Edition). Below steps helped me to fix it:
File → Project Structure → {Choose specific module} → "Paths" tab → Select "Use module compile output path" → Modify "Test output path" to point to test-classes folder. For example:
Output path: /home/rustam/IdeaProjects/{project}/{module}/target/scala-2.12/classes
Test output path: /home/rustam/IdeaProjects/{project}/{module}/target/scala-2.12/test-classes
IntelliJ does not like multiple Scala classes defined in one file, so make sure the test class is named the same as the test file and nest other helper classes, which you can refactor later as necessary.
I met this issue when I used Gatling
I fix it by replacing gatling-classes to test-classes on File -> Project Structure -> Modules -> Module Name -> Paths -> Test output path
You need to set up the Scala SDK.
1.) Usually, intelliJ will ask you by showing a message on right hand corner of your editor
2.) You can do it by yourself as mentioned on the https://www.jetbrains.com/help/idea/discover-intellij-idea-for-scala.html
In my case, I was missing the Scala facet in my module.
https://blog.jetbrains.com/scala/2010/09/02/project-configuration-explained/
I got rid of the error once I configured module properly.
You can try to recompile the test classes:
sbt test:compile
If you are using IntelliJ to run scalatest make sure the class paths are correct. For example:
/dummyApp
your build.sbt should look like, name := "dummyApp". If you name it name := "dummy App" you will get errors.
In my case I had in Preferences -> Build, Execution, Deployment -> sbt
Use sbt shell for build and import checkbox enabled
And the test was not in the expected directory src/test but in src/it (integrated test).
I encountered the error when the test class was not part of any package.
I am using the multi maven module and tried all possibilities here but not able to fix this. But for me I closed the complete IntelliJ -> removed .idea folder -> deleted managed projects from recent projects window.-> reimport the project did the job.
This kind of thing keeps happening to me every now and then. All the more concrete suggestions above have merit. Another possibility (which worked this time for me): Edit the run configuration for your tests; click "Use sbt"; run the tests (this should have no problem since it's just using the sbt-shell to run the tests); now unselect "Use sbt" and try it. It worked for me.
Another one in the long list of checks, if you do not use unique test names you get this error without any hint, in a long test suite it is easier to miss.
Failed
test("Check thing 1") {
class TestClass1 extends MainClass1{
... }
test("Check thing 1") {
class TestClass2 extends MainClass2{
... }
Successful
test("Check thing 1") {
class TestClass1 extends MainClass1{
... }
test("Check thing 2") {
class TestClass2 extends MainClass2{
... }
I got the same message on Idea 2021.1. I tried all the ways above but what helped me is running Scala-tests via sbt like this:
sbt "; project nameOfProject; testOnly some.package.SomeTest"
After that I could debug the same tests via Idea.
I had two modules marked as Test Sources Root and thus it didn't like that. So I unmarked one and then it worked great