Introduction to Play framework

This is an introductory tutorial for Play framework. We create simple web applications using Play. The tutorial uses Play version 2.5.

Play is an open source web application framework, written in Scala and Java. Play was created by Guillaume Bort in 2007. Play is heavily inspired by ASP.NET MVC, Ruby on Rails, and Django. Play belongs to the next generation Java web frameworks with others like Dropwizard, Ninja framework, or Jodd.

Play is built using the Model Miew Controller (MVC) architectural pattern. The traditional MVC pattern divides an application into three parts: a model, a view, and a controller. The model represents the data in the application. The view is the visual representation of the data. And finally the controller processes and responds to events, typically user actions, and may invoke changes on the model. The idea is to separate the data access and business logic from data presentation and user interaction, by introducing an intermediate component: the controller.

To optimize developer productivity, it uses convention over configuration and hot code reloading. Convention over configuration is a software design paradigm used by software frameworks to decrease the work needed to set up a project. A framework such as Ruby on Rails or Play uses sensible defaults for project structure, relating object attributes to table columns, or naming of the views. The paradigm is also known as coding by convention.

Main features of Play

The following is a main list of features of Play:

Play has dropped many traditional approaches used in Java web development. It does not use servlets and does not package projects into WAR archives. It does not use huge monolithic web application servers (JBoss, Glassfish) and XML configuration files.

Installing Play

Play is a series of libraries available in a Maven repository. It is possible to use any build tool to create a Play application. By default, Play uses a Sbt built tool, a default Scala build tool, to create Play applications.

To create Play applications, we use a tool called activator. Activator consists of a Sbt build tool, a set of and project templates, and a web interface to manage projects. The two important seed templates are play-scals for Scala developers and play-java for Java developers.

From the Play framework's project page, we download the activator. We recommend to download the whole offline distribution. After we download the distribution, we unpack the package to the chosen directory. We place it into the bin subdirectory of the home directory.

$ export PATH=$PATH:~/bin/activator-dist-1.3.10/bin/

We add the activator's bin directory to the PATH variable.

Creating Play application

Now we are going to create a new Play application.

$ activator new first play-java

The command creates a new Play Java application called first.

$ cd first
$ tree
.
├── app
│   ├── controllers
│   │   ├── AsyncController.java
│   │   ├── CountController.java
│   │   └── HomeController.java
│   ├── filters
│   │   └── ExampleFilter.java
│   ├── Filters.java
│   ├── Module.java
│   ├── services
│   │   ├── ApplicationTimer.java
│   │   ├── AtomicCounter.java
│   │   └── Counter.java
│   └── views
│       ├── index.scala.html
│       └── main.scala.html
├── bin
│   ├── activator
│   └── activator.bat
├── build.sbt
├── conf
│   ├── application.conf
│   ├── logback.xml
│   └── routes
├── libexec
│   └── activator-launch-1.3.10.jar
├── LICENSE
├── project
│   ├── build.properties
│   └── plugins.sbt
├── public
│   ├── images
│   │   └── favicon.png
│   ├── javascripts
│   │   └── hello.js
│   └── stylesheets
│       └── main.css
├── README
└── test
    ├── ApplicationTest.java
    └── IntegrationTest.java

The source code of the application is located in the app directory. The bin directory contains the activator tool. The build.sbt is the application build script. The conf directory contains configurations files and other non-compiled resources. The project directory has sbt configuration files. The public directory contains public assets, such as static HTML files, JavaScript files, images, or CSS files. The test directory is a source folder for unit or functional tests. As the application is build, new directories are generated; for instance the target directory contains files generated by the framework.

$ activator run

From the project directory, we run the application with the activator run command. The application already has some simple code in it.

First Play application
Figure: First Play application

The application listens on port 9000 by default. Note that there is some delay since the application is compiled on the fly.

Now we are going to modify the application a bit.

routes
# Routes
# This file defines all application routes (Higher priority routes first)
# ~~~~

# An example controller showing a sample home page
GET     /                           controllers.HomeController.index
# An example controller showing how to use dependency injection
GET     /count                      controllers.CountController.count
# An example controller showing how to write asynchronous code
GET     /message                    controllers.AsyncController.message

# Map static resources from the /public folder to the /assets URL path
GET     /assets/*file               controllers.Assets.versioned(path="/public", file: Asset)

In the conf/routes file, we have all the routes of the application defined. The router is the component that translates each incoming HTTP request to an action call, which is a public method in a controller class. We can see that the root route / calls the index() method of the HomeController.

HomeController.java
package controllers;

import play.mvc.Controller;
import play.mvc.Result;
import views.html.index;

/**
 * This controller contains an action to handle HTTP requests
 * to the application's home page.
 */
public class HomeController extends Controller {

    public Result index() {
        return ok(index.render("First application"));
    }
}

We modify the HomeController class. The index() method returns ok(), which generates an HTTP 200 OK result. The index action calls the render() method which tells Play to render a template. Using a template is the most common way to generate the HTTP response. We did not explicitly specify which template should be chosen, so Play chooses the default: views/index.scala.html.

index.scala.html
@(message: String)

@main("Welcome to Play") {

    @message
}

We modify the file to contain the above code. This template also calls the main template.

main.scala.html
@(title: String)(content: Html)

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>@title</title>
    </head>
    <body>
        @content
    </body>
</html>

This is main template, which is called from the index template. It fills the title and the content with string data.

First Play application 2
Figure: First Play application 2

Now the documentation is removed and only the message is shown.

Simple form

We create an application that will work with a HTML form.

$ activator new myform play-java

A new Play application is created.

$ tree app
app
├── controllers
│   └── Application.java
├── filters
├── services
└── views
    ├── greet.scala.html
    ├── index.scala.html
    └── main.scala.html

4 directories, 4 files

We delete all existing files in the app subdirectory. We create one Java file and three HTML files.

routes
# Routes

GET      /                           controllers.Application.index
GET      /greet                      controllers.Application.greet

In the routes file, we have two GET requests.

Application.java
package controllers;

import play.data.FormFactory;
import play.mvc.Controller;
import play.mvc.Result;
import views.html.index;

import javax.inject.Inject;

public class Application extends Controller {

    @Inject
    FormFactory formFactory;

    public Result index() {

        return ok(index.render("Enter your name:"));
    }

    public Result greet() {

        String name = formFactory.form().bindFromRequest().get("name");
        StringBuilder sb = new StringBuilder("Hello ");
        sb.append(name);

        return ok(sb.toString());
    }
}

We have an Application controller.

@Inject
FormFactory formFactory;

We inject a FormFactory, which is a helper class to create forms.

public Result index() {

    return ok(index.render("Enter your name:"));
}

The index() action renders a page that tells the user to enter his name.

String name = formFactory.form().bindFromRequest().get("name");

We bind the name request parameter to the name variable.

StringBuilder sb = new StringBuilder("Hello ");
sb.append(name);

return ok(sb.toString());

We build and return a message.

index.scala.html
@(message: String)

@main("My form") {

@message

    <form action="@routes.Application.greet", method="get">
        <input type="text" name="name" />
        <button>Submit</button>
    </form>

}

In the index.scala.html file, we have an HTML form which sends a GET request.

greet.scala.html
@(message: String)

@main("My form") {

    @message
}

The greet.scala.html file shows the generated message.

main.scala.html
@(title: String)(content: Html)

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>@title</title>
    </head>
    <body>

        @content
    </body>
</html>

The main.scala.html file is the main template file, which is merged with other two template files.

This was an introduction to Play framework. You might also want to look at the related tutorials: Stripes tutorial, Introduction to Spark Java, Jtwig tutorial, Java tutorial, or SQL Query tag tutorial.