Scala, Play, Akka, Websocket: how to transfer advertising messages through websocket

I have an actor who starts with the application, works in the background, looking at certain changes, and if there are any messages about them. At the moment this is just println for the console. What I need to do is when a new message appears - send it to the forefront using Websocket.

This is my Play Global object, in which the monitoring / listening executor is launched:

 object Global extends GlobalSettings { override def onStart(app: Application) { class Listener extends Actor { //This needs to be changed to pass messages to Websocket, how? def receive = { case Create(path) => println("CREATE " + path) case Delete(path) => println("DELETE " + path) case Modify(path) => println("MODIFY " + path) } } val listener = Akka.system.actorOf(Props[Listener], "listener") val swatch = Akka.system.actorOf(Props[SwatchActor], "swatch") swatch ! Watch("/folder/path", Seq(Create, Modify, Delete), true, Some(listener)) } } 

This is my play controller:

 object Application extends Controller { def test = WebSocket.using[String] { request => //This hopefully gets the listener actor reference? val listener = Akka.system.actorSelection("/user/listener") val (out, channel) = Concurrent.broadcast[String] val in = Iteratee.foreach[String] { msg => //Actor messages must be pushed here, how? channel push("RESPONSE: " + msg) } (in, out) } } 

I understand that in order to establish a connection with websocket, there must be an initial "in".

So my problems are:

  • How do I change the Listener actor to type messages in Websocket?
  • What do I need to do to prepare an actor for clicking messages after establishing a connection to a web socket?
  • How do I click messages from a listener on a website?
+7
scala akka websocket playframework
source share
2 answers

I have found a solution.

The case class to be imported from a separate file:

 case class Start(out: Concurrent.Channel[String]) 

Global object:

 object Global extends GlobalSettings { override def onStart(app: Application) { class Listener extends Actor { var out = { val (enum, chan) = Concurrent.broadcast[String] chan } def receive = { //Websocket channel out is set here case Start(out) => this.out = out //Pushing messages to Websocket case Create(path) => this.out.push(path.toString) case Delete(path) => this.out.push(path.toString) case Modify(path) => this.out.push(path.toString) } } val listener = Akka.system.actorOf(Props[Listener], "listener") val swatch = Akka.system.actorOf(Props[SwatchActor], "swatch") swatch ! Watch("/folder/path", Seq(Create, Modify, Delete), true, Option(listener)) } } 

Playback controller:

 object Application extends Controller { def test = WebSocket.using[String] { request => val (out, channel) = Concurrent.broadcast[String] val listener = Akka.system.actorSelection("akka://application/user/listener") //This is where the websocket out channel is being passed to the listener actor listener ! Start(channel) val in = Iteratee.foreach[String] { msg => channel push("RESPONSE: " + msg) } (in, out) } } 
+6
source share

The other day I wrote this, which will be included in Play 2.3. You can copy it to your application:

https://github.com/jroper/ReactiveMaps/blob/websocket-actor/app/actors/WebSocketActor.scala

You give him the object of props, and he will create an actor for you. You are sending to WebSocket by sending to context.parent.

+2
source share

All Articles