Learnings from a new technology stack

After years of programming in Java with frameworks like Spring, GWT, JBoss, Hibernate, Seam and other traditional stuff, I needed a new learning curve. My colleague Mats Strandberg invited me to create a new version of his code kata/hobby project SignUp.

SignUp has been built and rebuilt several times before, but for this incarnation (number 4 of the more prominent ones) we decided to use some stuff we haven’t used so much before: Scala, Play! Framework 2.0, Anorm, Twitter Bootstrap and Secure Social. We store the source code on GitHub and deploy on Heroku. In this article I’ll summarize some of the things I learned so far. Since I’m an IntelliJ IDEA user, there is some of that too…

SignUp is a simple group meeting tool where meetings and events are announced, and the invited can indicate if they are coming or not. Not much difference from a regular calendar, but easier to use with its simple web interface, and the group doesn’t have to reside on the same calendar/mail server.

At the time of writing the user interface is in Swedish, but perhaps you can make some sense of it in English by viewing it through Google Translate 🙂 The multi language feature is yet to come.

Scala

Ever since I did Martin Odersky’s training and read Olle Kullberg’s first Swedish Scala book Ett första steg i Scala I’ve been dying to use the language in a real project. Scala is supposed to be the future of JVM based languages supporting functional as well as object-oriented programming. To me though, Scala is a bit like C++ was to C; a double edged sword, not always serving you as a programmer.

Scala is excellent for creating DSLs, which can make your code very non-verbose and clear – or totally obscure. Using a DSL you are in the hands of the author’s sense for clarity, and since Scala encourages compactness and operator overloading most DSLs are packed with symbols like ~, ->, =>, [], etc. instead of spelling it out in plain text. The odd effect of this is that when you read the code it can make good sense, but when you write it you have no idea which symbol to use in a given situation. This made me program slower than usual, and forced me to do a lot more lookups, and copy/paste from examples. I never felt fluent at all.

// Source code from User.scala
val parser = {
  get[Pk[Long]]("id") ~
  get[String]("first_name") ~
  get[String]("last_name") ~
  get[String]("email") ~
  get[String]("phone") ~
  get[String]("comment") map {
    case id ~ firstName ~ lastName ~ email ~ phone ~ comment =>
      User(
        id = id,
        firstName = firstName,
        lastName = lastName,
        email = email,
        phone = phone,
        comment = comment
      )
  }
}

Note the above code snippet. It looks nice when reading it now, but writing it from scratch was hard for me. The characters ~ (tilde) are actually multiple function calls. In fact there are two functions named ~ that are called in this code, one is used where all the “get” calls are (defined in Anorm’s RowParser trait)  and one is used in the “case” statement. The latter is actually a constructor of a class named ~ in the anorm package. I was not able to write this seemingly simple piece of code without copying and pasting examples, turning me into a dumber programmer than I usually am.

One thing I do like a lot about Scala, and which is often forgotten, is the improved support for OO programming. Scala has support for mixins (traits), implicit (context) parameters, closures, and there are no primitives – even numbers are objects (as it should be). I love this, and I can see myself choosing Scala for these features alone.

Play! Framework 2.0

The Play! Framework 2.0 is an HTTP (not Servlet) oriented MVC framework with the developer experience (Dx instead of Ux) in focus. It has stolen shamelessly all good ideas from other frameworks for other programming languages, such as Ruby on Rails. And in my opinion quite successfully so.

Version 2.0 is apparently very different from 1.0. It is in fact a total rewrite in Scala, which has divided the existing community into two camps: the ones who appreciate the (r)evolution and the ones suffering from not being able to upgrade their Play 1.0 applications without having to rewrite them.

Play is a joy to work with. It’s simple, direct and fast. The framework compiles your stuff in the background, so any code change is quickly available by reloading in the browser. You never have to relaunch the container, and the error messages you get are very clear and informative. With a strongly typed language like Scala in the background, all files (even configuration files) are actually compiled and type checked, which eliminates the effects of typos and such.

Play is HTTP centric (stateless) which means you can use it for tasks other than providing HTML GUIs, such as web services or (even better) RESTful services. Play also have a Java binding, so this framework is a keeper for me, regardless of which JVM language I’ll be using in the future.

Anorm

Anorm is a persistence API that comes with the Play framework. Its recursive acronym is “Anorm is Not an ORM“. This is not a mandatory part of Play, you can use anything you like for persistence, but Anorm is like the rest of Play simple and direct. It basically does JDBC, but better. You use SQL to communicate with the database. Parameters and results are mapped using a parser you define in your model/entity objects. You can explicitly use transactions and connections if you wish. And that’s it.

def findAll(): Seq[Event] = {
  DB.withConnection {
  implicit connection =>
    SQL("SELECT * FROM events ORDER BY start_time DESC").as(Event.parser *)
  }
}

For simple CRUD applications (like SignUp) Anorm is so easy to use, but only works with SQL. And you have to manage associations and lazy/eager loading yourself in your little result parser, so for other types of databases or complex data structures you may want to use something else.

Twitter Bootstrap

Twitter Bootstrap seems to be the new defacto standard for many responsive HTML 5 designs. It basically consist of a CSS library and a few components in JavaScript. This is pure front end technology, so it doesn’t matter if you use Scala, Java, C# or whatever in your back end serving the HTTP calls.

It is very easy to learn and the documentation is exemplary, and it makes your GUI look really good with very little effort. There are plenty of add-on components and stuff out there, in case you find anything missing from the core distribution.

For me, this framework is definitely a keeper and  I will most likely use it in my next web application.

Secure Social

Secure Social allows a Play 2.0 application to do authentication using a range of social networks like Twitter, Facebook, Google, LinkedIn and GitHub. We are still in the process of integrating it, but it seems straightforward and really promising. Secure Social comes in the form of a Play module, which as far as I understand needs to be included as source code (I may not know Play well enough here). Graphically it’s based on Twitter Bootstrap, so it should be easy enough to use its default login page etc.

Heroku

When we started this little project Heroku was the only cloud application platform that supported Play applications out of the box. Thanks to Heroku we have a very quick release process. Just do:

git push heroku master

at the command prompt in your top level source directory, and the application is automagically compiled and deployed in the cloud.

Heroku also contains a Postgres database in the free offering, and if you pay there is a good range of addons. The only drawback is that Heroku doesn’t have a continuous integration environment, like CloudBees with its built in Jenkins support. Recently CloudBees announced native support for Play! 2.0 applications, so this is something I’ll have to try out soon.

IntelliJ IDEA

The popular IDE IntelliJ IDEA does support Scala out of the box, but the current version 11 doesn’t support Play 2.0. However, there is a version available from their early access program that does, so my advice is to download and use that version for your Play projects. Two versions of IntelliJ IDEA can be installed and run in parallel without any problems.

After installing the EAP version, make sure you disable the bundled “playframework” plugin which only support Play 1.x, and download the Scala and Play 2.0 for Scala plugins from the plugin repository. With these plugins you have good support for refactorings and highligting.

Play 2.0 itself supports IntelliJ IDEA by being able to generate project files with the command line utility:

play idea

Finally

If you want to try this stack yourself, check out the source code on GitHub. There are some instructions there that are useful when setting up the environment. This project is however not yet completed. There are some major features missing, such as automatic reminders (we plan to use Akka for that) and authorization. The authentication using Secure Social is work in progress.

6 responses on “Learnings from a new technology stack

  1. Nice write-up. I think that while the positives you mention about Scala as a language are definitely big wins, the lack of readability makes it much less interesting. As a non-everyday user of Scala, I’m not even sure how to read the User.scala class out loud. “get id tilde” isn’t very descriptive, and you need to understand the implementation just to read the code. So my vote is for more verbose code that’s easier to read 🙂

    1. Don’t get hung up on the parser combinator syntax, which is one of the more advanced features of Scala. I’ve found that scala code can be as simple to read as python or as terse as haskell; it’s up to you and how you choose to code it. Readability is definitely one of scala’s strengths.

      1. The parser stuff was just one example. The problem with using other people’s DSLs and APIs in general is that it’s not up to me how the author of those have chosen to code them. With the functional style in combination with operator overloading the possibilities to make pretty but hard to understand APIs are huge. I think that many Scala fans have confused readability with compactness and expressiveness, but one doesn’t imply the other.

  2. Jan,

    Nice article. Glad to know you found SecureSocial easy to use 🙂
    For now, the way to integrate SecureSocial into your app is by copying the sources. I know this is not ideal but there’s a bug in Play related to routes in submodules that prevents a better integration. The fix is targeted for Play 2.1.

    Feel free to ping me if you have questions on the module.

  3. I liked your article and the choice of stack elements: Play/Scala, Anorm especially. I am about 75% through a complete rewrite of a C# desktop application for a business that uses it for mission critical work. I wrote the original and they now want it ‘webified’.

    For that, I chose to write a RESTful web service using Play 2.1.2 on Anorm (with MySql – the existing DB engine for the desktop app).

    I also chose to use Spray-Json – a Scala/JSON marshaling layer that has proven to be very good at concisely translating between JSON and Scala case classes that hold my model objects. I agree with you about the Scala language – I’m very enthusiastic about using it, being a Java developer for many years (along with C++, C#, C, Python, Perl). I agree about the difficulties that can arise when someone decided to overload a bunch of non-intuitive operators for operations that don’t require it (or that don’t gain readability from it).

    On the GUI side, I went with GWT and GXT widgets along with RestyGWT (JSON marshaling layer for GWT).

    I recently ran into a lack of documentation for how to use transactions with Anorm – so I am having to experiment with it. If you have used transactions in Anorm I’d love to hear about your experiences with them.

    Thanks again for the article. Hope your application development work is as frustration-free as possible (and even fun).

    1. Thanks Joel!

      You can look at the source code for this project on https://github.com/crispab/signup and see how I use Anorm.

      The play.api.db.DB object will help you with creating transactions. Here is a snippet from Event.scala:

      import play.api.db.DB
      // ...
      def delete(id: Long) {
          DB.withTransaction() {
            implicit connection =>
              SQL("DELETE FROM participations p WHERE p.event={id}").on('id -> id).executeUpdate()
              SQL("DELETE FROM log_entries l WHERE l.event={id}").on('id -> id).executeUpdate()
              SQL("DELETE FROM reminders r WHERE r.event={id}").on('id -> id).executeUpdate()
              SQL("DELETE FROM events e WHERE e.id={id}").on('id -> id).executeUpdate()
          }
        }
      

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.