Akka HTTP Pokemon
In this tutorial, we are going to explore how to use Akka HTTP to create a very simple Scala based REST services for our Pokemon game.
Prerequisite
This tutorial assumes some working knowledge of Scala and Akka.
What is Akka HTTP
It is an Akka based HTTP library for building RESTful services in scala. It’s is not framework, it’s part of the Akka libraries. We are going to use it to expose our Actors to the web via HTTP.
Let’s get started. First, we need to add the right libraries to our project. Here is the sbt build file.
resolvers += Resolver.jcenterRepo
libraryDependencies ++= {
val akkaV = “2.4.7”
val sprayJsonV = “1.3.2”
Seq(
“com.typesafe.akka” %% “akka-http-core” % akkaV,
“com.typesafe.akka” %% “akka-http-experimental” % akkaV,
“com.typesafe.akka” %% “akka-http-spray-json-experimental” % akkaV,
“io.spray” %% “spray-json” % sprayJsonV
)
}
Looking at the dependencies we added, we have
- akka-http-core-experimental: As our http server and requires akka-stream which we included also in our class path.
Code structure
Normally we divide our RESTful API to two following pieces
- PokemonService – Defines the route for the rest service.
- PokemonServer – Defines and creates the Http server to run our
This approach of separating concerns of the API allows us to decouple the system in which the rest service actually runs.
Pokemon REST service
trait PokemonService {
implicit val system: ActorSystem
implicit val materializer: ActorMaterializer
val list = new ConcurrentLinkedDeque[Pokemon]()
import ServiceJsonProtocol.pokemonProtocol
val route =
path(“pokemons”) {
post {
entity(as[Pokemon]) {
pokemon =>
complete {
list.add(pokemon)
s”Caught pokemon ${pokemon.name}!!!”
}
}
} ~
get {
complete {
list.asScala
}
}
}
}
The above code defines a trait called PokemonService and observe, in PokemonService, we have:
- system – ActorSystem on which this service runs
- materializer – Flow materializer which we’ll explain shortly
Both values are implicits it allows us to use Scala dependency injection to inject these externally once we instantiate our service.
ActorFlowMaterilizer
Akka HTTP uses akka reactive streams for stream processing. So in a reactive system, we have to specify the flow materializer that handles how the requests and response flow get processed.
In akka-http, actors will be used for handling request and response flows. That’s why in our Pokemon example we have define an ActorMaterializer
implicit val materializer:ActorMaterializer
The route
Route specifies the URI endpoints REST server exposing. It is combination of multiple paths. A simple path will have the following three parts:
- Directive/URI
- HTTP Method
- Response
In our Pokemon service, we’ve defined our route as follows:
val route =
path(“pokemons”) {
post {
entity(as[Pokemon]) {
pokemon =>
complete {
list.add(pokemon)
s”Caught pokemon ${pokemon.name}!!!”
}
}
} ~
get {
complete {
list.asScala
}
}
}
}
Once the REST service is ready, we can now define a REST server, which we’ll serve this service.
class PokemonServer(implicit val system: ActorSystem, implicit val materializer: ActorMaterializer) extends PokemonService {
def startServer(address: String, port: Int) = {
Http().bindAndHandle(route, address, port)
}
}
object PokemonServer {
def main(args: Array[String]) {
implicit val actorSystem = ActorSystem(“pokemon-server”)
implicit val materializer = ActorMaterializer()
val server = new PokemonServer()
server.startServer(“localhost”, 8080)
}
}
Basically, we created an Http server running on port 8080 which will handle all connections to the PokemonService
Consuming Pokemon Service
Now, the exciting part, let’s see how we consume our shining Pokemon service – hopefully, we get one million downloads too.
To add our newly caught Pokemon, do a POST to the /pokemons endpoint
curl -H “Content-Type: application/json” -X POST -d ‘{“name”: “monster”}’ http://localhost:8080/pokemons
Caught pokemon monster!!!
And to see all our Pokemons, do a GET the /pokemons endpoint
curl -H “Content-Type: application/json” http://localhost:8080/pokemons
[{
“name”: “monster”
}, {
“name”: “Zooo”
}]
Conclusion
Note, we’ve barely scratched the surface but this should give you some ideas of what Akka HTTP is and the next tutorial will go deeper to show you more powerful features.
You can download the complete sample code