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:

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
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.
Hi Jan, I asked a relating to return types using a snippet of your code. Hope you don’t mind. I just wanted to test that part out in the open, because I want to find a ‘best way’ and not worry about it again.
Also, I think your example is a great starting point for many projects. So, before adding too many features in future, it may be nice to create a ‘template’ branch that people can use to get going on their own projects. Then again, maybe you don’t intent to add too many bells and whistles.
Ah, one more question: Why are you using maven instead of sbt? One very helpful part for me with sbt is using sbt-idea or the eclipse plugins. In the context of your tutorial, it would have helped me to quickly run sbt-idea, open the project in IntelliJ and follow along as you did your tutorial. As it was, I followed along using my file browser (Nautilus).
Anyways, great tutorial. I’ll stop bugging you now
Cheers
Hi Jan, I asked a relating to return types using a snippet of your code. Hope you don’t mind. I just wanted to test that part out in the open, because I want to find a ‘best way’ and not worry about it again.
Also, I think your example is a great starting point for many projects. So, before adding too many features in future, it may be nice to create a ‘template’ branch that people can use to get going on their own projects. Then again, maybe you don’t intent to add too many bells and whistles.
Ah, one more question: Why are you using maven instead of sbt? One very helpful part for me with sbt is using sbt-idea or the eclipse plugins. In the context of your tutorial, it would have helped me to quickly run sbt-idea, open the project in IntelliJ and follow along as you did your tutorial. As it was, I followed along using my file browser (Nautilus).
Anyways, great tutorial. I’ll stop bugging you now
Cheers
Aaaaagh typo! How do I delete or edit a comment on your blong?
Not at all–I’ll see what I can do with the SO question
Comments are forever
–I think you can edit it, though.
Hi – thanks for the tutorial. Is it possible that you can make your code available?
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.
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.