The Play Framework at LinkedIn

February 20, 2013

I’m excited to announce the next step in LinkedIn’s service infrastructure: the Play Framework. Play is a modern web framework that combines the performance and reliability of Java and Scala, the power of reactive programming, and the productivity of full hot reload support.

Play Framework

We’ve been running Play 2.0 in production for several months and are now gradually rolling it out to more teams at LinkedIn. In this blog post, I'll talk about the benefits we've seen from Play, show a brief walk-through of the developer experience, and talk about our future plans.


Play offers a lightweight framework for building scalable services that are easy to maintain; what makes it magical, however, is that it does this without sacrificing developer productivity. Building web services with Java and Scala can actually be fun!

Here are some of the features we love:

A Tour of Play

Let's walk through a quick tour of developing apps with Play. Play has idiomatic support for both Java and Scala; this tutorial will start with some Java examples in the first half and move onto Scala for the second half.

1. Create an app

Follow the install instructions to get the Play executable installed. Create a new app called play-tutorial using the play new command:

play new

2. Run the app

cd into the play-tutorial directory, use play run to fire up the server, and open http://localhost:9000 in your browser:

Default Play splash page

At this point, you can load up the source code for the play-tutorial project in your favorite IDE.

3. Say "Hello World"

Play follows an MVC pattern, so we’ll start by creating a controller called HelloWorld in app/controllers:

Controllers consist of actions, or methods, that return a Result. In the code above, we’re just returning a simple 200 OK with the text “Hello World” as our Result.

All we need to do now is to expose this controller/action at a URL. You do this by adding an entry to the routes file in the conf directory:

The format here is an HTTP method, followed by a URL pattern, followed by the actual controller/action code to execute.

Open http://localhost:9000/hello to test out your new route. Play will automatically reload the Java and routes file changes and you should see the results in your browser in seconds:

Hello world page

4. Read the query string

Let’s make things slightly more dynamic by reading a query string parameter from the URL. First, add a parameter to the index action in HelloWorld:

To specify that this parameter comes from the query string, modify the routes file:

Now open http://localhost:9000/hello?year=2013 in the browser, and you’ll see this:

Hello world with query string

Note that Play will check the parameter types for you. For example, try the URL http://localhost:9000/hello?year=garbage and you’ll see:

Hello world parameter type checking

5. Make a mistake

This is a good time to point out one of our favorite features about Play: you can see error messages right in the browser instead of hunting for them in a log file. For example, let’s say you have a typo in your Java code where you forgot a semi-colon. When you refresh the page, you'll see:

Java syntax error

If you make a mistake in a Java class, Scala class, routes file, template code, or just hit an exception, Play shows the error message, the line number, and even the relevant code right in the browser window.

6. Render a view

Let’s add a view for the HelloWorld controller to render. Play has Scala templates built-in, so we’ll create index.scala.html in the app/views/HelloWorld folder:

The @ syntax at the top lets you pass data from the controller to the view for rendering. Update the HelloWorld controller to render the index view and pass the date parameter to it:

Refresh http://localhost:9000/hello?year=2013 in your browser and you should see this page:

Java syntax error

7. Try out Scala

If you prefer Scala to Java, Play has you covered. Let’s create the skeleton of a Scala controller called Proxy in app/controllers:

We’ll use Play’s WebServices library to make non-blocking calls to a URL passed in as a query string parameter and return the response body as our Result, effectively proxying a website:

Let’s add a /proxy endpoint in our routes file:

Now try http://localhost:9000/skeleton/proxy?path= in your browser. You should see this very blog post!

Proxy example

8. Go parallel

The HTTP calls we made above with the WS library were non-blocking. This means it’s easy to make multiple calls in parallel. Let’s add a new Scala controller called Race that will make parallel calls to a few search engines and return JSON reporting how long it took to get a response from each one:

Now add a /race route:

Finally, open up http://localhost:9000/race and see who’s fastest.

Search engine race

Future plans

The above walk-through is just a small taste of what Play offers. Be sure to check out the Play documentation and sample apps for more.

We've found that Play is one of the few frameworks that is able to maintain the delicate balance of performance, reliability, and developer productivity. As we continue rolling out Play to the entire company and deploying more services, we will be writing about our experiences on this blog.

We're proud to be actively contributing pull requests to Play and will be ramping up our contributions even more in the future. We'll also be releasing a number of open source plugins. Early versions of the dust.js and testng plugins are already available, with many others - including integration, parseq support, and a new assets pipeline - coming soon.

Update: read on to learn about Play Framework and async I/O without the thread pool and callback hell.