API first REST in Akka and Spray

Another update to https://github.com/janm399/akka-patterns shows how to build and test REST application in Akka and Spray using API first approach, where we begin by defining the API and writing tests that check the API and then, independently, implement the rest of the system; finally swapping out the mock API for the real implementation and re-running the tests.

The most interesting points include the API tests (in Specs2, naturally!):

class CustomerServiceSpec extends DefaultApiSpecification {
  implicit val service = rootService

  "Getting a known customer works" in {
    val customer = perform[Customer](GET, 
                    "/customers/00000000-0000-0000-0000-000000000000")

    customer must_== janMachacek
  }

  "Finding all customers works" in {
    val customers = perform[List[Customer]](GET, "/customers")

    customers must contain (janMachacek)
  }

  "Saving a customer gets the saved one" in {
    val customer = perform[Customer](POST, "/customers", 
                     jsonContent("/org/.../customers-post.json"))

    customer must_== joeBloggs
  }

}

The DefaultApiSpecification mixes in the functionality of the Core and Api traits, together with SpecConfiguration, Specification and a few others to allow us to simply write perform[A](...): A.

Looking into the guts of the application, it is an absolute joy to be able to use typeclasses for persistence with Casbah to persist our instances in MongoDB:

case class Get(id: UUID)
case class FindAll()
case class Insert(customer: Customer)

class CustomerActor extends Actor 
  with Configured with TypedCasbah with SearchExpressions {

  def customers = configured[MongoDB].apply("customers")

  protected def receive = {
    case Get(id) =>
      sender ! customers.findOne(entityId(id)).map(mapper[Customer])

    case FindAll() =>
      sender ! customers.find().map(mapper[Customer]).toList

    case Insert(customer) =>
      customers += serialize(customer)
      sender ! customer
  }
}

Before you say anything about trivial values to persist, the Customer case class is defined as

case class Customer(firstName: String, lastName: String,
                    email: String, addresses: Seq[Address],
                    id: UUID)

case class Address(line1: String, line2: String, line3: String)

But enough dry text, here’s a video of how I put the whole thing together:

This entry was posted in Jan's Blog and tagged , , , , , , , , . Bookmark the permalink.

10 Responses to API first REST in Akka and Spray

  1. Jacobus says:

    Great example and tutorial – really refreshing and informative! Thanks Jan!

    Can’t wait for the next update!

    Out of interest, why are you using the Lift JSON library and not the Spray Json library?

    Cheers

  2. Jan Machacek says:

    Thanks–the next instalment will show Grails client application and regarding the endpoints and the structure of the code. I’ll try to get that done over the weekend.

    As for the Lift JSON, it is my historical baggage with Spray 1.0 Mx; ever since then, I stuck with Lift. Thanks for the nudge, I’ll take a look at Spray JSON again.

  3. Jacobus says:

    Aaaaagh typo! How do I delete or edit a comment on your blong?

  4. Jan Machacek says:

    Not at all–I’ll see what I can do with the SO question :)

  5. Jan Machacek says:

    Comments are forever :) –I think you can edit it, though.

  6. Hi – thanks for the tutorial. Is it possible that you can make your code available?

  7. Jan Machacek says:

    Most of the code is at https://github.com/janm399/akka-patterns, but it needs updating. I plan to migrate most of the code in that project to show all the latest code in the next two weeks.

  8. Thanks – I look forward to any updates. I spent time with the SBT version of your code, which is very different than the Maven version. I suspect that you spent more time on Maven (since that is the version in your video demo). I will post all of the dependencies + code changes that I made to make this work as soon as it runs for me.

    This is a very important project for people who are looking for an in-depth reference example of spray + akka + a data store.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>