Introduction to Play framework
last modified July 6, 2020
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 uses JBoss Netty for the web server by default.
- It uses the Scala SBT build tool to build applications.
- It is a RESTful framework.
- It has a persistence layer based on JPA.
- It uses Scala for the template engine.
- It is a full stack framework which contains libraries for many common development tasks such as JSON parsing, validation, persistence, or authentication.
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.

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 # 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
.
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
.
@(message: String) @main("Welcome to Play") { @message }
We modify the file to contain the above code. This template also calls the main template.
@(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.

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 GET / controllers.Application.index GET /greet controllers.Application.greet
In the routes
file, we have two GET requests.
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.
@(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.
@(message: String) @main("My form") { @message }
The greet.scala.html
file shows the generated message.
@(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.
List all Java tutorials.