This is a multi-part guide to walk you through how to make a RESTful API with JSON using Play 2.5.
We’ll demonstrate with a “best practices” REST API. You can get source code for this guide two ways:
Download a pre-packaged bundle with this link https://example.lightbend.com/v1/download/play-scala-rest-api-example
unzip play-scala-rest-api-example.zip cd play-scala-rest-api-example ./sbt
- Unzip the download
From a command line
cdinto the directory where you expanded the downloaded
zipfile and run:
git clone https://github.com/playframework/play-scala-rest-api-example.git git checkout 2.5.x
This example is in Scala, but Play also has a Java API which looks and acts just like the Scala API, and has a corresponding play-java-rest-api-example project. For instructions on running and using the project, please see the appendix. This project also comes with an integrated Gatling load test – again, instructions are in the appendix.
Note that there’s more involved in a REST API – monitoring, representation, and managing access to back end resources – that we’ll cover in subsequent posts. But first, let’s address why Play is so effective as a REST API.
Play makes a good REST API implementation because Play does the right thing out of the box. Play makes simple things easy, makes hard things possible, and encourages code that scales because it works in sympathy with the JVM and the underlying hardware. But “safe and does the right thing” is the boring answer.
The fun answer is that Play is fast.
In fact, Play is so fast that you have to turn off machines so that the rest of your architecture can keep up. The Hootsuite team was able to reduce the number of servers by 80% by switching to Play. if you deploy Play with the same infrastructure that you were using for other web frameworks, you are effectively staging a denial of service attack against your own database.
Play is fast because Play is built on reactive bedrock. Play starts from a reactive core, and builds on reactive principles all the way from the ground. Play breaks network packets into a stream of small chunks of bytes. It keeps a small pool of work stealing threads, mapped to the number of cores in the machine, and keeps those threads fed with those chunks. Play exposes those byte chunks to the application for body parsing, Server Sent Events and WebSockets through Akka Streams – the Reactive Streams implementation designed by the people who invented Reactive Streams and wrote the Reactive Manifesto.
Linkedin uses Play throughout its infrastructure. It wins on all four quadrants of scalability (video). Play’s average “request per second” comes in around tens of k on a basic quad core w/o any intentional tuning – and it only gets better.
Play provides an easy to use MVC paradigm, including hot-reloading without any JVM bytecode magic or container overhead. Startup time for a developer on Play was reduced by roughly 7 times for Walmart Canada, and using Play reduced development times by 2x to 3x.
Play combines this with a reactive programming API that lets you write async, non-blocking code in a straightforward fashion without worrying about complex and confusing “callback hell.” In both Java or Scala, Play works on the same principle: leverage the asynchronous computation API that the language provides to you. In Play, you work with
scala.concurrent.Future API directly, and Play passes that asynchronous computation back through the framework.
Finally, Play is modular and extensible. Play works with multiple runtime and compile time dependency injection frameworks like Guice, Macwire, Dagger, and leverages DI principles to integrate authentication and authorization frameworks built on top of Play.
One thing to note here is that although this guide covers how to make a REST API in Play, it only covers Play itself and deploying Play. Building a REST API in Play does not automatically make it a “microservice” because it does not cover larger scale concerns about microservices such as ensuring resiliency, consistency, or monitoring.
For full scale microservices, you want Lagom, which builds on top of Play – a microservices framework for dealing with the “data on the outside” problem, set up with persistence and service APIs that ensure that the service always stays up and responsive even in the face of chaos monkeys and network partitions.
With that caveat, let’s start working with Play!