Jacky Wong
Jacky Wong

Reputation: 521

How to create multiple users in play framework 2.5.x with WebSocket

I followed the documentation at https://www.playframework.com/documentation/2.5.x/ScalaWebSockets

I wrote a chat room with the actor:

def socket = WebSocket.acceptOrResult[String, String] { request =>
        ActorFlow.actorRef(out => MyWebSocketActor.props(out))
}
import akka.actor._
class MyWebSocketActor(out:ActorRef) extends Actor{
    def receive={
        case msg:String =>{
            out ! ("I received your message:"+msg)
            //println(msg)
        }
    }
}
object MyWebSocketActor{
    def props(out:ActorRef)=Props(new MyWebSocketActor(out))
}

But I have got a problem here: While two devices enter my chat room, they have their words only.

How do I create a chat room with Akka Streams and Actor?

Upvotes: 1

Views: 311

Answers (1)

zella
zella

Reputation: 4685

You need modeling your system with actors. MyWebSocketActor represents a single user. You need actor, that represents room with users.

I wrote simple example (explanation in comments):

object MyWebSocketActor {
  case object Init
}

class MyWebSocketActor(out: ActorRef) extends Actor {

  //you can pass precreated room in constructor or receive it from message,
  //based on your logic
  val room: ActorRef = ???

  //when actor starts, it register self in room, we send Init 
  //message, because actors communications should be in `receive`
  override def preStart(): Unit = {
    self ! Init
  }

  //initial state, waiting joining in room 
  def waitingToJoin: Receive = {
    case Init => room ! Join(self)
    case Joined => context become joined
  }

  //joined state, process messages from out and room
  def joined: Receive = {
    case textFromOut: String => room ! Msg(textFromOut)
    case msg: Msg => out ! msg.toString
  }

  //initial state
  override def receive: Receive = waitingToJoin
}


object Room {
  //request to join
  case class Join(user: ActorRef)
  //join response
  case class Joined(room: ActorRef)
  case class Msg(text: String)
}

class Room extends Actor {

  //users in room
  val users: ListBuffer[ActorRef] = ListBuffer()

  override def receive: Receive = {
    case msg: Msg =>
      //send messages to all users
      users.foreach(u => u ! msg)
    //join request
    case Join(user) =>
      context watch user
      users += user
      user ! Joined(self)
    case Terminated(user) =>
      users -= user
  }

}

Upvotes: 2

Related Questions