11.11.2011

Play - Real live experiences

The Play! framework is one of the upcoming stars in the sky of web frameworks. Featuring stateless "share nothing", asynchronous IO and especially blazingly fast turnarounds, it seems to combine two of my dream features: High productivity and trustworthy scalability. Time to test it in a real live project.

Our project

www.waduno.de - short for "what you know" - is a german-speaking website for proving IT and business skills. By mastering several tests, you get scores and can publish them on social networks, your own website or in your resume. In the long run, we enable candidates to enrich their resumes which trustworthy quantitative skill information.

We started waduno by closely following the lean startup methods. In order to provide the high-speed iterations required for a fast validated learning cycle, we needed a highly productive web framework. Ruby on Rails was a natural first choice. But since we are more familiar with the Java world, we looked around and fell in love with Play!

Though it is of course a risk to try a brand new technology for a serious project, our first tests were so promising, we couldn't resist. Just open your browser on your newly created application, change whatever you like, templates, code or configuration, reload - and there you are. It is hard to describe the boost of freedom in development you get from this feature - you have to try!

Basics

The MVP model looks familiar if you accept static methods as manifestations of the stateless architecture. The Play! people did such a good job in simplifying standard tasks. Let's as an example look at the code to save a business object, which is itself of course represented as a Model class:

package models;

import javax.persistence.Entity;
import play.db.jpa.Model;

@Entity
public class Person extends Model {
 public Date created;

 @Required
 @Email
 @Column(unique = true)
 public String email;

 @Required
 public String password;

 @Required
 @Column(unique = true)
 public String name;

 public int score;

 @ManyToOne
 public Company company;

 public static Person findByMailDomain(String domain) {
  return Person.find("email like ?", "@"+domain).fetch();
 }

 public void upgrade(String msg) {
  score++;
  Event.log(this, msg);
  this.save();
 }
}
From that simple example, you can observe several key aspects of Play! models:
  • Persistence is done with JPA
  • The Model base class provides ID handling
  • Several validation annotations are available
  • No anemic models: You find the business code in the model, not in services.
  • Querying is simple using find()-methods
  • the dirty state model is inverted when compared to hibernate et. al.: Objects are only save after an explicit call to save()
The web form for such a class has no real surprises:

#{extends 'main.html' /}
#{set title:'waduno - New Quiz!' /}

#{form @UserAdmin.save()}
<input type="hidden" name="person.id" value="${person?.id}"/>
<div class="region">
Name:<br>
<input type="text" class="big #{errorClass 'person.name'/}" 
        name="person.name" id="title" value="${person?.name}"/>
<br>
<!-- lots of other fields -->
</div>
#{/form}

Here you can see:
  • Play has templates, Groovy based, that can be extended (main.html in this case) and parameterized
  • It can construct URLs for server methods for you (@UserAdmin.save()) 
  • Simple error handling, e.g. by #{errorClass ...}
Now take a look at the controller method:

public static void saveQuestion(@Valid Person person) {
 if (validation.hasErrors())
  renderTemplate("@edit", person);
 person.save();
 show(person.id);
}
public static void show(Long id) {
 Person person = Person.findById(if);
 render(person);
}

Isn't that extremely simple to understand?
  • Play! takes the person.id request Parameter and loads the Person from the database
  • It applies the remaining request parameter to the object
  • ... validates the object
  • ... and the passes it to the controller method
  • The method the shows the form again if validation failed
  • ... or saves the updated object
  • ... and the applies Post-Redirect-Get. Yes, by simply calling another controller method show().
These are only some of the cool things you can do with Play!

Our experiences

It really was fun to develop with Play! We needed one man-month to come up with a first MVP-iteration (and we mostly worked on the graphical design ;-). Variations of flow, output or business logic could be implemented very fast.
We even saw developers and product managers sitting side by side in front of a monitor, trying features and developing in real time! This way not only productivity is boosted, but the whole team gets a much better understanding of product features and technical possibilities.