If you want someone to know how fast and straightforward it is to build a Java web application with the Play framework, then show, don't tell. The most compelling way to do this is to download Play and start coding a web application from scratch, while they watch. This article is a script for a five-minute live-coding Play demo.
This script is based on how I have seen Play's creator, Guillaume Bort, demonstrate Play to introduce it to a small audience. More or less the same demo, but with Ajax, is the video on the front page of http://www.playframework.org/. This is an especially good way of showing Play to a small group of people, if you are fairly fluent with the framework, because you can answer questions about how you do something by just writing the code and showing it working far more quickly than you would be able to with other frameworks.
Open http://www.playframework.org/ Download the binary
There is no need to install Play as such, although you might want to add the download's directory to your PATH, so you can execute the $PLAY_HOME/play commmand directly. On my machine, though, it's just as easy to just type ~/Downloads/play-1.0.2.1/play for this kind of demo.
Execute play new tasks
~ What is the application name? tasks
A task list application is an easy example for people to understand, but it is more fun to pick an example that is more familiar and relevant to your audience, such as 'customers' or 'cocktails'.
Execute find tasks (optional) - List the generated files
It is crucial to note that Play has not generated a lot of code here; the files are minimal stubs that you will only add to, rather than a lot of generated code that you will have to delete.
Execute play run tasks - Start the Play server runtime to run the application.
Depending on what you are used to, start-up time may seem extremely short.
Open http://localhost:9000/ - Show welcome page.
The welcome page describes how the stub application works, which the next few steps show.
Start a text editor.
You could use an IDE, such as Eclipse, already at this point. However, it is useful to start with a plain text editor to make it clear that you do not have to compile the Java code yourself.
Edit conf/routes - Show the route for the GET / HTTP request.
Since Play has an HTTP focus, in incoming HTTP request is a good starting point for explaining how it works. The routes file, is therefore crucial, because this defines the (two-way) mapping between HTTP requests and Java methods.
Edit app/controllers/Application.java - Show the index() method.
Edit app/views/main.html - Show the default template: HTML 5, CSS and jQuery.
Edit app/views/Application/index.html - Show the #{welcome /} tag and replace it with <h1>Tasks</h1>.
Open http://localhost:9000/ - Show the heading.
Edit app/views/Application/index.html - Change the heading to <h1>${items}</h1>.
Edit app/controllers/Application.java - Change the index() method body to the following (omitting a semi-colon).
final String items = "Things" render(items);
Open http://localhost:9000/ - Show the Java compilation error.
Edit app/controllers/Application.java - Add the missing semi-colon.
Open http://localhost:9000/ - Show the number, and Java changes without compilation or deployment.
Edit app/controllers/Application.java - Replace the items declaration line with a String items method parameter.
Open http://localhost:9000/?items=Things
Edit app/controllers/Application.java - Undo the last change - remove the parameter and put the declaration back.
Edit app/views/Application/index.html - Change the heading to <h1>&{'model.tasks'}</h1>.
Open http://localhost:9000/ - Show the message key being displayed, because the message is not defined.
Edit conf/messages - Add the line model.tasks = Tasks
Open http://localhost:9000/ - Show the message being displayed.
Execute Control+C - Show how little logging there is by default.
Execute play eclipsify tasks - Generate Eclipse project and class path configuration.
Eclipse File » Import… » Existing projects into workspace - Show project structure.
Eclipse eclipse/tasks.launch » Run » tasks - Start the Play server runtime from within Eclipse.
Open http://localhost:9000/ - Show the application running.
Edit app/models - create class:
@Entity
public class Task extends Model {
public String title;
}
At this point you may need to explain that Task is a Java Bean at run-time, because Play dynamically adds getter and setter methods for the public fields, turning them into normal Java Bean properties.
Edit app/controllers/Application.java - Change the index() method body to
List tasks = Task.findAll(); render(tasks);
Edit app/views/Application/index.html - After the heading, add:
<ul>
#{list tasks, as:'task'}
<li>${task.title}</li>
#{/list}
</ul>
Open http://localhost:9000/ - Show the JPA error.
Edit conf/application.conf - Uncomment the line # db=mem
Open http://localhost:9000/ - Show the page - no tasks.
Edit app/views/Application/index.html - After the list, add:
#{form @add()}
<p><input name="task.title"> <input type="submit" value="Add Task"></p>
#{/form}
Edit app/controllers/Application.java - Add the method:
public static void add(final Task task) {
task.save();
index();
}
Open http://localhost:9000/ - Add tasks.
Edit app/views/Application/index.html - Inside the <li> add a link:
<a href="@{delete(task.id)}">delete</a>
As for forms, there is also a tag for generating links; this way just generates the URL.
Edit conf/routes - Add GET /delete Application.delete
Edit app/controllers/Application.java - Add the method, noting the id parameter:
public static void delete(final Long id) {
Task.findById(id).delete();
index();
}
Open http://localhost:9000/ - Delete tasks - show the link URL and query string parameter.
Edit app/views/Application/index.html - Change the heading to:
<h1>${tasks.size()} Task${tasks.pluralize()}</h1>
Open http://localhost:9000/ - Add/delete tasks to show singular and plural forms.
If you are lucky, at this point someone in the audience will be smart enough to point out that some plurals are not just formed by adding an 's', at which point you can change the example, and show the pluralize method with one or more parameters, e.g. ${tasks.pluralize(messages.get('task'), messages.get('tasks'))}
Edit models/Task.java - Add the @Required annotation to title field.
Edit app/controllers/Application.java - Add the @Valid annotation to the add method's Task parameter, replace the first line of the method body (Task.save();) with the following.
if (validation.hasErrors()) {
validation.keep();
}
else {
task.save();
}
Edit app/views/Application/index.html - before the form, add:
#{errors}
<p style="color:red">${error}</p>
#{/errors}
Open http://localhost:9000/ - Show the validation error when submitting an empty name.
The validation error is just 'Required', but we can change this.
Edit conf/messages - Add the line validation.required = %s is a required field
Open http://localhost:9000/ - Show the new validation error.
Now we get the field name, but not as a formatted label.
Edit conf/messages - Add the line task.name = Task name
Open http://localhost:9000/ - Show the new validation error.
This lists validation errors in one place. A better way is to list the errors next to each field.
Edit app/views/Application/index.html - Replace the errors tag with:
#{ifErrors}
<p style="color:red">Validation failed</p>
#{/ifErrors}
… and after the text input, before the closing </p> tag, add:
<strong style="color:red">#{error 'task.name' /}</strong>
Open http://localhost:9000/ - Show the new validation error.
Peter Hilton is a senior software developer at Lunatech Research and committer on the Play open-source project.
Please send comments on this article to editorial@lunatech.com.
Copyright © 2005-2010, Lunatech Research B.V. All rights reserved.