Typesafe Activator

Google Glass Mirror API in Spray and Akka

Google Glass Mirror API in Spray and Akka

Jan Machacek
July 10, 2014
google-glass spray akka scala

Shows how to build a Spray and Akka-based application that deals with authentication, and then pushes notification to the Glass using the Mirror API.

How to get "Google Glass Mirror API in Spray and Akka" on your computer

There are several ways to get this template.

Option 1: Choose mirror in the Typesafe Activator UI.

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

Option 2: Download the mirror project as a zip archive

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

  1. Download the Template Bundle for "Google Glass Mirror API in Spray and Akka"
  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\mirror> activator ui 
    This will start Typesafe Activator and open this template in your browser.

Option 3: Create a mirror 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 mirror on the command line.

Option 4: View the template source

The creator of this template maintains it at https://github.com/eigengo/activator-mirror#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

Google Glass Mirror API

If you got your hands on the Google Glass, you are no doubt keen to try developing applications for it. The applications come in two major flavours: applications running on the Glass, and regular web applications using the Mirror API. In this post, I will show you how to use the Mirror API in a small Spray & Akka application. To focus on the essence, I will use the Google Client libraries, even though the are include blocking calls.

The goal

To demonstrate the Mirror APIs, we will build an application that allows users to insert messages to the Glass’s timeline. The application will prompt you to log in to your Google account if it does not have a valid OAuth2 authentication; once you log in and the application receives the OAuth2 credential, you can then type your message, click Insert Timeline, and the message will appear on your Glass.

The main components

The application is made up of the Spray REST server, and an AngularJS browser application. The REST server exposes only two endpoints:

  • GET /oauth2callback,
  • POST /timeline.

The /oauth2callback is the endpoint that deals with accepting the OAuth2 credential, and the /timeline endpoint inserts a message to the timeline on the Glass. The /timeline endpoint requires the Subject header to be present, and its value should be valid OAuth2 subject.

The AngularJS application only makes the REST calls to the /timeline endpoint.

The REST server

The REST server follows the usual pattern of spray-can applications. It starts the HTTP server and binds an actor that handles the incoming HTTP requests. Naturally, instead of dealing with the raw HTTP requests, we use spray-routing to express the endpoint behaviour in a convenient DSL. In Main, we have:

class Main(route: Route) extends HttpServiceActor {
  def receive: Receive = runRoute(route)
object Main extends App with RouteConcatenation {
  implicit val system = ActorSystem("Mirror")
  import system.dispatcher
  val service = system.actorOf(Props(new Main(...)))
  val io = IO(Http)
  io ! Http.Bind(service, interface = "", port = 8080)

In addition to implementing our two REST endpoints, we need to be able to serve the static content, namely the index.html, and js/mirror.js. So, we can split our endpoints into three services: the StaticService, AuthorisationService and the TimelineService.


The StaticService, as one expects, is the easiest to implement. It handles the GET requests by serving the content of a resource (a file on the classpath).

object StaticService extends Directives {
  def route(implicit arf: ActorRefFactory): Route = {


The /oauth2callback endpoint that this service exposes deals with getting and remembering the OAuth2 authenticaton that we will need for the /timeline endpoint. On a GET request to /oauth2callback, we check if we have the code request parameter. If so, we have received the OAuth2 response, and we’re ready to create the credential. If not, we need to compute a redirect URL, which will take the user to the Google login page. In AuthorisationService, all this looks a lot less scary.

object AuthorisationService extends Directives {
  def route: Route = {
    path("oauth2callback") {
      get {
        parameter('code) { code =>
          val flow = Authorisation.newAuthorizationCodeFlow()
          val tokenResponse = flow.newTokenRequest(code).
          val subject = tokenResponse.asInstanceOf[GoogleTokenResponse].
          flow.createAndStoreCredential(tokenResponse, subject)
        } ~ {
          val flow = Authorisation.newAuthorizationCodeFlow()
          val url = flow.newAuthorizationUrl().
          url.set("approval_prompt", "force")
          redirect(url.build(), StatusCodes.TemporaryRedirect)

The only thing that this listing is not showing is the Authorisation module, which handles the internals of the OAuth2 mechanism. To make our code easier, we are using the Google client APIs.

object ClientComponents {
  val transport = new NetHttpTransport()
  val jsonFactory = new JacksonFactory()
object Authorisation {
  import org.eigengo.mirror.ClientComponents._
  private final val GLASS_SCOPE: String =
    "https://www.googleapis.com/auth/glass.timeline " +
    "https://www.googleapis.com/auth/glass.location " +
  private final val (clientId, clientSecret) = {
    val config = ConfigFactory.parseFile(
      new File(System.getProperty("user.home"), ".google/mirror"))
    (config.getString("clientId"), config.getString("clientSecret"))
  private final val dataStoreFactory = new MemoryDataStoreFactory()
  def newAuthorizationCodeFlow(): AuthorizationCodeFlow = {
    new GoogleAuthorizationCodeFlow.Builder(transport, jsonFactory, 
        clientId, clientSecret, Collections.singleton(GLASS_SCOPE)).


To complete the picture, the TimelineService exposes the /timeline endpoint, which receives the text of the message to be sent out as the request body and the OAuth2 subject as the header parameter. It delegates the actual sending of the timeline item to the MirrorClientActor.

object TimelineService extends Directives {
  import Authentication._
  import akka.pattern.ask
  import Timeouts.internalTimeout
  def route(mirrorActor: ActorRef)(implicit ctx: ExecutionContext): Route = {
    path("timeline") {
      authenticate(validCredential) { credential =>
        post {
          handleWith { body: String =>
            val t = new TimelineItem()
            t.setNotification(new NotificationConfig().setLevel("DEFAULT"))
            (mirrorActor ? ((credential, t))).mapTo[String]

Apart from the authenticate(validCredential) call, this is again fairly standard Spray code! It turns out that the implementaton of validCredential is not too onerous, eihter, as the code in Authentication shows.

object Authentication {
  private val headerName = "Subject"
  def validCredential(implicit ec: ExecutionContext): ContextAuthenticator[Credential] = { ctx => {
      val header = ctx.request.headers.find(_.name == headerName).map(h => doAuth(h.value))
  private def doAuth(subject: String): Authentication[Credential] = {
      .map(Right(_)).getOrElse(Left(AuthenticationFailedRejection(AuthenticationFailedRejection.CredentialsRejected, Nil)))

In human-speak, we look up the Subject header, returning a rejection if it is missing. If we have a value, we attempt to find the matching Credential, again rejecting the request if the Credential for the given subject could not be found.

Wiring up

To wire everything up, we need to consider the order of the routes, leaving the StaticService.route last. The final version of Main is now simply:

class Main(route: Route) extends HttpServiceActor {
  def receive: Receive = runRoute(route)
object Main extends App with RouteConcatenation {
  implicit val system = ActorSystem("Mirror")
  import system.dispatcher
  val mirror = system.actorOf(Props[MirrorClientActor])
  val service = system.actorOf(Props(
    new Main(AuthorisationService.route ~ TimelineService.route(mirror) ~ StaticService.route)))
  val io = IO(Http)
  io ! Http.Bind(service, interface = "", port = 8080)

This leaves us with just the MirrorClientActor to implement! This actor will use the Mirror API and actually post the timeline items.


As we are using the Google Client APIs, the implementation of the actor is going to be rather trivial. (A non-blocking implementation will be slightly more involved, but this is good enough to as a proof of concept!) And so, on to the code.

class MirrorClientActor extends Actor {
  import org.eigengo.mirror.ClientComponents._
  def mirror(credential: Credential) = new Mirror.Builder(transport, jsonFactory, credential)
      .setApplicationName("Activator Mirror")
  def receive: Receive = {
    case (c: Credential, t: TimelineItem) =>
      sender ! mirror(c).timeline().insert(t).execute().getId

This is really all there is to it. When we receive the tuple containing the Credential and the TimelineItem, we simply call the Mirror API and insert the given TimelineItem!

The AngularJS app

To keep things simple, the Angular JS application’s UI and code also remains as short as possible. The only HTML file we have is index.html, which pulls in the AngularJS framework and our AngularJS application.

<!DOCTYPE html>
<html ng-app="mirror">
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.14/angular.min.js"></script>
    <script type="text/javascript" src="js/mirror.js"></script>
<div ng-controller="MirrorController">
        <input ng-model="timelineMessage"/>
        <button ng-click="insertTimeline()">Insert Timeline</button>

There is no fancy UI, all that the users can do is to type the message and submit it by clicking the button. The JavaScript side is also simple, though it needs to deal with the redirects and setting the HTTP header in the POST to the /timeline endpoint. The mirror.js is the last component.

angular.module('mirror', []);
    function($scope, $location, $http, $window) {
        $scope.subject = $location.search().subject;
        $scope.insertTimeline = function() {
            $http({method: 'POST', url: '/timeline', headers: { 'Subject': $scope.subject }, data: $scope.timelineMessage}).
                success(function(data, status, headers, config) {
                    // this callback will be called asynchronously
                    // when the response is available
                    alert('it worked!');
                error(function(data, status, headers, config) {
                    $window.location.href = '/oauth2callback';

Running the beast

Before you run the application, remember the code in Authorisation:

object Authorisation {
  private final val (clientId, clientSecret) = {
    val config = ConfigFactory.parseFile(new File(System.getProperty("user.home"), ".google/mirror"))
    (config.getString("clientId"), config.getString("clientSecret"))

You need to create the HOCON file in ~/.google/mirror, and it must contain the client id and client secret that you generated in the Google Developer Console. When you do create the OAuth Client ID, be sure to create it for a Web application, specifying http://localhost for authorised JavaScript origins, and http://localhost:8080/oauth2callback for the authorised redirect URI.

Now everything is truly ready to go. Run the application, and navigate to http://localhost:8080/index.html. When you first try to submit a timeline item, the application will redirect you to the Google login; on success, it will take you back to the home page, where you will be able to submit the item.

comments powered by Disqus