How to execute a request from another actor when using akka-http

I am using akka-http 1.0 and I would like to use a route defined as

def route: Route = path("") { // start actor with requestContext // call requestContext.complete(...) in actor with the result } 

How to do it?

+7
scala
source share
2 answers

In developing @jrudolph's comment, the code below satisfies your requirements for sending RequestContext values ​​to an Actor. Your question stated that you needed a new actor for each request; however, the code below uses the same Actor for all queries, which, in my opinion, are a more efficient / probable use case. When creating an actor, you can always move inside handleRequest.

First, we need an actor to process the response request:

 import akka.actor.Actor import akka.http.scaladsl.server.{RequestContext, RouteResult} import akka.http.scaladsl.model.HttpResponse class RequestActor extends Actor { //business logic - returns empty HttpResponse def handleRequestMessage(requestContext : RequestContext) = RouteResult.Complete(new HttpResponse()) override def receive = { case reqContext : RequestContext => sender ! handleRequestMessage(reqContext) } }//end class RequestActor 

Now create a utility function to query the Actor:

 import akka.actor.ActorRef import scala.concurrent.Future import akka.pattern.ask object RequestActor { val handleRequest : ActorRef => RequestContext => Future[RouteResult] = (actorRef) => (requestContext) => ask(actorRef,reqContext).mapTo[RouteResult] } 

And all that remains to be done is to put everything together in a service:

 import akka.actor.{ActorSystem, Props} import akka.stream.ActorMaterializer import akka.http.scaladsl.Http import akka.http.scaladsl.server.Directives.{get,path} import akka.util.Timeout object RouteActorTest extends App { implicit val as = ActorSystem("RouteActorTest") implicit val timeout = new Timeout(1000) val sendRequestToActor : RequestContext => Future[RouteResult] = RequestActor handleRequest (as actorOf Props[RequestActor]) val route = path("")(get(sendRequestToActor)) //rest of application... }//end object RouteActorTest 
+7
source

you can try even better:

 package controllers import akka.actor.{Actor, ActorSystem, Props} import akka.stream.ActorMaterializer import scala.concurrent.{Await, Future} import akka.http.scaladsl.server.Directives._ import akka.stream.ActorMaterializer import akka.util.Timeout import akka.pattern.ask import scala.concurrent.Await import scala.concurrent.duration._ import scala.io.StdIn import akka.actor._ import akka.util.Timeout case object Message class TestActor(name:String) extends Actor { def receive = { case Message => sender ! "Testing Ask pattern Approach" println(s"hello from $name") case _ => println("that was unexpected") } } object AskTest extends App { implicit val system= ActorSystem("myactor") implicit val material=ActorMaterializer() // implicit val props=Props.empty implicit val timeout = Timeout(5 seconds) implicit val result =system.actorOf(Props(new TestActor("TestingName")),name = "Scala") val future3:Future[String]= ask(result ,Message).mapTo[String] val results = Await.result(future3, 2 seconds) println(results) } 
+2
source

All Articles