Cannot understand Scala method definition - scala

This is some code from Alvin Alexander's minimal Scala Websocket server.
package controllers
import play.api.mvc._
import play.api.libs.streams.ActorFlow
import javax.inject.Inject
import akka.actor.ActorSystem
import akka.stream.Materializer
import models.SimpleWebSocketActor
import play.api.libs.json._
class WebSocketsController #Inject() (cc: ControllerComponents)(implicit system: ActorSystem)
extends AbstractController(cc)
{
def index = Action { implicit request: Request[AnyContent] =>
logger.info("index page was called")
Ok(views.html.index())
}
}
What I'm curious about is the method definition for index. The notation is different to the normal method definition I've seen in Scala. Could someone explain what is going on here, and possibly point to some docs on this syntax? I haven't been able to find anything.

This definition is a combination of several syntax features of Scala but in the end there's nothing that special about it.
It's equivalent to something like this:
def index = {
def handleRequest(request: Request[AnyContent]) = {
implicit req = request
logger.info("index page was called")
Ok(views.html.index())
}
Action.apply(handleRequest) // Replaced by Action(...), then Action { ... }
}

Related

having problems calling a method from controller in scala

i'm using playframework with scala and slick.
in my dto (dao) I do this:
class processDTO #Inject() (protected val dbConfigProvider: DatabaseConfigProvider) extends HasDatabaseConfigProvider[JdbcProfile]
with ProcessTemplatesComponent {
import driver.api._
private val processTemplates = TableQuery[ProcessTemplates]
def getAll(): Future[Seq[ProcessTemplatesModel]] = db.run { processTemplates.to[Seq].result }
}
and in controller I do this:
#Singleton
class ProcessesController #Inject() (processDTO: processDTO, actionBuilder: ActionBuilders) extends Controller{
def getProcesses() = actionBuilder.DynamicAction(name = "pureLuck").defaultHandler() {
request =>
processDTO.getAll().map(_.map(result => {
}))
.map(result => Ok(Json.toJson(result)))
}
}
and now I got this error
First of all you need to import execution context. PlayFramework has his own context. Add this import play.api.libs.concurrent.Execution.Implicits._ Play documentation
Also you need to return something from this code of block:
_.map(result => {})
Currently you return Unit which can't be transformed to json.
The error tells you what you need to know. Adding import scala.concurrent.ExecutionContext.Implicits.global at the top of your file should fix it.
One issue is the lack of execution context as other had mentioned.
As of your json error, you need to implement a Write converter to transform your ProcessTemplatesModel objects into json.

Why are implicit variables not initialized in Scala when called from unit test?

Given the the following singleton Object in Scala:
package demo
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Directives._
import akka.stream.ActorMaterializer
import scala.concurrent.Future
import scala.io.StdIn
object WebServer extends App {
implicit val system = ActorSystem("myActorSystem")
implicit val executionContext = system.dispatcher
implicit val materializer = ActorMaterializer()
val route = {
path("api" / "done-as-promised") {
get {
complete {
Future.successful("done")
}
}
}
}
val bindingFuture = Http().bindAndHandle(route, "localhost", 8080)
}
And the following unit test
package demo
import akka.http.scaladsl.testkit.ScalatestRouteTest
import org.scalactic.TypeCheckedTripleEquals
import org.scalatest.{Inspectors, Matchers, WordSpec}
class WebServerSpec extends WordSpec with Matchers with TypeCheckedTripleEquals with Inspectors with ScalatestRouteTest {
"The WebServer /done-as-promised" should {
"return done" in {
// tests:
Get("/api/done-as-promised") ~> WebServer.route ~> check {
status.intValue() shouldEqual 200
responseAs[String] shouldEqual "done"
}
}
}
}
I get the following error:
[ERROR] [04/19/2016 07:12:18.995]
[ScalaTest-run-running-WebServerSpec]
[akka.actor.ActorSystemImpl(demo-WebServerSpec)] Error during
processing of request
HttpRequest(HttpMethod(GET),http://example.com/api/done-as-promised,List(),HttpEntity.Strict(none/none,ByteString()),HttpProtocol(HTTP/1.1))
java.lang.NullPointerException at
akka.http.scaladsl.server.directives.ExecutionDirectives$$anonfun$handleExceptions$1$$anonfun$apply$1.apply(ExecutionDirectives.scala:33)
at
akka.http.scaladsl.server.directives.ExecutionDirectives$$anonfun$handleExceptions$1$$anonfun$apply$1.apply(ExecutionDirectives.scala:29)
at
akka.http.scaladsl.testkit.RouteTest$TildeArrow$$anon$1.apply(RouteTest.scala:162)
at
akka.http.scaladsl.testkit.RouteTest$TildeArrow$$anon$1.apply(RouteTest.scala:150)
It took me a while to figure out. The thing is: removing the extends app will make the test succeed.
The reason for the problem is that when WebServer is declared as extends App, it uses the DelayedInit functionality of the App trait. Because of this, the initialization code in the contructor is not added to the constructor of the WebServer object. Instead is called when the main method is called on the WebServer. So when he references the "route" inside the tests, those are all coming up null.
Mixing in the DelayedInit trait (App extends from DelayedInit) will rewrite your class or object template. Instead of adding your val's and var's to the constructor, it will be added to the def delayedInit(body: => Unit) hook (inaccessible to user code). Apparently this one is called whenever the main method is called.
You can verify this by simply calling "main" on the WebServer inside the test. If you do this, then the test will pass. This is because calling main triggers the initialization resulting in those objects being created.
Generally speaking though the right solution is probably to move the routing to somewhere else, rather than having it inside of the base App.

Getting implicit val from the companion object

I'm playing with Scala Spray. I enjoy working with it but can't figure out one thing.
This code compiles fine:
import spray.http.MediaTypes._
import spray.routing.HttpService
import spray.json.{DefaultJsonProtocol, _}
import spray.httpx.SprayJsonSupport._
trait StatusService extends HttpService {
case class StatusResponse(status: String)
object StatusResponseProtocol extends DefaultJsonProtocol {
implicit val statusResponse = jsonFormat1(StatusResponse)
}
import StatusResponseProtocol._
val statusRoute =
path("status") {
get {
respondWithMediaType(`application/json`) {
complete {
StatusResponse("OK")
}
}
}
}
}
But it doesn't compile (can't find json serializer) when I move case class & protocol to the companion object.
trait StatusService extends HttpService {
import StatusResponseProtocol._
val statusRoute =
path("status") {
get {
respondWithMediaType(`application/json`) {
complete {
StatusResponse("OK")
}
}
}
}
}
object StatusService {
case class StatusResponse(status: String)
object StatusResponseProtocol extends DefaultJsonProtocol {
implicit val statusResponse = jsonFormat1(StatusResponse)
}
}
I do not understand why..
I think the problem might be in your import statement. If you import from a companion object, it should be done like this:
trait StatusService extends HttpService {
import StatusService.StatusResponseProtocol._
The rest of the code doesn't have to be changed.
I think I've had pretty much the same problem. Try replacing:
import spray.httpx.SprayJsonSupport._
with
import spray.json._
It worked for me.
I noticed today (in another context, not Spray) that providing a type for the implicit val in a companion object made it visible.
So, I'm thinking whether this would make it work in your case:
implicit val statusResponse: RootJsonFormat[StatusResponse] = jsonFormat1(StatusResponse)
Note: I'm not sure of the type I added - it may not be what jsonFormat1 returns. Also, the Spray.json documentation does not use types. Anyways, if someone has the time to try this out, I'd be interested to know..

Spray.io case class extraction error

I'm learning spray.io, and I'm stuck in a problem.. I'm trying to test the case class extraction of several GET parameters. My code is inspired by the examples from the documentation page :
package com.example
import akka.actor.Actor
import spray.routing._
import spray.http._
import MediaTypes._
class ServiceActor extends Actor
with ServiceHello {
def actorRefFactory = context
def receive = runRoute(testRoute)
trait ServiceHello extends HttpService with Controls {
case class Color(keyword: String, sort_order: Int, sort_key: String)
val route =
path("test") {
parameters('keyword.as[String], 'sort_order.as[Int], 'sort_key.as[String]).as(Color) { color =>
handleTestRoute(color) // route working with the Color instance
}
}
}
This code should be ok, but when I try to run it, I got the following errors :
Cannot resolve symbol as (on top of "as(Color)" )
Missing parameter type: color (on top of "{ color =>")
I understand these errors, but i do not understand why they come...
I'm running Scala 2.10.3
Am I doing something wrong ?
Thats working for me (scala 2.10.4, spray 1.3.1):
import akka.actor.Actor
import spray.routing._
import spray.http._
import MediaTypes._
class ServiceActor extends Actor with ServiceHello {
def actorRefFactory = context
def receive = runRoute(testRoute)
}
trait ServiceHello extends HttpService {
case class Color(keyword: String, sort_order: Int, sort_key: String)
val testRoute =
path("test") {
parameters('keyword.as[String], 'sort_order.as[Int], 'sort_key.as[String]).as(Color) { color =>
//handleTestRoute(color) // route working with the Color instance
complete {
<h1>test route</h1>
}
}
}
}
Don't know what Controls is, so I just commented it.

Instantiating Akka actors in a Play application with Subcut

I have a Play 2.1 application. I am also using Subcut for dependency injection, which is already set up and working for most parts of the application, except for one.
Say I have the following snippet of actor-related code:
import akka.actor._
import com.typesafe.plugin._
import play.api.Play.current
import play.api.libs.concurrent.Akka
class FoobarActor extends Actor {
def receive = {
// do stuff here
}
}
object Foobar {
val actor = Akka.system.actorOf(Props[FoobarActor])
}
Now, say I would like to inject some objects into each instance of the FoobarActor using Subcut. This would require the actor class to extend Injectable, with the BindingModule passed into the constructor, like this:
import akka.actor._
import com.typesafe.plugin._
import play.api.Play.current
import play.api.libs.concurrent.Akka
import com.escalatesoft.subcut.inject.{Injectable, BindingModule}
class FoobarActor(implicit val bindingModule: BindingModule) extends Actor
with Injectable {
val bazProvider = inject[BazProvider]
val quuxProvider = inject[QuuxProvider]
def receive = {
// do stuff here
}
}
The question is: how is such an actor instantiated?
Typically, objects managed by Subcut are constructed in Subcut's configuration objects (i.e., objects that extend NewBindingModule), or in the case of Play's controllers, in the Global object (see play-subcut on github).
What would I replace Akka.system.actorOf(Props[FoobarActor]) with in order to override the instantiation of actors in order to pass in the binding module?
object Foobar {
val actor = /* what goes here? */
}
As Roland mentioned, this should be as simple as just instantiating the actor with a constructor argument. I wasn't sure the implicit would work with Akka's way of doing actor instantiation with constructor args but it seems to work okay. The code should look something like this:
class FoobarActor(implicit val bindingModule: BindingModule) extends Actor
with Injectable {
val bazProvider = inject[BazProvider]
val quuxProvider = inject[QuuxProvider]
def receive = {
// do stuff here
}
}
object FoobarActor {
def apply(implicit bindingModule:BindingModule) = {
Akka.system.actorOf(Props(classOf[FoobarActor], bindingModule))
}
}
Then, if you wanted to instantiate the FoobarActor, as long as you had an implicit BindingModule in scope, you could just do:
val ref = FoobarActor()