Building APIs in Scala with Play! Framework 2 Silicon Valley Code Camp Oct 5 th , 2013 Manish Pandit @lobster1234
Jan 15, 2015
Building APIs in Scala with Play! Framework 2
Silicon Valley Code Camp
Oct 5th, 2013
Manish Pandit@lobster1234
Agenda
Scala
Typesafe Platform
PlayFramework
REST
Hands-on API
Open Floor
Scala
Concise, yet expressive
Statically Typed via Type Inference
Rich Constructs
Functions as First Class Citizens
Power of DSL
Interoperability with the Java Ecosystem
Typesafe Platform
Scala Programming Language
PlayFramework for Web Applications
sbt for builds
Akka
Typesafe Activator
Misc. Tools
Typesafe Activator
A very simple way to start with Scala and Play!
Applications
Browser-based
Interactive
Comes with a good number of templates
Typesafe Activator
Typesafe Activator
Use if you do not have an IDE
Use it to play with various templates it comes with
Yet to mature but a (very) good start
Play! Framework
Simple
Convention over Configuration
Focus on Developer Productivity
Asynchronous Processing Model
Makes testing easy
JSON support for RESTFul Applications
Play! Framework
Not a J2EE compatible framework
Does not follow the traditional request/response model
Creating a Play! Project
Using an IDE
Eclipse Import
Gotchas!
Start with a fresh installation of ScalaIDE
Go to Install New Software – Select ScalaIDE – Check
Play2 Plugin
Run the App!
And Play! with it
http://localhost:9000
Test the app with play test
Play! Core Concepts
Uses sbt as the build system
(In a special way to support always-on builds)
Play! Core Concepts
MVC
Folder Structure
Controllers
Routes File
Tests
Play! Actions
In simple terms, an Action takes function, that takes a
request Request, and returns a Response.
Play! Actions
All routable methods of a Controller are Actions
(Request => Result) function
The almighty Action
A simple, no-request that returns a result.
A function that makes the Request available to the block
You can pass a BodyParser to the Action as an argument
Default BodyParsers are available for common content
types
Play! Console Demo
run vs. ~run
With ~ run or run, change the app with syntax error
Fix the app and retry
Use the app with ~ test in Play! Console
Change the code and watch the tests fail
Change the tests and watch them pass
The Routes file
Type-safe way to define mappings from URLs to Actions
Rich support for basic data types
Handling of defaults
RESTFul APIs
Not JSON over HTTP
Not JSON representation of your Database
No Spec or official standard
RESTFul APIs
Envision the entities as HTTP resources
Envision the interactions as HTTP methods
Read RFC 2616
Play! Hands-on API
Model – A Person
APIs – Get all, Get by First/Last/Zip, Add a person
JSON Request and Response
Model
object PersonModel {
val persons = ArrayBuffer(Person("Manish", "Pandit", 94568), Person("John", "Doe", 95051), Person("My", "Neighbor", 94568))
def add(p: Person) = persons += p
def getAll = persons
def getByFirstName(first: String) = persons.filter(_.first == first)
def getByLastName(last: String) = persons.filter(_.last == last)
def getByZip(zip: Int) = persons.filter(_.zip == zip)
}
case class Person(first: String, last: String, zip: Int)
Controller
object SimpleAPI extends Controller {
implicit val personWrites = Json.writes[Person] implicit val personReads = Json.reads[Person]
def getAll = Action { Ok(Json.toJson(PersonModel.getAll)) }
def add = Action(parse.json) { request => Logger.info(s"Body is $request.body") request.body.validate(personReads) match { case x: JsError => BadRequest case x: JsSuccess[Person] => PersonModel.add(x.get) Created } }
def getByFirstName(first: String) = Action { val list = PersonModel.getByFirstName(first) if (list.isEmpty) NotFound else Ok(Json.toJson(PersonModel.getByFirstName(first))) }
}
Routes# ~~~~# Routes# This file defines all application routes (Higher priority routes first)# ~~~~
# Home page
GET /persons controllers.SimpleAPI.getAll
GET /persons/first/:first controllers.SimpleAPI.getByFirstName(first)
GET /persons/last/:last controllers.SimpleAPI.getByLastName(last)
GET /persons/zip/:zip controllers.SimpleAPI.getbyZip(zip:Int)
GET /persons/default controllers.SimpleAPI.getByFirstName(first="Manish")
POST /persons controllers.SimpleAPI.add
Play! Packaging
Use play dist to package the app as a zip file
Run using the start script
Play! Advanced Topics
Reactive Programming
Akka, Futures, Promises
Play WS Library
Anorm and Slick
Further reading
http://www.playframework.com/
http://typesafe.com/platform
StackOverflow
Source : https://github.com/lobster1234/SVCC2013
We are hiring!
netflix.github.io
techblog.netflix.com
jobs.netflix.com