Generic Top

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:


1. Overview

The purpose of this intro tutorial is to explore the Play Framework and teach you how to create a web application with it.

Play is a high-productivity web applications framework for programming languages whose code is compiled and run on the JVM, mainly Java and Scala. It integrates the components and APIs we need for modern web application development.

2. Play Framework Setup

Let’s head over to Play framework’s official page and download the latest version of the distribution. At the time of this tutorial, the latest is version 2.5.

This will download a small starter package with a script called activator inside the bin folder. This script will setup the rest of the framework for us incrementally as and when we need the different components.

To make things simple, we will need to add the activator to PATH variable so as to run it from the console.

3. Anatomy of Play Applications

In this section, we will get a better understanding of how a Play application is structured and what each file and directory in that structure is used for.

If you would like to challenge yourself to a simple example right away, then skip to the next section.

The app Directory

This directory contains application sources and all executable resources. Java source code, web templates and compiled assets’ sources and is the core part of our API.

It contains some important subdirectories each of which packages one part of the MVC architectural pattern, plus optional files and directories:

  • models – this is the application business layer, the files in this package will probably model our database tables and enable us to access the persistence layer
  • views – this package contains HTML templates that can be rendered to the browser
  • controllers – a subdirectory in which we have our controllers. Controllers are Java source files which contain actions to be executed for each API call. Actions are public methods which process HTTP requests and return results of the same as HTTP responses
  • assets – a subdirectory which contains compiled assets such as CSS and javascript. The above naming conventions are flexible, we can create our own packages e.g. an app/utils package. We can also customize the package naming app/com/baeldung/controllers

The bin Directory

Contains the activator scripts we will be using to run our application. Apart from run, It offers other utility methods such as clean, compile and test.

The conf Directory

Where we configure the application. It contains two most important files.

The application.conf file is where we configure things like logging, database connections, which port the server runs on, and more.

The routes file is where we define our application’s routes and mappings from HTTP URLs to controller actions.

The project Directory

Contains the files that configure the build process based on SBT (Scala Build Tool).

The public Directory

Contains public assets such as CSS, javascript and image files for rendering to the browser.

The test Directory

This directory contains unit test and integration test suites for the Play application.

The build.sbt File

The application build script.

4. Simple Example

In this section, we will create a very basic example of a web application and use it to familiarize ourselves with the fundamentals of Play framework.

Remember that we just set up a skeleton of the framework. Therefore, the first time we execute a new command, Play will need to download all the related dependencies to fulfill the command; this could take quite a while depending on our internet connection.

The next time we execute the same command, Play will have what it needs, so it won’t need to download anything new and will be able to execute the command faster.

Let’s open a command prompt, navigate to our location of choice and execute the following command:

activator new webapp play-java

The above command will create a new web application called webapp from a Java template. In the same way, Scala developers would use play-scala instead of play-java.

When we check webapp directory after the console process has completed, we should see a directory structure as below:


We should be able to understand this now as in a previous section, we inspected each directory and file of webapp individually.

From the console, let’s cd into webapp directory to run the new application. Execute the following command from the project root:

activator run

The above command, after completion of execution, will spawn a server on port number 9000 to expose our API which we can access by loading http://localhost:9000. We should see the following page loaded in the browser:


Our new API has four endpoints which we can now try out in turn from the browser. The first one which we have just loaded is the root endpoint which loads a startup documentation of webapp as we may have already noticed.

The second one, accessible through http://localhost:9000/message will greet us with a Hi! message.

The third at http://localhost:9000/count will load an integer which is incremented each time we hit this endpoint.

The last one at http://localhost:9000/assets is meant for downloading files from the server by adding a file name to the path, since we have not created any files on the server yet, it will load an informative error page.

5. Actions and Controllers

An action is basically a Java method inside a controller class that processes request parameters and produces a result to be sent to the client.

A controller is a Java class that extends play.mvc.Controller that logically groups together actions that may be related to results they produce for the client.

Let’s head over to webapp/app/controllers and pay attention to HomeController.Java and CountController.Java. Each one contains a single action.

HomeController‘s index action returns a web page with startup tutorials. This web page is the default index template in views package and a text is passed to it to be displayed at the top of our page.

Let’s change the text a little:

public Result index() {
    return ok(index.render("REST API with Play by Baeldung"));

and reload the page in the browser:

We can do away with the template completely so that we only deal with what we can control and what we are interested in:

public Result index() {
    return ok("REST API with Play by Baeldung");

in which case when we reload, we will have only this text in the browser, without any HTML or styling:

REST API with Play by Baeldung

We could as well include our own HTML-like wrapping the text in the header <h1></h1> tags and receive the appropriate result on reloading, feel free to play around with it. But there is a catch! Let’s see.

CountController uses an inbuilt counter to maintain state with how many times the /count endpoint has been hit using the count action:

public Result count() {
    return ok(Integer.toString(counter.nextCount()));

Let’s customize it a bit:

public Result count() {
    return ok("<h1>API hit count:" + Integer.toString(

When we reload, instead of getting a tiny integer, we now have a large text with HTML header formatting.

We have manipulated our response by customizing the response type. We’ll look into this feature in more detail in a later section.

We have also seen two other important features of Play Framework.

First, our code changes are compiled on the fly and reloading the browser reflects the most recent version of our code.

Secondly, Play provides us with helper methods for standard HTTP responses in the play.mvc.Results class. For example, the ok() method which returns an OK HTTP 200 response alongside the response body we pass to it as a parameter.

There are more of such helper methods such as pageNotFound() and badRequest() which we will explore in the following section.

6. Manipulating Results

We have been benefiting from Play’s content negotiation feature without even realizing. Play automatically infers response content-type from the response body. We have been returning:

return ok("text to display");

And Play would automatically set Content-Type header to text/plain. We can take over control and customize this.

We customized the response for CountController.count action to text/html like so:

public Result count() {
    return ok("<h1>API hit count:"+Integer.toString
      (counter.nextCount()) + "</h1>").as("text/html");

We could have done the same using response() method of super class, Controller like so:

return ok("html formatted text");

This pattern cuts across all kinds of content types. Depending on the format of the data we pass to the helper method ok, we can replace text/html by text/plain or application/json.

If we need to set response headers, the response() helper method still comes in handy:


Apart from ok() helper method, the Play.mvc.Results class offers other helper methods for standard HTTP responses such as pageNotFound() as we saw in the Actions and Controllers section.

7. Conclusion

In this article, we have explored the basics of Play Framework. We have also been able to create a basic Java web application using Play.

To get full source code, you can check out the project over on GitHub.

Generic bottom

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2: