2015-08-27 11 views
7

Poniżej znajduje się prosty aktor, który jest wymagany do wykonania połączenia HTTP w celu odebrania danych z interfejsu API. Zgodnie z Akka HTTP Core Request-Level Client-Side API tylko implicite wymagają tylko ActorSystem i ActorMaterializer.Czy jest możliwe utworzenie żądania klienta rdzenia HTTP Akka wewnątrz aktora?

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) 
     } 
    } 
    } 
} 

Jednak przy próbie kompilacji aplikacji otrzymuję następujące komunikaty o błędach:

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 { 

Jest to poprawny sposób, aby nawiązać połączenie HTTP wewnątrz aktora Akka?

Edit

wliczony import ExecutionContext.Implicits.global naprawić dwa ostatnie ExecutionContext błędów.

Odpowiedz

10

Do utworzenia ActorMaterializer wymagany jest niejawny ActorRefFactory. Właściwość kontekstu zdefiniowana w funkcji Aktor rozszerza element ActorRefFactory i jest niejawny. Właściwość systemowa w kontekście, którą zaimportowano jawnie, jest kolejnym niejawnym kandydatem do ActorRefFactory, ponieważ ActorSystem rozszerza ActorRefFactory.

Moja sugestia polega na usunięciu importu i podaniu go tam, gdzie jest on potrzebny.

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) 
     } 
    } 
    } 
}