One of the more fun opportunities that a hack day provides (apart from the unlimited pizza and beer) is the chance to try out technologies and tools that we don’t get to use in our day job. For the recent Caplin hackathon we built a dashboard that allows an administrator to read and curate a real-time stream of news items from a variety of sources. He can then annotate selected items with his own comments and broadcast them out to all the connected users of our trading application.
I’m not going to write about what we built, except to provide a bit of context. Instead, I want to talk about my first impressions of the Play Framework, and how well it performed in a hack day situation.
Play is an open source MVC web application framework written in Java and Scala. It’s approximately seven years old and still under active development, and is apparently used by a number of major websites including LinkedIn and the Guardian.
I chose to use Play for building our news dashboard for a couple of reasons. The first is that our main integration point with the Caplin platform is a Java library which is used to broadcast messages. Since the server-side code for Play Framework applications can be written in Java, we thought it should be easy to wire up the plumbing of responding to user actions in our web application by calling into our Java library to publish data. The second reason for using Play was that, well, none of us had ever used it before.
A hack day is perhaps the ultimate test of how easily a user can get up and running and be productive with a library or framework. With very limited time to build and even less time to read documentation or trawl through forums, the journey to “Hello World” must be as easy and frictionless as possible (I have written about this before).
Once the Hello World stage has been achieved – and there’s no excuse for that being difficult – you also need good community resources with answers to specific problems you encounter when building your app. Play is a mature framework with big name backing so I was confident that there would be a wealth of good resources and Stack Overflow answers to help me out when my brain inevitably hit the 3:00am Jägerbomb-induced slump. So, how did it perform?
Good: Hello World is easy
There’s a 20 minute “Getting Started” video on the homepage – actually two videos, one for Java developers and one for Scala developers – and prominent links to tutorials. The installation guide is decent, it throws a bit of unnecessary technical information at you about the innards of the framework but you can get it installed and running quickly. There’s a command to generate the necessary project files for your IDE of choice. All good stuff.
Good: Promises equal support for Java and Scala developers
From the very start, Play goes to some lengths to make you feel welcome whichever JVM language you prefer. A lot of the “Getting Started” documentation comes in two flavours, one for Java developers and one for Scala developers. The same applies to the template applications available to download as starting points.
Bad: finding specific information is a bit tricky
Play has a bit of an SEO problem in that it has the same name as Google’s vastly more popular app store. This means that when searching for something you sometimes have to sift through quite a lot of irrelevant results about how to implement the feature in an Android app for the Play Store, rather than an app for the Play Framework
There isn’t really much the Play Framework team can do about the naming clash with Google. However, a more significant problem we found is that the framework documentation is getting hamstrung by the age of the project and the amount of information floating around that is no longer valid.
At the time of writing the latest version of Play is 2.3.6. There was a significant redesign in version 2.0.0 which rendered much of the older documentation obsolete, but it still frequently crops up at the top of search results. Very often we got frustrated trying to follow a thread of information about a specific topic because we kept inadvertently landing on older pages with misleading or out of date advice.
Good: Wiring up the plumbing was simple
As we had hoped, handling user actions in Java code is nice and easy. It’s as simple as adding entries to a plain text routes file with entries like this:
POST /publish-item controllers.PostHandler.publishItem()
You then create a class
PostHandler with a static method
publishItem(), and that’s all there is to it. Your
publishItem() callback is able to access what is effectively an
HttpServletRequest object containing the URL parameters etc.
If I was using Play for a longer project I would be a little concerned that Play provides its own proprietary API for interrogating and responding to HTTP requests rather than following the Servlet spec, but for a hack day project it’s not a problem.
We also wanted our application to handle Websocket connections so that the server can push new data into the page, and Play handles this reasonably well too. The implementation is pretty minimal, so all of the string parsing and authentication etc is left to you to implement however you like. Play also provides its own API for parsing and creating JSON, and as always, it’s horrendous. Is it actually possible to create a nice Java API for parsing JSON or XML? If you know of one, please get in touch.
All in all, Play provided everything we needed to write our server code. Static callback methods for dealing with each request meant we had to introduce a slightly ugly global state object, but code quality and testability is never a huge concern on a hack day.
Good: Plenty of nice features that we didn’t need
By default Play allows you to respond to
POST requests by passing Java data objects into Handlebars-style templates. The template language is proprietary to Play but simple to learn, and if you don’t like it you can swap it out for something else. Database integration looks good as well.
Bad: Promise of equal support for Java and Scala not delivered
From the start, Play presents itself as a language agnostic framework. However, I offer these three nuggets of information:
- For version 2.0.0 the entire core of the framework was rewritten in Scala from the original Java.
- The default templating language was also changed to Scala from Groovy.
- The build tool was changed to SBT (Simple Build Tool).
This gives a pretty clear indication of which direction the core contributors want to move in!
In theory, these changes to the underlying framework shouldn’t have to affect the users of the framework; for example, although the SBT build file looks strange to my Java-trained eye, I never had to do anything with it apart from add a few dependencies by following the convention already contained in the file. The templates that you write are technically using Scala syntax, but it’s easily readable.
Unfortunately, the “Scala first” mindset of the core team seems to be bleeding into the end user experience, particularly when it comes to documentation. The getting started and installation guides are admirably maintained equally in both languages, but this does not hold true as you move into the more advanced parts of the framework. On more than one occasion I would come across documentation that described exactly what I needed to do with Scala code examples, but the equivalent Java page was either out of date or didn’t exist at all.
Although I haven’t used Scala before, it isn’t usually a problem translating code examples from one language to another. When you only have 24 hours to build something you would obviously prefer not to spend time learning the syntax of a new language, but it doesn’t take very long to pick up. That’s not the problem.
The problem is that the Play API does not map from one language to the other on a one to one basis, the Scala and Java APIs seem to have diverged somewhat. Most of the core classes in Play seem to exist at least twice, once in the
play.api package (Scala version) and once in the
play.mvc package (Java version). The classes in these packages frequently do not have the same methods, method signatures, or even the same names. This means that trying to extrapolate what sort of Java code you need to write from a Scala code example is often difficult or impossible.
Too close to call: how does it scale?
From a technical perspective, Play is apparently designed to scale well to many concurrent users. However, I’m more interested in how the codebase for Play applications would scale to larger projects with potentially many developers and work streams. I did notice that quite a lot of the code we wrote wasn’t very pretty, and this seems to be because Java isn’t well suited to the asynchronous callback style of application. We ended up using a lot of anonymous inner classes to act as pseudo-closures, with all of the cruft and boilerplate this implies. If we had used Java 8 lambda expressions it would probably have improved this signficantly.
The fact that the key methods you must implement to receive events must be static also led us to writing a lot of very procedural code. You have to fight against the framework a bit if you want to do something more object oriented, and this raises concerns about how well the app could be unit tested if the code is making a lot of calls to static methods in other classes.
Since we didn’t read up on the patterns or best practices used by other Play developers and were just hacking something together, I’m happy to give Play the benefit of the doubt here and assume the ugly code was our fault!
To conclude then, what were our overall impressions of the Play Framework after 24 hours of use, and would we use it again on another project?
Firstly, to give credit where it’s due, the framework provided everything we needed to build the app that we had envisioned. We needed a framework that was easy to pick up, provided server-side interoperability with Java libraries, and could handle single page applications with persistent Websocket connections. On all of these points, Play gave us what we needed. For that reason, I wouldn’t hesitate to use it on another hack day – especially as I expect we could go a lot faster the second time round.
Whether to use Play for a more long term project is more difficult to say. If you’re a Scala developer or are interested in becoming one, I think it’s a great choice. If you’re a die hard Java developer, probably not. Although it largely works, and I’m sure almost all the same functionality is available, I suspect Java developers using Play will quickly get the nagging feeling that they are second class citizens.
Thanks for reading, and if you have any suggestions for tooling we should take a look at next time, let us know in the comments.