Akka

AkkaSupport

Akka is a toolkit and runtime for building highly concurrent, distributed, and fault tolerant event-driven applications on the JVM. Scalatra allows you to easily mix it into your application.

Dependencies

The following dependencies will be needed to make the sample application work.

"com.typesafe.akka" %% "akka-actor" % "2.5.3",
"net.databinder.dispatch" %% "dispatch-core" % "0.13.1",

Setting up your Scalatra app with Akka

When you’re using Akka, you’ll want to start your Actors and ActorSystem from inside the ScalatraBootstrap class. You can then pass those into the constructors of your servlets as necessary:

import _root_.akka.actor.{Props, ActorSystem}
import com.example.app._
import org.scalatra._
import javax.servlet.ServletContext


class ScalatraBootstrap extends LifeCycle {

  val system = ActorSystem()
  val myActor = system.actorOf(Props[MyActor])

  override def init(context: ServletContext) {
    context.mount(new PageRetriever(system), "/*")
    context.mount(new MyActorApp(system, myActor), "/actors/*")
  }

  override def destroy(context:ServletContext) {
    system.terminate()
  }
}

It’s also considered good form to shut the ActorSystem down when you’re done with it. Keep in mind that a servlet context destroy does not necessarily mean a full application shutdown, it might be a reload - so you’ll need to release the ActorSystem resources when your Scalatra application is destroyed.

Using Scala Futures

Scalatra’s FutureSupport trait provides a mechanism for adding Futures to your routes. At the point where you

The generic case looks like this (but it won’t compile):

import _root_.akka.dispatch._
import org.scalatra.FutureSupport

class MyAppServlet extends ScalatraServlet with FutureSupport {
  get("/"){
    new AsyncResult { val is =
      Future {
        // Add async logic here
        <html><body>Hello Akka</body></html>
      }
    }
  }
}

Async request example

See akka-examples for a minimal and standalone project containing the examples in this guide.

As a more concrete example, here’s how you’d make an asynchronous HTTP request from inside one of your actions, using the Dispatch http client and an Akka ActorSystem.

package com.example.app

import akka.actor.ActorSystem
import dispatch._
import org.scalatra._

import scala.concurrent.{ExecutionContext, Future, Promise}
import scala.util.{Failure, Success, Try}

class FutureController(system: ActorSystem) extends ScalatraServlet with FutureSupport {

  protected implicit def executor: ExecutionContext = system.dispatcher

  get("/") {
    new AsyncResult { val is =
      HttpClient.retrievePage()
    }
  }

}

object HttpClient {

  def retrievePage()(implicit ctx: ExecutionContext): Future[String] = {
    val prom = Promise[String]()
    dispatch.Http(url("http://slashdot.org/") OK as.String) onComplete {
      case Success(content) => prom.complete(Try(content))
      case Failure(exception) => println(exception)
    }
    prom.future
  }
}

AsyncResult isn’t strictly necessary. It’s a way to ensure that if you close your Future over mutable state (such as a request object or a var) that the state is captured at the point you hand off to the Future.

If you attempt to use mutable state inside your Future without AsyncResult (e.g. calling request.headers or something), you’ll get an exception. If you use AsyncResult, it’ll work. So, you’re trading a bit of boilerplate code for a bit of safety. If you can remember not to close over mutable state, don’t bother with AsyncResult.

Actor example

See akka-examples for a minimal and standalone project containing the examples in this guide.

When you use Scalatra with Akka, you most likely want to return a result of some sort. So you’re probably going to send a message to an Actor which will reply to you. The method you use for that returns a Future. Typically, this involves Akka’s ask pattern.

When the request you get just needs to trigger something on an Actor using the fire-and-forget [tell pattern](https://doc.akka.io/docs/akka/current/scala/actors.html#tell-fire-forget, then you don’t need a Future. In this case, you probably you want to reply with the Accepted status or something like it.

Here’s some example code:

package com.example.app

import akka.actor.{Actor, ActorRef, ActorSystem}
import akka.pattern.ask
import akka.util.Timeout
import org.scalatra.{Accepted, FutureSupport, ScalatraServlet}

import scala.concurrent.ExecutionContext
import scala.concurrent.duration._

class MyActorApp(system:ActorSystem, myActor:ActorRef) extends ScalatraServlet with FutureSupport {

  implicit val timeout = new Timeout(2 seconds)
  protected implicit def executor: ExecutionContext = system.dispatcher

  // You'll see the output from this in the browser.
  get("/ask") {
    myActor ? "Do stuff and give me an answer"
  }

  // You'll see the output from this in your terminal.
  get("/tell") {
    myActor ! "Hey, you know what?"
    Accepted()
  }

}

class MyActor extends Actor {
  def receive = {
    case "Do stuff and give me an answer" => sender ! "The answer is 42"
    case "Hey, you know what?" => println("Yeah I know... oh boy do I know")
  }

}

Once again, if we wanted to ensure that it was safe to close over mutable state, we could have used AsyncResult with out Actors.