In my previous blog post I introduced the new Akka I/O and already kind of demonstrated that you can use it – in combination with spray – to build HTTP servers with Akka. This post is the first in a series which build on these core concepts and dive into the domain of modern and reactive web applications: We’ll create Gabbler, a simple push-enabled chat application using the latest and greatest tools like Scala, Akka, spray and AngularJS.
Setting up the project
As usual, we are going to use the amazing sbt build tool. I have heard rumors that some don’t like it, but anyway, here’s some interesting stuff from our
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
As you can see, we are still on the latest released version
2.10.2 of Scala, although I’d love to go for Scala
2.11 milestone whatsoever. But we all know that it can be a little tricky to find our library dependencies published against these latest development versions. As in my previous post we are using Akka
2.2 and spray
The user interface
Don’t expect anything fancy or stylish here! I’m not a web designer and never will be. Luckily there’s Twitter Bootstrap which prevents me from creating a complete mess. Enough talk, here’s the Gabbler UI:
As you can see, we are using the Bootstrap starter template. We add two columns: the left contains a textarea for new messages and a button to send them off, the right hosts the list of received messages.
It shouldn’t be too hard to imagine how a push-enabled chat application is working, but just to be on the safe side, here is a very short video, showing the Gabbler UI in action:
Not shown in the video, we have to logon first. For sake of simplicity we can use any username-password combination with equal username and password. Then we can send messages which are pushed to all connected clients.
The AngularJS client
Let’s first take a look at the view portion of the client, which is a single HTML 5 page:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
As you can see, this is a completely logic-free HTML 5 page which can be opened in any browser. All interactivity comes through AngularJS
data-ng- directives, which usually show up as attributes of HTML elements, and AngularJS expressions, embedded in
The controller part of the client, which gets connected to the view through the
data-ng-controller directive of the
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
GabblerCtrl defines the
$scope.getMessages function that queries the server for messages asynchronously and adds any new messages sent from the server to the
messages array. Notice that the callback for the query calls
$scope.getMessages again, hence the client is polling the server. We don’t use WebSocket here by purpose, because it will be illustrative to use Akka actors to implement long polling in a very elegant fashion on the server side. The controller also defines the
$scope.sendMessage function which sends a new message to the server and reinitializes – i.e. empties – the local message which is stored in the
The model part of the client is made up from the
$scope.messages array and the
$scope.message object, which are synchronized with the view through AngularJS’s two-way data binding. Therefore the view gets updated anytime new messages are sent from the server, resulting in new entries in the list of messages in the right column. Also, when the user clicks the “Gabble away” button, reinitializing the
$scope.message variable leads to blanking out the textarea for new messages in the left column.
The server skeleton
With the client in place, let’s start looking at the RESTful HTTP server. In this post we just cover a server skeleton with incomplete implementations for accetping GET and POST requests.
In my previous post I have shown how to build a HTTP server with Akka I/O and spray-can. This time we add another spray module – spray-routing – which provides a high-level, very flexible routing DSL for elegantly defining RESTful web services.
First we have to create an application:
1 2 3 4 5 6 7 8 9 10
As usual we create an
ActorSystem and shut it down at the end, after hitting “ENTER”, which is a feature we probably don’t want to add to a mission critical high-available production system. We also get some configuration settings from the
GabblerSettings Akka extension which we use to create the
GabblerService top-level actor:
1 2 3 4 5 6 7 8 9
As you can see,
HttpServiceActor from spray-routing which makes the routing DSL available. When the
GabblerService actor is created, we send a
Http.Bind message to the I/O manager for HTTP to register itself as listener for HTTP connections.
Other than in my previous post we don’t handle the various HTTP messages natively, but instead use the routing DSL to define the actor’s behavior. The core concepts of the routing DSL are routes and directives.
Routes, which are simply functions of type
RequestContext => Unit and can be nested or composed, are used to either complete a request or recejct or ignore it. Here is a very simple route that completes a request:
Directives are small building blocks for arbitrarily complex routes which can have inner routes, transform or filter the incoming
RequestContext or extract values form it. spray-routing already provides many useful directives, e.g. for completing a request, matching against the HTTP verb or extracting path elements:
1 2 3 4 5 6 7 8 9 10 11 12
Using this routing DSL we define the behavior of the
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
As you can see we define the
receive method in terms of the
runRoute method which gets a route composed of
Let’s first look at the pretty straightforward
staticRoute, which is a composite of two simple routes. The first is made up from the
path direcitve matching the empty path and the
getFromResource directive which completes a GET request with the given resource, which is
web/index.html in our case. The second route is constructed with the
getFromResourceDirectory direcitve and completes all GET requests with resources from the
web directory. Essentially,
Now let’s take a look at
apiRoute. It extracts the authenticated user and then matches requests with path
api/messages. Within that, GET and POST requests are accepted.
We use basic authentication with a simple scheme: We accept any username-password combination with equal username and password:
1 2 3 4 5 6 7 8 9 10 11
On receiving a GET request we simply log that the authenticated user is asking for messages. Notice that we dont’ complete the request here in order to support long polling, which will be introduced in the next post.
On receiving a POST request we extract the body into an instance of the
Message case class by using the
entity directive. This is supported by spray-json integration with the following
1 2 3 4 5
As you can see, marshalling and unmarshalling of case classes with spray is a breeze.
entity directive we complete the request with status code
204 “No Content” after logging that the authenticated user has posted a message. Again, we save an essential aspect – sending the message to all connected users – for the next post.
We have introduced Gabbler, a modern and reactive push-enabled chat application. Actually we have only shown Gabbler’s client portion, built with AngularJS and a server skeleton built with Scala, Akka I/O and spray. In the next posts we will complete the server step by step towards a fully functional solution.
The complete source code is available on GitHub, the current state under the tag