2016-04-22 12 views
1

zunächst allen danke Ihnen für einige Zeit nehmen, um mein Problem zu überprüfen. Ich bin ein Neuling im Scala-Ökosystem, also denke ich, dass ich einige Konzepte durcheinander bringe.Play 2.4 erstellen Sie einen Schauspieler für Handle WebSocket mit Guice

Ich stelle Guice in einem Play 2.4-Projekt vor und es funktioniert in einigen REST-Controllern. Ich habe build.sbt bearbeitet routesGenerator := InjectedRoutesGenerator als Wiedergabe offiziellen doc recomends anhängen und bearbeitet meine Routen, wie Sie im folgenden Beispiel sehen:

GET  /socket  @com.letgo.chat.controllers.ChatController.socket 

Meine Modul Schauspieler zum Injizieren wie folgt aussieht:

class ChatModule extends AbstractModule with ScalaModule with AkkaGuiceSupport with GuiceAkkaActorRefProvider { 
    override def configure() { 

    bindActor[TalkerProviderActor](TalkerProviderActor.name) 
    ... 

Und all das scheint zu funktionieren.

Aber ein anderer Endpunkt behandelt einen Websocket mit Play-Methode WebSocket.acceptWithActor. Ich muss einen Akteur schaffen, der auch einige Abhängigkeiten benötigt.

Der Controller erzeugt ein ConnectionActor:

class ConnectionActor(
    @Assisted() websocket: ActorRef, 
    monitoring: Monitoring, 
    @Named(BouncerActor.name) bouncer: ActorRef, 
) extends Actor 

... 

class ChatController @Inject() extends Controller { 
    def socket(): WebSocket[String, JsValue] = WebSocket.acceptWithActor[String, JsValue] { request => out => 
    // I had the following statement in order to build the actor before introducing Guice: 
    // ConnectionActor.props() 
    // Now, I need some magic here 
    } 
} 

So wie Sie ich brauche eine websocket: ActorRef für die websocket Ausgabe zu sehen.

Ich habe einige Akteure in anderen Teilen der Anwendung erstellt von AkkaGuiceSupport bereitgestellt bindActorFactory Methode:

bindActorFactory[TalkerActor, TalkerActor.Factory] 

Aber ich weiß nicht, wie ich für die Handhabung des websocket in diesem Fall einen Schauspieler schaffen soll. Kannst du mir helfen?

Danke

Antwort

3

Ich glaube, das den Trick tun können:

package controllers 

import javax.inject._ 

import akka.actor.{Actor, ActorRef, ActorSystem, Props} 
import akka.stream.Materializer 
import play.api.libs.streams.ActorFlow 
import play.api.libs.ws.WSClient 
import play.api.mvc._ 

import scala.concurrent.ExecutionContext.Implicits.global 

@Singleton 
class SocketActorProvider @Inject() (ws: WSClient) { 
    def get(out: ActorRef) = Props(new SocketActor(out, ws)) 
} 

class SocketActor(out: ActorRef, ws: WSClient) extends Actor { 
    override def receive: Receive = { 
    case "ping" => ws.url("http://localhost:9000/pong").get().foreach(pong => out ! pong.body) 
    } 
} 

@Singleton 
class HomeController @Inject() (implicit system: ActorSystem, ws: WSClient, materializer: Materializer, provider: SocketActorProvider) extends Controller { 

    // route '/ws' 
    def socket = WebSocket.accept[String, String] { request => 
    ActorFlow.actorRef(out => provider.get(out)) 
    } 

    // route '/pong' 
    def pong = Action { 
    Ok("PONG!") 
    } 

    // route '/' 
    def index = Action { 
    Ok(""" 
     <script> 
     var ws = new WebSocket('ws://localhost:9000/ws'); 
     ws.onopen =() => console.log('I am open!'); 
     ws.onmessage = m => console.log(m.data); 

     setInterval(() => {console.log('ping'); ws.send('ping')}, 1000) 
     </script> 
    """).as("text/html") 
    } 

} 

Wie Sie ein Anbieter von Guice injiziert ist, die hatte WSClient injiziert und wenn ein Schauspieler Gebäude sehen kann geht es in der Abhängigkeit

+0

danke roger! Ich werde es mir ansehen. – SergiGP