2015-08-27 12 views
7

Aşağıda, bir API'dan veri almak için bir HTTP çağrısı yapmak için gerekli olan basit bir oyuncu vardır. Akka HTTP Core Request-Level Client-Side API'a göre, yalnızca ActorSystem ve ActorMaterializer, zımni olarak gereklidir. AncakBir Aktör içinde bir Akka HTTP çekirdek istemci isteği yapmak mümkün mü?

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

, aşağıdaki hata iletilerini almak uygulamayı derlemeye çalışırken:

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 { 

bu bir Akka aktör içinde bir HTTP çağrısı yapmak için doğru yolu var mı?

Düzenleme

son iki ExecutionContext hataları düzeltmek için import ExecutionContext.Implicits.global Dahil.

cevap

10

ActorMaterializer'ı oluşturmak için örtülü bir ActorRefFactory gerekir. Aktör özelliğinde tanımlanan içerik özelliği, ActorRefFactory'yi genişletir ve örtülüdür. ActorSystem, ActorRefFactory'yi genişlettiği için, açık bir şekilde içe aktardığınız sistem özelliği ActorRefFactory için başka bir örtülü adaydır.

Önerim, içe aktarma işlemini kaldırmak ve gereken yere açıkça iletmektir.

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