6
votes

I'm attempting to test out Akka with Play 2.5 and I'm running into a compile error I can't seem to get around.

I'm following this page from the Play docs: https://playframework.com/documentation/2.5.x/ScalaAkka

Here is the full code:

package controllers

import javax.inject.{Inject, Singleton}
import akka.actor.ActorSystem
import controllers.HelloActor.SayHello
import play.api.mvc._
import play.api.libs.concurrent.Execution.Implicits.defaultContext
import scala.concurrent.duration._
import akka.pattern.ask

@Singleton
class Application @Inject()(system: ActorSystem) extends Controller {

  implicit val timeout = 5.seconds

  val helloActor = system.actorOf(HelloActor.props, "hello-actor")

  def sayHello(name: String) = Action.async {
    (helloActor ? SayHello(name)).mapTo[String].map { message =>
      Ok(message)
    }
  }
}

import akka.actor._

object HelloActor {
  def props = Props[HelloActor]

  case class SayHello(name: String)

}

class HelloActor extends Actor {
  import HelloActor._

  def receive = {
    case SayHello(name: String) =>
      sender() ! "Hello, " + name
  }
}

My route looks like:

GET     /:name                      controllers.Application.sayHello(name: String)

And, finally, my build.sbt:

name := "AkkaTest"

version := "1.0"

lazy val `akkatest` = (project in file(".")).enablePlugins(PlayScala)

scalaVersion := "2.11.7"

libraryDependencies ++= Seq( jdbc , cache , ws   , specs2 % Test )

unmanagedResourceDirectories in Test <+=  baseDirectory ( _ /"target/web/public/test" )  

resolvers += "scalaz-bintray" at "https://dl.bintray.com/scalaz/releases"

routesGenerator := InjectedRoutesGenerator

When I attempt to run this, I get the following compilation error:

could not find implicit value for parameter timeout: akka.util.Timeout

I've tried moving around the timeout to no avail. Does anyone have an idea what might cause this compilation error?

1

1 Answers

13
votes

You getting this error because the ask pattern requires an implicit timeout for asking (it will complete future with TimeoutException if no answer was received for this time). So all you need is to create an implicit local value in sayHello method like this:

import akka.util.Timeout
import scala.concurrent.duration.Duration

// ...

  def sayHello(name: String) = Action.async {
    implicit val timeout: Timeout = Duration.Infinite
    (helloActor ? SayHello(name)).mapTo[String].map { message =>
      Ok(message)
    }
  }

Instead of specifying infinite timeout you can specifiy a finite one with following syntax:

import scala.concurrent.duration._
import akka.util.Timeout

implicit val duration: Timeout = 20 seconds