2015-08-27 7 views
7

Di seguito è riportato un semplice attore che è necessario effettuare una chiamata HTTP per ricevere dati da un'API. Secondo lo Akka HTTP Core Request-Level Client-Side API sono necessari solo gli ActorSystem e ActorMaterializer.È possibile effettuare una richiesta del client core Akka HTTP all'interno di un attore?

class MyActor extends Actor { 

    import context.system 
    implicit val materializer = ActorMaterializer() 

    override def receive: Receive = { 
    case _ => { 
     val responseFuture: Future[HttpResponse] = Http().singleRequest(HttpRequest(uri = "http://akka.io")) 
     responseFuture onComplete { 
     case Success(res) => println(res) 
     case Failure(t) => println("An error has occured: " + t.getMessage) 
     } 
    } 
    } 
} 

Tuttavia, quando si tenta di compilare l'applicazione ricevo i seguenti messaggi di errore:

Error:(18, 48) ambiguous implicit values: both value context in trait Actor of type => akka.actor.ActorContext and method system in trait ActorContext of type => akka.actor.ActorSystem match expected type akka.actor.ActorRefFactory 
    implicit val materializer = ActorMaterializer() 

Error:(18, 48) implicit ActorRefFactory required: if outside of an Actor you need an implicit ActorSystem, inside of an actor this should be the implicit ActorContext 
    implicit val materializer = ActorMaterializer() 

Error:(18, 48) not enough arguments for method apply: (implicit context: akka.actor.ActorRefFactory)akka.stream.ActorMaterializer in object ActorMaterializer. Unspecified value parameter context. 
    implicit val materializer = ActorMaterializer() 

Error:(22, 70) could not find implicit value for parameter fm: akka.stream.Materializer 
    val responseFuture: Future[HttpResponse] = Http().singleRequest(HttpRequest(uri = "http://akka.io")) 

Error:(22, 70) not enough arguments for method singleRequest: (implicit fm: akka.stream.Materializer)scala.concurrent.Future[akka.http.scaladsl.model.HttpResponse]. Unspecified value parameter fm. 
    val responseFuture: Future[HttpResponse] = Http().singleRequest(HttpRequest(uri = "http://akka.io")) 

Error:(23, 22) Cannot find an implicit ExecutionContext. You might pass an (implicit ec: ExecutionContext) parameter to your method or import scala.concurrent.ExecutionContext.Implicits.global. 
    responseFuture onComplete { 

Error:(23, 22) not enough arguments for method onComplete: (implicit executor: scala.concurrent.ExecutionContext)Unit. Unspecified value parameter executor. 
    responseFuture onComplete { 

E 'questo il modo corretto di effettuare una chiamata HTTP all'interno di un Akka attore?

Modifica

Incluso import ExecutionContext.Implicits.global per sistemare le ultime due ExecutionContext errori.

risposta

10

Per creare ActorMaterializer è necessario un ActorRefFactory implicito. La proprietà context definita nel tratto Actor estende ActorRefFactory ed è implicita. La proprietà di sistema sul contesto, che è stata importata in modo esplicito, è un altro candidato implicito per ActorRefFactory, poiché ActorSystem estende ActorRefFactory.

Il mio suggerimento è rimuovere l'importazione e passarla esplicitamente dove è necessario.

class MyActor extends Actor { 

    // Do not import context.system 
    // import context.system 
    implicit val materializer = ActorMaterializer() 

    override def receive: Receive = { 
    case _ => { 
     // use context.system explicitly 
     val responseFuture: Future[HttpResponse] = Http(context.system) 
     .singleRequest(HttpRequest(uri = "http://akka.io")) 
     responseFuture onComplete { 
     case Success(res) => println(res) 
     case Failure(t) => println("An error has occured: " + t.getMessage) 
     } 
    } 
    } 
}