Akka

How to get an ActorContext from Akka testKit

Posted on by  
Tammo Sminia

In Akka Typed we need an ActorContext to create new actors.

This poses some problems if we want to create an actor inside a class that’s not an actor. We can pass around an ActorContext from a (higher level) actor. But if this is a longer-lived class, we have to keep in mind that this ActorContext is only valid during construction. So it’s generally frowned upon to pass around the ActorContext.

Continue reading →

Throttling in Akka and Spray

Posted on by  
Tammo Sminia

When you want to limit the amount of messages an actor gets, you can use the throttler in akka-contrib. This will let you limit the max transactions per second(tps). It will queue up the surplus. Here I'll describe another way. I'll reject all the surplus messages. This has the advantage that the requester knows it's sending too much and can act on that. Both methods have their advantages. And both have limits, since they still require resources to queue or reject the messages. In Akka we can create an Actor that sends messages through to the target actor, or rejects them when it exceeds the specified tps.

object ThrottleActor {
  object OneSecondLater
  object Accepted
  object ExceededMaxTps
}
import ThrottleActor._

class ThrottleActor (target: ActorRef, maxTps: Int) extends Actor with ActorLogging {
  implicit val executionContext: ExecutionContext = context.dispatcher
  context.system.scheduler.schedule(1.second, 1.second, self, OneSecondLater)

  var messagesThisSecond: Int = 0

  def receive = {
    case OneSecondLater =>
      log.info(s"OneSecondLater ${DateTime.now} $messagesThisSecond requests.")
      messagesThisSecond = 0
    case message if messagesThisSecond >= maxTps =>
      sender ! ExceededMaxTps
      messagesThisSecond += 1
      log.info(s"ExceededMaxTps ${DateTime.now} $messagesThisSecond requests.")
    case message =>
      sender ! Accepted
      target ! message
      messagesThisSecond += 1
  }
}

Continue reading →

JSON parsing in Scala

Posted on by  
Tammo Sminia

We can use the Spray JSON parser for uses other than a REST API. We add spray-json to our dependencies. Our build.gradle:

apply plugin: 'scala'
version = '1.0'
repositories {
    mavenCentral()
}
dependencies {
    compile group: 'io.spray', name: 'spray-json_2.11', version: '1.3.1'
}

Continue reading →

Building a REST client with Spray

Posted on by  
Tammo Sminia

In a previous blog I wrote how to make an API. See here.
Now we'll make a client to use that API. This can be done with spray-client. First we add dependencies for spray-client and spray-json:

apply plugin: 'scala'

version = '1.0'

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'org.scala-lang', name: 'scala-library', version: '2.11.6'
    compile group: 'com.typesafe.akka', name: 'akka-actor_2.11', version: '2.3.9'
    compile group: 'com.typesafe.akka', name: 'akka-remote_2.11', version: '2.3.9'
    testCompile group: 'org.scalatest', name: 'scalatest_2.11', version: '2.2.4'
    compile group: 'io.spray', name: 'spray-http_2.11', version: '1.3.3'
    compile group: 'io.spray', name: 'spray-httpx_2.11', version: '1.3.3'
    compile group: 'io.spray', name: 'spray-json_2.11', version: '1.3.1'
    compile group: 'io.spray', name: 'spray-client_2.11', version: '1.3.3'
}

Continue reading →

Alternating between Spray-servlet and Spray-can

Posted on by  
Tammo Sminia

On a server you may want to deploy your application as a war. How to build a war with spray-servlet Locally it's easiest to run without an application server. We include both the spray-servlet and spray-can dependencies:

name := "sprayApiExample"

version := "1.0"

scalaVersion := "2.11.6"

libraryDependencies ++= {
  val akkaV = "2.3.9"
  val sprayV = "1.3.3"
  Seq(
    "io.spray"            %%  "spray-can"     % sprayV,
    "io.spray"            %%  "spray-servlet" % sprayV,
    "io.spray"            %%  "spray-routing" % sprayV,
    "io.spray"            %%  "spray-json"    % "1.3.1", //has not been updated yet
    "com.typesafe.akka"   %%  "akka-actor"    % akkaV
  )
}

//This adds tomcat dependencies, you can also use jetty()
tomcat()

Continue reading →

Building a war with spray-servlet

Posted on by  
Tammo Sminia

We will use spray-servlet to build a war file of our API. So we can run it in a java app server. I assume we already have a working REST API. We will need a web.xml, under src/main/webapp/WEB-INF/:

 spray.servlet.Initializer 

    SprayConnectorServlet
        spray.servlet.Servlet30ConnectorServlet
        true 

    SprayConnectorServlet
        /* 

Continue reading →

Building a rest API with spray

Posted on by  
Tammo Sminia

Building a rest API with akka and spray is easy. This is how I did it: SprayApiApp:

import akka.actor.{ActorSystem, Props}
import akka.io.IO
import akka.pattern.ask
import akka.util.Timeout
import spray.can.Http
import scala.concurrent.duration._

object SprayApiApp extends App {
  //we need an ActorSystem to host our application in
  implicit val system = ActorSystem("SprayApiApp")

  //create apiActor
  val apiActor = system.actorOf(Props[ApiActor], "apiActor")

  //timeout needs to be set as an implicit val for the ask method (?)
  implicit val timeout = Timeout(5.seconds)

  //start a new HTTP server on port 8080 with apiActor as the handler
  IO(Http) ? Http.Bind(apiActor, interface = "localhost", port = 8080)
}

ApiActor:

import akka.actor.{ActorLogging, Actor}
import spray.http.MediaTypes
import spray.httpx.SprayJsonSupport._
import spray.json.DefaultJsonProtocol
import spray.routing._

object RobotProtocol extends DefaultJsonProtocol {
  //Our domain class
  case class Robot(name: String)

  //We use the default json marshalling for Robot.
  //There are multiple jsonFormat methods in DefaultJsonProtocol. Depending on how many parameters the model class has.
  //Robot has just one, so we use jsonFormat1
  implicit val RobotFormat = jsonFormat1(Robot)
}
import RobotProtocol._

class ApiActor extends Actor with HttpService with ActorLogging {
  //A list of our domain objects
  var robots = List(Robot("R2D2"), Robot("Asimo"))

  //The HttpService trait defines only one abstract member, which
  //connects the services environment to the enclosing actor or test
  def actorRefFactory = context

  //This actor only runs our route, but you could add
  //other things here, like request stream processing or timeout handling
  def receive = runRoute(apiRoute)

  //Notice that both path methods return a Route. We need to chain them together with ~
  val apiRoute: Route =
    path("robots") {
      get { //with get we will return our current list of robots
        log.info("Building get route")
        complete {
          log.info("Executing get route")
          //complete will return the result in an appropriate format
          //With SprayJsonSupport it knows how to marshall a List to json
          //With RobotFormat it knows how to marshall Robot
          robots
        }
      } ~ post { //With post we will add a robot
        log.info("Building post route")
        handleWith { robot: Robot =>  //handleWith will unmarshall the input
          log.info("Executing post route")
          robots = robot :: robots
          robot //handleWith will also marshall the result. Here we simply return the new robot.
        }
      }
    } ~ path("") { //When we go to localhost:8080/ just show a link to localhost:8080/robots
      respondWithMediaType(MediaTypes.`text/html`) { //XML is marshalled to `text/xml` by default, so we simply override here
        complete {
          [The list of robots](/robots)
        }
      }
    }
}

Continue reading →

Akka and scalatest in gradle

Posted on by  
Tammo Sminia

When you start using Scala, it's tempting to also start using sbt. You can also use your favorite build tool: Gradle. This is my default Gradle build file:

apply plugin: 'scala'

repositories {
  mavenCentral()
}

dependencies {
  compile group: 'org.scala-lang', name: 'scala-library', version: '2.11.5'
  compile group: 'com.typesafe.akka', name: 'akka-actor_2.11', version: '2.3.9'
  compile group: 'com.typesafe.akka', name: 'akka-remote_2.11', version: '2.3.9'
  testCompile group: 'org.scalatest', name: 'scalatest_2.11', version: '2.2.4'
}

//run the akka application
task run(type: JavaExec, dependsOn: classes) {
  //object to run. (The one that extends App)
  main = 'pi.Pi'
  classpath sourceSets.main.runtimeClasspath
  classpath configurations.runtime
}

//run scala tests. These are not automatically picked up by gradle,
//so we run them like this.
task spec(dependsOn: ['testClasses'], type: JavaExec) {
  main = 'org.scalatest.tools.Runner'
  args = ['-R', 'build/classes/test', '-o']
  classpath = sourceSets.test.runtimeClasspath
}

Continue reading →

shadow-left