2013-12-07 8 views
3

Я пытаюсь написать простой HTTP-клиент, используя Scala и spray-client. Я основываю мой клиент на примерах, приведенных на Spray docs.Scala spray-client определяет implicits для AKKA ActorRefFactory

Моя проблема заключается в том, что пример создания нового неявное ActorSystem т.е.

implicit val system = ActorSystem() 

, но я хочу, чтобы мой клиент для повторного использования, а не создавать новую ActorSystem.

Вот суть моего кода.

trait WebClient { 
    def get(url: String)(implicit system: ActorSystem): Future[String] 
} 

object SprayWebClient extends WebClient { 
    val pipeline: HttpRequest => Future[HttpResponse] = sendReceive 

    def get(url: String): Future[String] = { 
    val r = pipeline (Get("http://some.url/")) 
    r.map(_.entity.asString) 
    } 

} 

Но я получаю две ошибки компилятора относительно implicits

implicit ActorRefFactory required: if outside of an Actor you need an implicit ActorSystem, inside of an actor this should be the implicit ActorContext WebClient.scala ... 

и

not enough arguments for method sendReceive: (implicit refFactory: akka.actor.ActorRefFactory, implicit executionContext: scala.concurrent.ExecutionContext, implicit futureTimeout: akka.util.Timeout)spray.http.HttpRequest => scala.concurrent.Future[spray.http.HttpResponse]. Unspecified value parameters refFactory, executionContext. WebClient.scala... 

Как следует изменить определения API?

ответ

10

Вот одно решение:

import akka.actor.ActorSystem 
import spray.http.{HttpRequest, HttpResponse} 
import scala.concurrent.Future 
import spray.client.pipelining._ 

trait WebClient { 
    def get(url: String): Future[String] 
} 

class SprayWebClient(implicit system: ActorSystem) extends WebClient { 
    import system.dispatcher 

    val pipeline: HttpRequest => Future[HttpResponse] = sendReceive 

    def get(url: String): Future[String] = { 
    val r = pipeline (Get("http://some.url/")) 
    r.map(_.entity.asString) 
    } 
} 

и вот еще что сохраняет первоначальную WebClient.get подпись:

import akka.actor.ActorSystem 
import spray.http.{HttpRequest, HttpResponse} 
import scala.concurrent.Future 
import spray.client.pipelining._ 

trait WebClient { 
    def get(url: String)(implicit system: ActorSystem): Future[String] 
} 

object SprayWebClient extends WebClient { 
    def get(url: String)(implicit system: ActorSystem): Future[String] = { 
    import system.dispatcher 

    val pipeline: HttpRequest => Future[HttpResponse] = sendReceive 
    val r = pipeline (Get("http://some.url/")) 
    r.map(_.entity.asString) 
    } 
} 

Второй немного дороже, поскольку трубопровод создается заново каждый раз, даже если он теоретически статичен на ActorSystem. Я бы предпочел первое решение и попытался найти способ распространения WebClient через ваше приложение (используя шаблон торта, передав его явно или используя другие методы инъекции зависимостей).

+0

Я пошел на первое решение, поскольку я как бы тяготел к этому. Также я делаю курс coursera, и образец был похож. Благодарю. –

+0

+1 это было полезно. Благодаря! – maasg