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.
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.
Benefits
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:
- Rapid iteration: change the code, refresh the page, and see the change instantly.
- Java and Scala: JVM performance, type safety, libraries, IDE/tooling support, huge community.
- Reactive: non-blocking IO makes parallel data fetch easy and real-time web possible.
- Open: github repo, documentation, user group, open source plugins, and StackOverflow.
- Supported: Typesafe and Zenexity provide commercial support for Play.
- Flexible: almost everything is pluggable, configurable, and customizable.
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:
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:
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:
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:
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:
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:
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:
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=http://engineering.linkedin.com/play/play-framework-linkedin in your browser. You should see this very blog post!
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.
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 rest.li 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.