Category Archives: scala

WebSockets Echo Using Play, Scala, and Actors, Part I

There’s a perfectly good example of a simple chat room server using the Play Framework, WebSockets, and Actors.  But other than the example code and one page in the tutorial, using WebSockets with Actors isn’t terribly well-documented.  So I thought I’d walk through an even simpler example that makes use of WebSockets and Actors, and explain what’s going on in more detail.

This echo server accepts a WebSocket connection then runs indefinitely until the client closes the connection. Each WebSocket message received is echoed back to the client:

  def simpleIterateeWebSocket = WebSocket.using[String] {
    val out = Enumerator.imperative[String]()
    val in = Iteratee.foreach[String] {
      msg =>
        out.push(msg)
    }
    (in, out)
  }

You can try out all the code in this tutorial by cloning the github repo. Use the echo test at websocket.org and point it to ws://localhost:9000/wsSimple. Each example in this tutorial has its own URL that you can see in the routes file.

Iteratees

What’s going on here? First off, it’s important to understand Play iteratees. I won’t go into iteratees in great detail here other than to say that they’re a deeply interesting functional programming technique, and an incredibly useful one as well. There are already a few useful guides to them that I encourage you to read.

WebSocket.using takes a block returning an (in, out) pair. in as an Iteratee that will handle incoming messages — the framework will deliver WebSocket messages from the client to this iteratee. And out is an Enumerator that acts as an outbound channel. out can be used to send messages back to the client.

The easiest way to understand Iteratee.foreach is that it’s like an “onMessage” event handler. Iteratees are more powerful and general than event handlers. Iteratee.foreach creates a specialized iteratee that invokes the block on each message received. In this sense, in isn’t really the input stream so much as the handler on that input stream.

The out val is the Enumerator that will be used to send messages back to the client. An ordinary enumerator would be crafted by chaining messages together using various basic enumerators and combinators. After the enumerator is returned by simpleIterateeWebSocket, the framework connects the enumerator to the client and the messages on it are consumed. The framework uses its own iteratee, in fact, to consume the messages and write them to the client.

Enumerator.imperative() creates a specialized enumerator called a PushEnumerator. This enumerator allows you to write messages through the enumerator by calling PushEnumerator.push(msg). Writing the message “wakes up” the iteratee on the other side of the enumerator and invokes its message handler. As I said, this iteratee is given by the framework and writes each message out to the client. This iteratee remains alive until you send a special close message. In our example, the server will never close the connection.

Note that you can’t invoke out.push("hello world") immediately after instantiating the enumerator. That’s because the enumerator hasn’t been connected to the client yet. push must be invoked after simpleIterateeWebSocket has returned and the framework has connected the enumerator to its own iteratee. In our example, push isn’t invoked until a message is received from the client.

Asynchrony Teaser

I’ve gone into a lot of detail and we haven’t even talked about Actors yet! Before I conclude Part I, let me show you an asynchronous version of this code (that still doesn’t use actors :-):

  import play.api.libs.concurrent.Akka
  import play.api.Play.current // needed by Akka.future

  def simpleAsyncWebSocket = WebSocket.async[String] {
    Akka.future {
      val out = Enumerator.imperative[String]()
      val in = Iteratee.foreach[String] {
        msg =>
          out.push(msg)
      }
      (in, out)
    }
  }

The code turns out to be identical to the ordinary version except we use WebSocket.async instead of WebSocket.using. And we wrap the block in an Akka.future. Akka.future simply runs the block in a separate thread. It returns a Promise[T] where T is the return type of the block. WebSocket.async indicates a WebSocket handler just like WebSocket.using except that it takes a block with a result of type Promise[(Iteratee, Enumerator)] instead of simply (Iteratee, Enumerator). This code acts the same as the first code, except that the function runs asynchronously and returns immediately. This is trivial for now, but it sets us up for Part II when we introduce actors into the mix.