My Journey away from Play Framework….and back again

Background

As many who know, or follow me, I am a strong advocate of the Play Framework. I am first and foremost a Java developer, and the Play Framework was a breath of fresh air. That is what led me to start this blog, and eventually write the Play Framework book. However, Play took a change of direction several years ago with the release of Play 2. Ever since then, Play 1 has been in maintenance mode, and whilst Nicholas and co have done some work on it to keep it going, it is clear that there is not going to be a major jump forward in Play 1. There have even been a few times when the community have tried to resurrect the framework, but with a small number of backers, and seemingly limited personal time to commit to the project to bring it back up to current, it simply has not worked.

What Next

I have been looking to build a personal project for a few months now, and this brought me to the decision of what the stack should be for this project. Quite quickly, I found myself choosing AngularJS for the client side, MySQL for the database layer (I just couldn't get on with the references problem in a Document style database). So, all that was left was to choose the Web Framework. This was a much more difficult choice, and I will take you on a little bit of a journey as to how I came to conclude this choice.

What Was I Looking For

Basically, I wanted a replacement for Play 1. Play did most of what I wanted and needed, so that was my starting point. To be specific, what I wanted was

  • As little boilerplate as possible. I loved the magic of Play that just made my life easier and faster
  • Simple database interaction
  • Good JSON integration: Angular was going to be mainly talking with JSON Web Services.
  • Good community support: there are always questions, and Google having the answers is an important part of any framework
  • Rapid application development. I don't have a lot of time to develop in my spare time, so when I pick up my laptop for an hour or two, I really want to make some progress, otherwise the project becomes to feel tiresome!

The Options

I decided to evaluate quite a few different options. I won't go into huge details of why I picked them, I was simply exploring. I am sure some of you will have your own favoured framework I did no evaluate, but that's the joy of programming…there are huge options out there!

  • NodeJS: As more and more is going client side, I wanted to see how much I could achieve in just JavaScript
  • MeteorJS: Similar to Node, but I have heard some great things about Meteor, so wanted to give it a try
  • Grails: Play 1 was inspired a lot by Grails, so I thought this may be a good choice
  • Spark Framework
  • Play 2 Java & Scala

The Approach

I created a few interactions in the Angular app, and built a few mock JSON Web Service calls. I basically created a few CRUD type operations, such as Login (using JWT), Create item, List items, Delete item etc. I then created a database to match the data items I wanted to build the CRUD against, and was ready to implement the Web Services layer.

Evaluation

Meteor

I tried Meteor first, whilst looking into Node, it felt like Meteor would take away some boilerplate for me, and make development more rapid. However, I found it quite complex when working through the tutorials. I was expecting the code base to be brief for the simple examples I was working through, but this was not the case. I was concerned about how easily maintainable the solution would be. As such, I didn't spend too long on the Meteor journey (I see great potential for certain apps, but not for the simple interactions that I required), but may revist for future projects.

Node

I actually really liked Node to begin with. I found it simple and quick to get started, and it was quite nice not having to jump between languages from client side to server side interaction. However, I got to the point where I was uncomfortable about how maintainable the solution would be. Whilst many of the interactions were simply functional, there were a few where I needed a little bit of imperative coding, such as perform a DB operation, and depening on the result, do another DB operation, and then possibly another. This brought me to the "Callback Hell" anti-pattern. I started working with Futures and Promises, but I felt I was trying to solve a problem that Java would easily solve for me by being imperative. So, after a promising start, I put Node to one side (but enjoyed using it all the same).

Grails

I had high hopes for Grails, based on it being partly the inspiration for Play. It actually started off quite well. For simple Entities, the configuration was brief and easy to use. Annotations worked neatly. However, I need to get some summary information out of the Entities, without loading the whole sub-entity. I found myself craving direct database access, instead of using JPA. I know this philosophy has been brought into Play 2 (especially Scala), and I can understand why this is necessary.

Spark Framework

I really like the Spark Framework, but it just isn't a full framework. I liked that it was Java 8 ready, so could make use of lambdas to remove boilerplate, but I found myself trying to extend it to be more like Play. I did this by having some auto-discovery of controllers, and building some utils, such as JWT and JSON integration, but it felt like to make this framework what I needed it to be, I would have to build out a medium size project just to get started. Whilst I was quite interested in taking this approach, but before I invested in a decent amount of time in this, I thouht I would go give Play 2 a fair shot. I would say though, this approach does feel like the future of Java Frameworks: code like the following just feels like the right way to write an HTTP method in Java.

get("/api/person/:id", (req, res) -> { 
  return "Hello from user ID " + req.params("id");
});

Play 2

So, before I discuss Play 2, I should make it clear that I have been a little biased when it came to Play 2. I didn't want Play 1 to die, and I didn't invest heavily in Play 2. I was a technical reviewer on the Play 2 Java book, so I was quite comfortable with Play 2 for Java, but whilst I have been learning Scala, I just haven't given Play 2 for Scala the time and energy it deserves. So I created an app for Java and Scala in Play 2 to compare and contrast.

With Play 2 Java, I went with Ebean, but soon found myself up against the same issues as Grails. Play 2 for Java is a neat framework, but I do find it somewhat confused. It feels like a second class citizen to the Scala version, the philosophy of the framework seems to be Scala first, and try to get Java to fit in. For me, it just doesn't quite work. It feels a little disjointed. That's not to say it is a bad framework, it is definitely my second choice from my journey of searching, it just doesn't feel quite as polished as Play Scala.

So, that brings me to Scala. I used Anorm, and I used JSON Inception (nice work @mandubian). I had access to JWT from a Java library with a very simple conversion to Scala. In brief, I had it all set up very rapidly, without very much hassle at all. My only gripe (and this may be my newness to Anorm), was that I was using pattern matching to create a case class from the SQL query. Getting the pattern to match was a lot of trial and error (how did I know that a "SELECT count(1) FROM …" returns an Option[Long]?). Because the match will quietly ignore non-matching cases, I found it difficult to diagnose. Other than that, I was happy with the minimal code, the speed of development, the ease of JSON interactions, the flexibility the direct SQL gave me.

Conclusion

I found myself searching for an alternative to Play, and found myself coming back to the new (okay, not quite so new!) Play. I have a lot to learn here. I haven't kept up with Play and my Scala is passable at best, but I have enough to be getting on with. I therefore will challenge myself to get better at Scala whilst building my new Web Application, and see where this journey takes me to next.

I should also stress that with many architectural choices, this journey was very specific to my use case, and needs. I am sure others would follow the same thought process and would come to the same conclusion, and other come to others. This is not a slight to the other frameworks, it is just a realisation of my use case, my skills and my preferences that have brought me to this answer.

One thing is for sure though. When Play 3.0 comes out, I will be giving it my all at the start, rather than trying to hold on to an older framework.