First Look: Scala Spray Framework

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.

– Support

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.

Spraydeadpages

– Actors

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 you’re project isn’t using them).

sprayboot

– Routes

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.

sprayroutes

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.

spraymissingtilda

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.

– Implicits

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.

Conclusion

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.

Continue Reading

First Look: Scala Play Framework

Play Framework makes it easy to build web applications with Java & Scala.

Play is based on a lightweight, stateless, web-friendly architecture.

Built on Akka, Play provides predictable and minimal resource consumption (CPU, memory, threads) for highly-scalable applications.

Play was the first framework I picked up in preparation for a talk Kingsley and I gave at Scala Exchange 2016; Scala Services in Action. As it is one I have used before at a previous company, I was keen to go back and see if I still enjoyed using it a year or so later. I was left with a great first impression from using it in industry, which thankfully has held true throughout my experience at home. As part of the talk preparation, I wrote a small REST application that can be found here, where all of the below examples can be found.

+ Documentation

Play’s website was very nice to use, clear to navigate around and included plenty of sample projects to look at. This is all so very useful when looking at a framework for the first time and can’t be underestimated. Everything I needed when writing my example project was easy to find in the Scala documentation and it covered everything in a way that I understood (not as common as you’d think!).

+ Routes

I really liked Play routes. It felt like a natural separation to keep the routes in a configuration file away from the rest of the Scala code. You simply define the route and direct it to a method in the controller, no fussing with syntax or boilerplate. Once you start to accept payloads or query parameters there is a small amount of googling to find out the exact syntax and how to pass them into your method, but nothing too scary or time-consuming.

playroutes2

– Guice

Play comes pre-packaged with a dependency injection framework by Google called Guice. I can’t say I’m a fan of Guice, I particularly found it to be a huge barrier when using Play as a beginner. It’s quite “magic” in the way that it does a lot of things you can’t see and, everyone knows, when magic goes wrong it’s even harder to understand and fix.

Also, as Scala developers we have come to depend on the compiler, and in most cases if it compiles, we already have a decent amount of faith it will work. Guice introduces these runtime errors into your code which is a HUGE downfall. These errors are often misleading or confusing when the project becomes more complex.

playguiceerror

Furthermore, Guice seems to make testing quite difficult to get going with. Granted, I didn’t spend that much time battling with it, I’d already lost my temper with Guice a long time ago so my patience was wearing thin. I just found the effort in understanding what I had to do and what was going on completely unnecessary. Even though I would use Play in the future, I would not use it with Guice.

+ User Interface

Play comes with a user interface without any extra effort required. At first it may not seem like a big deal, especially if you are planning to return json objects. However, the UI helped me quite a bit when I was testing endpoints or getting runtime errors cough *Guice* cough. As shown below, if you get the endpoint wrong, it shows you all the endpoints that are available to you (thumbs up from a lazy developer).

playui

+ Json formatters

On Play’s website it claims they aim to make Json a first class citizen. So, the good news is Play was the only framework where I successfully manipulated the json I was sending or receiving in one sitting. I was able to negate the need for certain unnecessary fields in the json to maximise usability. For example, I nested my case classes, even for those values that only needed one field like this:

playnamecaseclass

This meant by using the default Play json formatters, I would need to be writing json with extra “value” fields like below. sad face.

jsonwithvalue

Another example would be that you would ideally want to model your data with one case class, for example a pet:

petcaseclasswithoutoption

This means this case class will model what your json will look like in the request and the response. However, it may be misleading or confusing to ask for an ID (also shown in the above json) when someone is ‘registering’ a pet, yet our service needs to respond with an ID when the user ‘GETs’ a Pet so they can use it later to update or delete.

Thankfully, Play json custom formatters (and Options) gives you a huge amount of flexibility.

Here is my custom formatter for the above examples:

petplayjsonformatters

– Compilation: When and How long

Play, by default, has “just in time” compilation. I realise this doesn’t sound like a huge problem, and I would agree, but it did get a bit annoying when doing what should be very quick manual tests on the endpoints. Not only do you have to send the request and wait, you have a to wait quite a while – Play does seem to be very slow 🙁 This also means that you don’t get your compilation errors until after you’ve sent a request for the first time:

routesruntimeerrorplay

which is almost as bad as runtime.

+ Cycle time

I realise that speed and usability are factors that are largely subjective and are not a clear reflection of the framework alone. However, I can claim that compared to the other frameworks I’ve had a ‘first look’ at, this tops my list in this category. The documentation is extensive and clear to navigate around, there are many templates available and every question I asked Google was answered dozens of times.

As for going from zero to service; along with the routes I have shown above, all you need is to add this to your build.sbt:

playbuildsbtand add your method straight to a class that extends Controller:

playcontroller

That’s it. No nasty boilerplate and nothing that isn’t directly focused on the service you want to build.

Conclusion

Play came out top favourite in a poll we ran during our talk in the Scala Exchange! I think this is mostly down to the excellent support and documentation you get if you choose Play, you never feel like you’re the only one who’s approached a particular problem. I saw the biggest downfall was the way it introduces runtime errors to a language that loves to depend on the compiler – I would definitely get rid of Guice.

Resources

  • I found a book by Underscore incredibly useful that can be found here. Great for beginners!
  • Activator is an excellent tool for developers to get started with SO MANY tutorials.
  • This blog by Krzystof Pado is great at looking at all of the dependency injection techniques you can use with Play – excellent read if you are looking for an alternative to Guice.

Sofia x

Continue Reading