2016-10-02 5 views
2

Я создал веб-сервис с помощью Play & Akka и теперь вам необходимо интегрировать другой Web-сервис, где мой веб-сервис является клиентом.Использование WebService с Аккой Актеры и игровая платформа

Моего контроллер по умолчанию (с соответствующим маршрутами файлом) выглядит

class myController @Inject() (implicit val messagesApi: MessagesApi, 
    config: play.api.Configuration) extends Controller with I18nSupport { 
// Actions 
} 

Это раскручивает большую систему актера и все хорошо.

Один из актеров определяется как ниже -

class ActorMgr (jobId: Long, 
    config: Config) extends Actor with ActorLogging { 
// Actor specific stuff 
} 

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

я видел и следовал инструкции из (среди прочих)

  1. https://playframework.com/documentation/2.5.x/ScalaWS
  2. Dependency injection with abstract class and object in Play Framework 2.5

В соответствии с приведенными выше инструкциями, я должен вводить WSClient в класс, где мне нужно для доступа к нему.

Я в состоянии решить инъекции зависимостей во второй контроллер, как показано ниже

class DbController @Inject() (ws: WSClient) extends Controller { 
    def post = Action { 
     // access webservice 
    } 
} 

Это работает, и я могу выполнить «пост» действие, путем доступа к URL, что она отображается в маршрутах файл и, следовательно, доступ к веб-службе. У меня также есть два контроллера.

Моя проблема заключается в доступе к методу «post» контроллера веб-сервиса от ActorMgr (Акка Акка). Как мне включить это?

+0

Вы можете использовать инъекции зависимостей для создания актеров, смотрите здесь: https://www.playframework.com/documentation/2.5.x/ScalaAkka# Зависимость-впрыскивающие субъекты – Haspemulator

+0

Haspemulator, спасибо за ваш ответ. Он ответил на части моего первоначального вопроса (как я могу влиться в актера), но не решил мою проблему. Я перефразировал части своего вопроса, чтобы это было более ясно. –

+0

Вот что, наконец, –

ответ

0

После много исследований я хотел обновить мои результаты здесь. Хотя мне удалось решить мою конкретную проблему, как показано ниже, здесь еще многое нужно сказать.

Мой конкретное решение первой -

Вместо DbController, я wraped моей службы, как показано ниже, и вводят его в случае необходимости -

trait Db { 
    def post 
} 

class InfluxDb @Inject() (ws: WSClient) extends Db { 
    val logger = LoggerFactory.getLogger(classOf[InfluxDb]) 
    logger.info("InfluxDb: Initiatlized")  

    def post = { 


    val req = ws.url("http://localhost:9086/write") 
       .withQueryString("db" -> "db1") 
       .withHeaders("Content-Type" -> "application/json") 
       .post("job_id,command=PUT value=99") 

    logger.debug("InfluxDb: Post")  
    } 
} 

Сказав, что, впрыскивая материал дал мне массу проблем. Я, наконец, понял, что есть несколько случаев, отчетливый использование здесь -

  1. Использование Акку & Guice и не используя Playframework
  2. Использование Playframework + Akka + Guice и нагнетание верхнего уровня актера
  3. Использование Playframework + Akka + Guice и инъекции детских актеров
  4. Использование playframework + Akka + Guice НО создание не "инъекции g "ваш актер верхнего уровня & Система исполнителей.

Вот как вы могли бы решить каждый из вышеперечисленных.

  1. Для (1) - Обратитесь к guice akka tutorial
  2. Для (2) & (3) - см Playframework Documentation
  3. Для (4) Это немного сложнее

Вы будете необходимо расширить «IndirectActorProducer», а затем использовать его для создания вашего ActorRef. Проблема заключается в том, что «реквизит» не знает, как взаимодействовать с Guice. Это также является частью решения в (1)

Нижеприведенный пример кода показывает все 4 варианта использования и компилирует. В коде ниже

ParentActor - указывает на использование корпуса (2) выше, ChildActor для использования корпуса (3) и ParentActor_2 & ChildActor_2 для использования корпуса (4).

// play imports 
import play.api.mvc._ 
import play.api.Logger 
import play.api.mvc.Results 

// actor imports 
import akka.actor.{Actor, ActorSystem, ActorRef, Props, IndirectActorProducer} 

// DI imports 
import com.google.inject.{Injector, AbstractModule, Key, Provides} 
import javax.inject._ 
import com.google.inject.assistedinject.Assisted 
import play.libs.akka.AkkaGuiceSupport 
import play.api.libs.concurrent.InjectedActorSupport 


class MainCntrlr @Inject() (injector : Injector, 
          @Named("PActor") pa: ActorRef, 
          cfP: ParentActor_2.Factory) 
          extends Controller { 
    Logger.debug("MainCntrlr: created")  

    val pa_2 = ActorSystem("test") 
       .actorOf(Props(classOf[GuiceActorProducer], injector, "PActor_2"), "PA_2") 

    pa ! 12    
    pa_2 ! 100 

    def index   = Action { Ok (views.html.index.render()) } 
} 


class ParentActor @Inject() (cf: ChildActor.Factory) extends Actor with InjectedActorSupport { 
    Logger.debug("ParentActor: created") 
    val cactor = injectedChild(cf(2),"childActor") 
    cactor ! 10 

    def receive = { case _ => Logger.debug("ParentActor received msg") } 
} 


object ChildActor { trait Factory { def apply(i: Int) : Actor } } 
class ChildActor @Inject()(i: Injector, @Assisted v: Int) extends Actor { 
    Logger.debug("ChildActor: created with value " + v.toString) 

    def receive = { case _ => Logger.debug("ChildActor received msg") } 
} 

class ParentModule extends AbstractModule with AkkaGuiceSupport { 
    def configure() = { 
    bindActor(classOf[ParentActor],"PActor") 
    bindActorFactory(classOf[ChildActor], classOf[ChildActor.Factory]) 
    bindActorFactory(classOf[ParentActor_2], classOf[ParentActor_2.Factory]) 
    bindActorFactory(classOf[ChildActor_2], classOf[ChildActor_2.Factory]) 
    } 
} 


object ParentActor_2 { trait Factory { def apply() : Actor } } 
class ParentActor_2 @Inject() (cf: ChildActor_2.Factory) extends Actor with InjectedActorSupport { 
    Logger.debug("ParentActor_2: created") 
    val cactor = injectedChild(cf(4),"childActor_2") 
    cactor ! 10 

    def receive = { case _ => Logger.debug("ParentActor_2 received msg") } 
} 


object ChildActor_2 { trait Factory { def apply(i: Int) : Actor } } 
class ChildActor_2 @Inject() (i: Injector, @Assisted v: Int) extends Actor { 
    Logger.debug("ChildActor_2: created with value " + v.toString) 

    def receive = { case _ => Logger.debug("ChildActor_2 received msg") } 
} 


class GuiceActorProducer(val injector: Injector, val actorName: String) 
     extends IndirectActorProducer { 

    override def actorClass = classOf[ParentActor_2] 
    override def produce() = 
    injector.getBinding(Key.get(classOf[ParentActor_2])).getProvider.get() 
} 

А потом в моей application.conf

play.modules.enabled += "package.ParentModule"