spray is an open-source toolkit for building REST, HTTP-based integration layers on top of Scala and Akka.
Being asynchronous, actor-based, fast, lightweight, modular and testable it’s a great way to connect your Scala applications to the world.
So when Kingsley and I were deciding what frameworks to cover for our talk, we were unsure whether to include Spray or not. Spray seems to be on its way out; there’s currently no roadmap to upgrade spray to Scala 2.12 (https://twitter.com/oxbow_lakes/status/796311657203068928). However, Spray is widely used and teams are still continuing to use it, even on new services they’re building. I found it very interesting to take a first look at Spray and then move onto akka-http to be able to compare the differences. As I did with my first look at Play, I wrote an identical small REST application that can be found here, where all of the below examples can be found.
I’m going to start with this because this alone is a reason not to pick Spray up right now. As with all of my ‘first looks’, I googled things a lot. This page appeared a lot. This tells me that less people are asking/answering questions since the latest documentation which is a bad sign.
For me, I find Actors being baked in to the Spray framework more of an obstacle rather than a useful addition. It’s one of the first thing you have to write in order to set up a service and this isn’t particularly beginner-friendly; I was definitely intimated by this concept at first and believed I needed to learn all about Actors to use Spray. However, once you realise that this is just some boilerplate you need to cover to get started, you can more or less ignore Actors from there on (if your project isn’t using them).
I wasted a lot of time when writing the routes. Spray uses the magnet pattern and it can be quite complex when linking routes together; more so when trying to decipher where a particular route ends up.
I needed to thoroughly read through the docs whilst writing the routes for the first time, and not everything was very clear straight away. Specifically returning Json and Futures; something simple like not needing to explicitly state that you want to return something in Json took some time to debug.
Another annoyance was a problem that occurred when forgetting to write one of those little tilda’s between routes.
Firstly, I would expect a compilation error, but we don’t get that. We don’t even get an appropriate or clear runtime error. What we do get is very strange behaviour – the routes work for everything declared after the missing tilda and the routes before it just gets ignored.
If you noticed in the above picture of the routes, I’ve imported some implicits as close to where we need them as possible, but that’s not all, I have also imported them just above where I have declared myRoute. This was the only way I could get the implicits to play nice and I still have no idea why. I’m sure I’ve missed a trick here somewhere but my dislike for this still stands; it shouldn’t have to be this hard.
This felt like the most clumsy of all the framworks I used for our talk, between the odd behaviour of the implicits, the routes being hard to read at a glance and the awkward way we return Futures and Json. I will say that once I had jumped the hurdles and learnt the quirks, it was very fast and simple to add more routes and re-run the service. I also didn’t quite implement all of the little ‘extras’ I added in the play service (e.g. custom json marshallers) as I was planning on coming back to them once I had everything basic in place, however I doubt I will be going back to work on this service with Spray being on the way out.