Search icon
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletters
Free Learning
Arrow right icon
Mastering play framework for scala

You're reading from  Mastering play framework for scala

Product type Book
Published in May 2015
Publisher
ISBN-13 9781783983803
Pages 274 pages
Edition 1st Edition
Languages
Author (1):
Shiti Saxena Shiti Saxena
Profile icon Shiti Saxena

Table of Contents (21) Chapters

Mastering Play Framework for Scala
Credits
About the Author
Acknowledgments
About the Reviewers
www.PacktPub.com
Preface
1. Getting Started with Play 2. Defining Actions 3. Building Routes 4. Exploring Views 5. Working with Data 6. Reactive Data Streams 7. Playing with Globals 8. WebSockets and Actors 9. Testing 10. Debugging and Logging 11. Web Services and Authentication 12. Play in Production 13. Writing Play Plugins Index

Chapter 8. WebSockets and Actors

In this chapter, we will cover the following topics:

  • Introduction to WebSockets

  • Actor Model and Akka Actors

  • WebSockets in Play: using Iteratees and Actors

  • FrameFormatters

An introduction to WebSockets


Picture this:

A moviegoer is trying to purchase movie tickets online. He or she has selected the seats, entered the payment details, and submitted. He or she gets an error message saying that the tickets they tried to book have sold out.

Consider an application, which gives detailed information about the stock market and allows purchasing/selling stocks. When someone enters payment details and submits these details, they get an error saying that the purchase has been rejected as the price of the stock has now changed.

Initially, in applications where real-time data was required over HTTP, developers realized that they needed bidirectional communication between the client side and server side. It was generally implemented using one of the following approaches:

  • Polling: Requests are sent from the client side at fixed and regular intervals. The server responds within a short span (less than 1 second or so) with a result for each request made.

  • Long-polling: When a...

WebSockets in Play


WebSockets cannot be defined using Action since they should be bidirectional. Play provides a helper to assist with WebSockets, which is documented at https://www.playframework.com/documentation/2.3.x/api/scala/index.html#play.api.mvc.WebSocket$.

Note

WebSockets, which are defined using the helper, use the Play server's underlying TCP port.

WebSockets can be defined similarly to Actions in Play applications. Starting from Play 2.3, a WebSocket helper finds a method to define WebSocket interactions using an Actor. However, before we learn more about the methods provided by the helper, let's take a small detour and get a little familiar with the Actor Model and Akka Actors.

Actor Model


Concurrency in programming can be achieved by using Threads which may include the risk of a lost update or a deadlock. The Actor Model facilitates concurrency by utilizing asynchronous communication.

According to the Actor Model, an actor is the fundamental unit of computation. It cannot exist independently, that is, it is always part of a specific actor system. An actor can send messages to one or more actors within its actor system if it knows the address of the other actor. It can also send messages to itself. The order in which the messages are sent or received cannot be guaranteed since the communication is asynchronous.

When an actor receives a message, it can do the following:

  • Forward it to another actor whose address is known to it

  • Create more actors

  • Designate the action it will take for the next message

Note

The Actor Model was first described in August 1973 in a publication by Carl Hewitt, Peter Bishop and Richard Steiger in the paper A Universal Modular ACTOR Formalism for...

Introducing Akka Actors


Akka is a part of the Typesafe Reactive Platform, which is similar to the Play Framework. According to their website:

Akka is a toolkit and runtime used to build highly concurrent, distributed, and fault-tolerant event-driven applications on the JVM.

Akka implements a version of the Actor Model, which is commonly called Akka Actors and is available for both Java and Scala. According to the Akka documentation, Actors give you:

  • Simple and high-level abstractions for concurrency and parallelism

  • Asynchronous, nonblocking, and highly performant event-driven programming model

  • Very lightweight event-driven processes (several million actors per GB of heap memory)

Akka Actors are available as a library and can be used within a project by adding them into the dependencies:

libraryDependencies ++= Seq(
  "com.typesafe.akka" %% "akka-actor" % "2.3.4"
)

Note

Adding a dependency in Akka explicitly is not required in a Play project as Play uses Akka internally.

We can then define an actor...

WebSocket using Iteratee


Let's define a WebSocket connection, which accepts strings and sends back the reverse of a string using Iteratee:

 def websocketBroadcast = WebSocket.using[String] {
    request =>
      val (out, channel) = Concurrent.broadcast[String]
      val in = Iteratee.foreach[String] {
        word => channel.push(word.reverse)
      }
      (in, out)
  }

The WebSocket.using method creates a WebSocket of a specific type using an Iteratee (inbound channel) and its corresponding enumerator (outbound channel). In the preceding code snippet, we return a tuple of the Iteratee in and the Enumerator out.

The Concurrent object is also a helper, which provides utilities to use Iteratees, Enumerators, and Enumeratees concurrently. The broadcast[E] method creates an Enumerator and a channel and returns a (Enumerator[E], Channel[E]) tuple. The Enumerator and channel, thus obtained, can be used to broadcast data to multiple Iteratees.

After this, we need to bind it to a path in the...

WebSocket using Actors without Iteratees


The Play WebSocket API allows the use of Actors to define the behavior. Let's build the WebSocket application that replies with the reverse of a given String once it's connected. We can do this by slightly modifying our Reverser Actor to have an argument as the reference of the Actor to which it can/must send messages, as shown here:

class Reverser(outChannel: ActorRef) extends Actor {

    def receive = {
      case s: String => outChannel ! s.reverse
    }
  }

object Reverser {
  def props(outChannel: ActorRef) = Props(classOf[Reverser], outChannel)
}

The websocket can then be defined in a controller as follows:

def websocket = WebSocket.acceptWithActor[String, String] {
  request => out =>
    Reverser.props(out)
}

Finally, we make an entry in the routes file:

GET        /wsActor                  controllers.Application.websocket

We can now send messages through the WebSocket when the application is running using a browser plugin.

Now, lets...

Closing a WebSocket


When the WebSocket is closed, Play automatically stops the actor bound to it. This binding works in two ways: the WebSocket connection is closed when the underlying actor is killed. If there is a need to free any resources once the connection is closed, we can do so by overriding the actor's postStop method. In our example, we have initialized a DBActor within WebSocketChannel. We will need to ensure that it's killed once the WebSocket is closed, since each connection to the WebSocket will lead to the initialization of a DBActor. We can do so by sending it a poison pill, as shown here:

override def postStop() = {
  backend ! PoisonPill
}

Using FrameFormatter

Suppose that an incoming JSON has the same fields for every request, instead of parsing it every time; we can define an equivalent class in this way:

case class WebsocketRequest(reqType:String, message:String)

Now, we can define our WebSocket to translate the JSON message to a WebSocketRequest automatically. This is possible...

Troubleshooting


  • What is the equivalent of interrupting Actions in GlobalSettings for WebSockets? What if we want to refuse a WebSocket connection when certain headers are missing? Something similar to the following code snippet didn't work as expected:

    override def onRouteRequest(request: RequestHeader): Option[Handler] = {
        if(request.path.startsWith("/ws")){
          Option(controllers.Default.error)
        } else
          super.onRouteRequest(request)
      }

    Interrupting WebSocket from the global object does not work as it does for Actions. However, there are other means of doing so: by using the tryAccept and tryAcceptWithActor methods. A WebSocket definition can be replaced by the following code:

    def wsWithHeader = WebSocket.tryAccept[String] {
        rh =>
          Future.successful(rh.headers.get("token") match {
            case Some(x) =>
              var channel: Concurrent.Channel[String] = null
              val out = Concurrent.unicast[String] {
                ch =>
                  channel = ch
       ...

Summary


We have learned a couple of things in this chapter. This chapter briefly covered the Actor Model and usage of Akka Actors in an application. In addition to this, we defined a WebSocket connection in a Play application with various constraints and requirements using two different approaches: the first one where we use Iteratees and Enumerators, and the second where we use Akka Actors.

In the next chapter, we will see the different ways in which we can test a Play application using Specs2 and ScalaTest.

lock icon The rest of the chapter is locked
You have been reading a chapter from
Mastering play framework for scala
Published in: May 2015 Publisher: ISBN-13: 9781783983803
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime}