Typesafe Activator

HTML 5 Device Orientation with play, ember and websockets

HTML 5 Device Orientation with play, ember and websockets

Michal Janousek, Martin Zapletal
July 9, 2014
scaladays2014 playframework emberjs scala websockets threejs

This template shows how simple it is to use latest technologies to build a nice modern reactive web application comprising of a Client-side JavaScript App built using EmberJS and WebSockets with WebGL ThreeJS, served from the Play 2 Framework written in Scala which works high velocity data from different sources using Play Iteratees and Akka.

How to get "HTML 5 Device Orientation with play, ember and websockets" on your computer

There are several ways to get this template.

Option 1: Choose reactive-orientation in the Typesafe Activator UI.

Already have Typesafe Activator (get it here)? Launch the UI then search for reactive-orientation in the list of templates.

Option 2: Download the reactive-orientation project as a zip archive

If you haven't installed Activator, you can get the code by downloading the template bundle for reactive-orientation.

  1. Download the Template Bundle for "HTML 5 Device Orientation with play, ember and websockets"
  2. Extract the downloaded zip file to your system
  3. The bundle includes a small bootstrap script that can start Activator. To start Typesafe Activator's UI:

    In your File Explorer, navigate into the directory that the template was extracted to, right-click on the file named "activator.bat", then select "Open", and if prompted with a warning, click to continue:

    Or from a command line:

     C:\Users\typesafe\reactive-orientation> activator ui 
    This will start Typesafe Activator and open this template in your browser.

Option 3: Create a reactive-orientation project from the command line

If you have Typesafe Activator, use its command line mode to create a new project from this template. Type activator new PROJECTNAME reactive-orientation on the command line.

Option 4: View the template source

The creator of this template maintains it at https://github.com/teroxik/reactive-orientation#master.

Option 5: Preview the tutorial below

We've included the text of this template's tutorial below, but it may work better if you view it inside Activator on your computer. Activator tutorials are often designed to be interactive.

Preview the tutorial


This template shows how simple it is to use latest technologies to build a nice modern reactive web application comprising of a Client-side JavaScript App built using EmberJS and WebSockets with WebGL ThreeJS, served from the Play 2 Framework written in Scala which works high velocity data from different sources using Play Iteratees and Akka. One of the main goals of this template is to show how such non-trivial application can be written very quickly, elegantly, readably and scalably with just a few lines of code using the Typesafe technologies and to describe and discuss the concepts, technologies, various alternatives that are provided to programmer to meet the goals, provide resources for further education and to help even beginners to start with or improve in using these technologies.

In the beginning it doesn't look very interesting. But we will get there.


Reactive applications are aiming to resolve the latest needs in software development. Even web is quickly moving towards the features of the Reactive Manifesto. The ability to react quickly to user’s interaction is becoming more and more important. This activator template illustrates how a real time communication can be simply, reliably and scalably built on the Typesafe platform. The template uses Play 2.3 and utilizes Iteratees as an useful abstraction to handle continuous streams of data in form of real time bidirectional websocket communication as well as Akka Actor web socket interface. Other technologies used are Scala, Play, Akka and Scalaz for server backend and Ember.js, HTML5 device orientation API, Bootstrap and Three.js for front end and visualisation as well as some other smaller tools that will be mentioned in the documentation.

Main functionality of the Play server is to act as a router for web socket messages. It accepts connections on two different web sockets. The first web socket receives messages with data about spatial orientation from an arbitrary number of mobile devices. Web sockets in combination with orientation data serve as a good descriptive source of data with reasonably high volume and velocity so we can show how these can be handled using the Typesafe platform. The server applies transformation function to each message and merges streams of messages from all devices into a single stream which is in turn sent to the other websocket where the data for each individual device are clearly displayed in real time. This is illustrated on the figure below.


Go to Run tab in Activator and start the application and then visit http://localhost:9000. Another option is to start the application from linux terminal using activator run command for Play 2.3. After the application startup, you will be presented by the Dashboard page and IP address of the machine in network. This is because you will need to connect to the Play server from other devices. In real life the application would be deployed in the internet so you would just need to enter the url. This case however requires you to enter the local network address, including port (default 9000) to your mobile device’s browser - for example When the page is loaded, select Device tab and click the Start button. If the device supports orientation sensor, it should start sending data to the server. The Dashboard page will show real time information including visualisation of the device’s orientation. Each device connected will be presented individually. After certain time of inactivity the device is removed from the Dashboard. Note the visualisation may not be exactly correct, because the alpha represents the angle to north so you may need to adjust your screen with Dashboard manually.

System overview - Server

Play controller

The main work of the application happens in Application.scala. This object is the only Play Controller in the whole application. It has three methods. The index method attempts to retrieve network interfaces to be able to present the IP address and then presents index.scala.html view. The most elegant way is to use play actor sockets (introduced in Play 2.3) for connections from mobile devices and Iteratees/Enumerator for dashboard sockets. You can read about both options in Play scala web sockets. The controller has one instance of Enumerator and one instance of Channel. Messages pushed to the Channel will be received by web sockets using the Enumerator. This is important to understand, because these will be shared by actors that will push messages to the Channel and device websockets who will use the Enumerator.

val (dataEnumerator, dataChannel) = Concurrent.broadcast[JsValue]

Method mobileWebSocket is triggered when a new web socket connection is started from the mobile device. When using actor sockets, Play automatically creates one actor for each connection on the web socket. This is a very convenient way to scale - because actors can run in parallel and have nicely distributed responsibility - having as much actors as devices won’t create a performance bottleneck or a single point of failure.

       def mobileWebSocket = WebSocket.acceptWithActor[OrientationChangeEvent, JsValue] { request => out =>
           Props(new StreamMergingActor(dataChannel))

Play automatically sends a message to the specified actor when a message on the web socket interface is received. The type of the message is specified by the first type parameter of acceptWithActor function.

It would be possible to achieve the same using Iteratees and Enumerators approach. The code would then look for example like this.

        def mobileWebSocket = WebSocket.using[OrientationChangeEvent] { request =>
          val in = Iteratee.foreach[OrientationChangeEvent] { mergingActorRouter ! _ }
          val out = Enumerator.empty[OrientationChangeEvent]

          (in, out)

In this case, we would however need to take care of the number of actors manually. One solution would be for example to create a Router that distributes incomming messages according to predefined logic. One option to create a router would be to add one actor to the routees with each connection or create a router with a fixed number of actors equal to number of cpu cores available on the machine.

        lazy val mergingActorRouter = Akka.system.actorOf(
        .props(Props(new StreamMergingActor(dataChannel))))

Method dashboardWebSocket manages web socket connections from dashboard page using Iteratee and Enumerator. Iteratee is a representation of incomming message stream and Enumerator of the outgoing. The code handling web sockets from dashboard using Iteratees and Enumerators may look like this.

        def dashboardWebSocket = WebSocket.using[JsValue] { request =>
          (Iteratee.ignore, dataEnumerator)

This solution is very elegant and minimal, because we again use Play to do the hard work. We just use the same channel for each incomming websocket connection. When a message is received from mobile device, the actor that is responsible for handling the message will simply push it to this channel and because it is shared by all Dashboard web sockets, they will automatically all receive the message. In addition, this abstraction very nicely illustrates the intended functionality - messages from multiple devices are merged into one stream! Notice also the Iteratee is ignored (because we are not expecting any messages from the dashboard apart from initial web socket connection). Again this is not the only option and it would be possible implement the same logic using Actor web sockets, but we would have to manually handle the fact that the response is not going to the same socket as the received message.

To summarize the above solution - one actor is created for each Device connection. All these actors push messages the same shared output channel which in turn is also shared by all Dashboard connections.

Scala’s ecosystem offers a variety of options to handle this use case. One notable alternative to Play would be for example Spray.

Akka actor

The application only uses one user defined actor located in StreamMergingActor.scala. StreamMergingActor’s role is to merge incomming streams from devices and send the resulting stream to dashboards using the share channel. Companion object StreamMergingActor defines messages which the actor understands. OrientationChangeEvent and OrientationChangeData represent one single message received from the mobile device. Each message contains deviceId, information about the device, assigned colour and three values - alpha, beta and gamma - which represent the orientation data and will be explained later. Most important fact is, that the actor holds one instance of Channel[JsValue] called dataChannel which is passed to him in constructor and messages pushed to this channel are sent to all dashboard web socket connections. When a single message from mobile device is received by Play, it is sent to this actor (as an instance of OrientationChangeEvent case class) and the actor simply pushes the message to this channel, thus merging all incoming streams into one as described earlier.

        case e: OrientationChangeEvent =>

The important fact is that all this is non-blocking. Play sends a message using “fire and forget” technique where it is simply telling the actor what needs to be done and does not wait for response (and if one would wait for a response from actor, it would be done in a non-blocking way by simply defining the expected message in receive function or by using Future as a representation of asynchronous computation as described in the documentation). The message is processed asynchronously to the sender by the actor, usually in different thread.


Html5 device orientation events create data about angles in degrees, but three.js library used for display requires data in radians. This gives us an opportunity to apply a transformation function to the data stream. Trait DegreesToRadiansConversions has one public method called convertDegreesToRadians which converts the angles in data property in OrientationChangeEvent from degrees to radians. Since case classes are immutable, the angle values can not be simply updated and we need to provide a whole new instance of OrientationChangeData. However data property in OrientationChangeEvent is also immutable so we need to provide a new instance of this class too. This is an implication of immutable data structures that may look like a disadvantage, but it actually is not and accompanies many advantages.

          OrientationChangeData(math.toRadians(event.data.alpha), math.toRadians(event.data.beta), math.toRadians(event.data.gamma))

This code is fine, but unnecessary. Updating properties in larger structures could become messy even when the logic would be extracted to a kind of factory class. That is why Scala provides copy method on case classes. It creates a new object based on values in the old one and the changes in the selected properties.

        event.copy(data =  OrientationChangeData(math.toRadians(event.data.alpha), math.toRadians(event.data.beta), math.toRadians(event.data.gamma)))

This template however uses another approach which utilizes Scalaz library and a concept called lenses known from functional programming. A lens is created by passing get and set functions. We can then use the lens to modify the value viewed through it. Scalaz is a library which provides purely functional data structures to complement those from the Scala standard library. Note that the template uses the same data structure for both radians and degrees which may not be the best practice, because the client does not know which value is stored in it. It is used for the opportunity to discuss copy and lenses concepts, but otherwise you may want to distinguish the cases for example by using types, generics or separate classes.

IpAddress trait

Trait IpAddress provides functionality to retrieve ip address. The most interesting thing here to note is how easily can Java functions be used in Scala. Java collections are transformed to Scala collections using asScala and therefore they can then be cleanly manipulated using Scala's collection transformations like map and flatMap. The trait also uses Validation from Scalaz to handle errors encountered during the address retrieval. In this case, it is used instead of try-catch block well known from most OO languages, because Validation makes error handling more explicit, readable and provides a nice api for composition of multiple errors. Other alternatives to consider for this purpose are Scala’s Try and Either.

        Validation.fromTryCatch( … )
Json marshalling

Json marshalling and unmarshalling operations to convert json messages on websocket to objects in Scala and back to json are also very clean in Play and Scala generally. Notice we don’t need to do any marshalling explicitly. The signatures of methods that are used to handle web socket connections.

        def acceptWithActor[In, Out](f: RequestHeader => HandlerProps)(implicit in: FrameFormatter[In], out: FrameFormatter[Out], app: Application, outMessageType: ClassTag[Out]): WebSocket[In, Out]

        def using[A](f: RequestHeader => (Iteratee[A, _], Enumerator[A]))(implicit frameFormatter: FrameFormatter[A]): WebSocket[A, A]

both require an implicit parameter called FrameFormatter. It is provided by importing object JsonFormats to scope and Scala compiler will inject the implicit parameter for us.

        import json.JsonFormats._

All the case classes we use to represent web socket messages can be marshalled and unmarshalled using the default formats.

        implicit val eventDataJsonFormat = Json.format[OrientationChangeData]

For more complicated cases, you can write your own format definition.

That is it for the Play server application! As you can see only a very little code is required to accomplish the required functionality. Most of the heavy lifting is already done by Akka and Play

System overview - Client

The client application runs in browser and is built on one of the major javascript MVC-like frameworks, Ember.js. It also uses Ember.js plugin to enable simple compilation of handlebars templates. All required javascripts all simply included as files in index.scala.html returned by the index method of previously discussed Application controller.

The main Ember application entry point is in app.js where Ember itself and routes are initialized. The whole application uses two controllers - indexController as default controller for Dashboard and deviceController for the Device tab.

Mobile device

The DeviceController has 3 important properties startOn flag saying if the data are being sent, socket which is the websocket object and orientation which represents current set of device’s orientation data. A handlebars template device.handlebars is used as a view for this controller. Important thing to note here is that Ember controller properties are accessible from the view and Ember automatically binds their state and updates the view when they are changed. Ember also provides set of standard tools for data access called Ember-data. For sake of simplicity of code and clarity of the intended functionality, the web socket interactions are handled manually in this template. The controllers subscribes to deviceorientation event which triggers every time you move your device. When this happens, the properties of the controller are updated (and therefore the values re-rendered in the view). Html5 provides this api to be able to use data from device's orientation sensors in a browser. It provides values alpha, beta and gamma which represent rotation through angle about axes. The specification can be found at www.w3.org. There are some differences between browsers, but method calculateEulerOrientationForDevice in orientation module handles that.

         var orientationData = Orientation.calculateEulerOrientationForDevice(event);

         var data = {
         deviceInfo: self.model.deviceInfo,
         deviceId: self.model.deviceId,
         colour: self.model.colour,
         data: orientationData

Screenshot from Nexus 7 tablet in portrait mode before starting the sending process.

Screenshot of device page sends data from table

Screenshot from Nexus 7 tablet in landscape mode showing the generated color and real-time orientation data.

Screenshot of device page with actual data.

We refer to the values by self, because they are properties of the controller to be simply displayed on the device page. Apart from orientationData, they are all static and only change when the page is reloaded. OrientationData on the other hand are calculated with each change of device’s orientation. Device info contains data about the device - model, type, vendor, os or browser and version etc which are retrieved using the ua-parser-js project. These informations are used to create unique deviceId and colour by adding a current timestamp and using an appropriate hash function to convert string to colour. These properties are then used to identify the device throughout the application. Uniqueness provided by this approach is sufficient for this template. After that, the data are sent to the Play server’s device web socket.


Other important parts of the controller are the init function which executes on initialization of the controller and methods in actions object which are used to control user actions in Ember. Notice one of two (Start or Stop) buttons displayed in device.handlebars view. Click on them executes start and stop action respectively.


The indexController is a bit more complicated, but still easily understandable. Important thing to note is that it extends ArrayController, which means it can contain array of models instead of just one or none. Content property is initialized to empty array. This array will include list of active devices. Index.handlebars view is a template for this route. The {{#each}} is used to render the whole array of models stored in controller and their selected properties. Each model also has an empty div called canvas where the orientation data will be visually displayed when available.

The main idea of this controller is to receive messages with data about orientation from all the connected devices and either add them to the content array (in case the device is not yet present)


or update their orientation values (if the device is already in the content array).

        device = Device.update(item, json);

Ember is able to bind and re-render relevant parts of the view even if just values of nested object properties in an array change. This provides sufficient performance for multiple displayed devices. An algorithmically simpler, but less performant solution would be to set the whole content array. We use device property of the message to uniquely identify each device. A timestamp is also saved in Device.update function to mark when were last data from each device received. Inactive devices are periodically scanned by removeUnusedDevicesTimer and removed from the array.

The majority of the work described above is done by handleWebSocketReceivedMessage function which is triggered with each received web socket message. The methods to create and update device object are extracted to Device module located in device.js file. Notice objects are created using Ember.Object.create() function which takes javascript object as parameter. Property values that are dynamically updated are updated using set method which ensures the values are bound and updated properly.

Graphical representation

An impressive javascript library three.js is used for graphical representation of the orientation data. This library aims to provide 3D graphics in a browser. Most of the functionality was extracted to orientation.js module. It contains functions to initialize the drawing canvas (createCanvas), create objects (createCube), transformations to achieve rotation around world axes (setObjectQuaternion) and extracting device’s orientation data (calculateEulerOrientationForDevice). The canvas is then attached to the DOM (the empty div in index.handlebars) mentioned earlier in indexController’s handleWebSocketReceivedMessage function.


Calls to Device.update() function then dynamically update the rotation of the displayed object by using Orientation.setObjectQuaternion() function.


The maing WebGL and Three.js objects are

  • renderer - renders the scene using camera
  • camera - defines the view of the scene
  • scene - all displayed objects must be added to scene

Render is using a render function to update the canvas with the latest changes.

       var render = function () {
          renderer.render(scene, createCamera());

We are using a simple cube/box object which is instantiated using the THREE.BoxGeometry class. But it is not enough for displaying it in the scene. We have to specify the object material. We chose one of the simplest materials to display boxes with only one colour. For our demo purpose is the box a very nice representation of mobile device (mobile,phone,tablet). The selected colour is passed to the material constructor and our object can be appended to the scene.

       var scene = new THREE.Scene();
       var renderer = new THREE.WebGLRenderer({alpha: true});
       renderer.setSize(600, 300);
       renderer.shadowMapEnabled = true;

       cube.receiveShadow = true;

       // add subtle blue ambient lighting
       var ambientLight = new THREE.AmbientLight(0x000044);

       // directional lighting
       var directionalLight = new THREE.DirectionalLight(0xffffff);
       directionalLight.position.set(1, 1, 1).normalize();

The 3d object is very nice but if we use only one color for all faces it doesn't look so good. The 3d objects becomes flat. Because of that we added 2 different lights to the scene with different colors and positions. It causes color changes on the faces which thank looks much more plastic. Unfortunately it slightly changes the resulting color so it is not so easy to identify the proper device.


In conclusion, notice what the template achieves. Play is not just a server providing resources on endpoints. It acts as a server and router for messages which can also apply transformations on them. It would also be possible to cooperate with other services and applications. All in a reactive way. Where else can Play and web sockets (or even different protocol) be used? How difficult would it be for example to create a 2d, isometric projection or even a 3d racing game using the Play server we already have? Wouldn’t it be achievable by just changing the javascript front end? Or a message queue? Or an enterprise service bus?


We know that tests are very important part of the application. This is only a demo with only small amount of code but still we included at least tests for the util package in the play backend. Because only with tests you can build applications which can satisfy the Reactive manifesto.


Can we do better? There is always space for improvements.

  • Update the Play plugin for EmberJS to support the latest versions of JQuery and Bootstrap.
  • Detection if the browser supports required technologies eg. Orientation API and WebGL.
  • Better handling of WebSockets to ensure reliable connection and auto-reconnects.
  • Notification if the server is up and running.
comments powered by Disqus