1. Play Framework and Activator
Getting started with the Play Framework with Activator
2. Topics, goals, context
2
• An introduction to Typesafe Activator
• An introduction to the core features of Play 2.x
• What is a Reactive application, and how do you build one with Play?
7. Activator Overview
7
• Learn — In depth tutorials
• Develop — Code, compile, test,
run, inspect
• Deliver — Monitoring
integration with AppDynamics
and New Relic
8. Code view
8
• Activator
• Browse code
• Make small changes
• IDE
• Generate IDEA or Eclipse
project files
• Dig into the template in your
favourite IDE
9. Development monitoring
9
• Incoming requests
• Controller
• HTTP verb (GET, POST, etc)
• Response code
• Invocation time
10. Inspect — Development monitoring
10
• Actor metrics
• Throughput — messages/s
• Max time — high watermark
• Max size — mailbox
11. Monitoring and support
11
• Application monitoring
• Need production caliber monitoring?
• AppDynamics or New Relic integration
• Support
• Ready to take your application to the
next level?
• http://typesafe.com/how/subscription
12. Contributing a template — tutorials vs seeds
12
• Seed
• Boilerplate code as a starting point
• Tutorial
• Teaching about a particular focused topic or integration
• Components
• Activator templates are just regular sbt projects with some additional components
• Metadata (activator.properties), license, sbt build file, tutorial (tutorial/index.html)
• Contribute!
• https://typesafe.com/activator/template/contribute
13. The Typesafe Activator UI is a Play framework application.
!
Peek behind the covers…
!
https://github.com/typesafehub/activator/tree/master/ui
14. Play 2.3 overview
14
• Stateless MVC framework with routing, a template engine, REST support, etc
• Dynamic class reloading
• Support for Java 8 and Scala 2.1x
• sbt-web to implement an asset pipeline
• Akka interoperability for highly concurrent web applications
• Built on Netty 3.9.x
17. 17
Simplified HTTP request
1. mydomain.com/admin/settings
renders views.html.admin HTML
2. Browser fetches static assets served
from outside of Play
3. Ajax requests — Play serves JSON
via a RESTful API
Browser Play
HTTP GET (mydomain.com/admin/settings)
HTML for views.html.admin(...)
CDN
JS, CSS, images, etc
HTTP GET (mydomain.com/ws/some/services)
JSON
18. Example template with AngularJS
18
@(customer: Customer)!
!
<head>...</head>!
<body>!
<div class="wrapper">!
<header>…</header>!
<h1>Welcome @customer.name!</h1>!
<section id="body" ng-app="ngAdmin">!
<div ng-view></div>!
</section>!
<footer>...</footer>!
</div>!
</body>!
</html>
load async || fail whale
• Scala template rendered by Twirl and returned by Play controller
Header
Play handles navigation
Footer
• HTML inserted into ng-view by Angular controller after initial page render
load async || omit
AngularJS
20. routes
20
GET !/admin!! ! ! ! controllers.AdminController.index!
GET ! /admin/login! ! ! controllers.AdminController.login!
GET ! /admin/*any! ! ! controllers.AdminController.angularWildcard(any: String)!
GET ! /ws/some/service! ! controllers.ServiceController.service
• Routes must be declared in order
• /admin and /admin/login are used to render Scala view templates
• /admin/*any will be intercepted by client-side routing in AngularJS
• Client-side routes may hit the server if the URI has been bookmarked
• Nothing special about web services aside from payload (JSON vs HTML)
21. Sample controller action
21
/**!
* Renders the admin template.!
*/!
def index = Action.async {!
implicit request =>!
val account = loggedIn!
Ok(views.html.admin()).withCookies(Cookie(“…”, …, httpOnly = false))!
}
• Controllers should stay thin and delegate the real work
• Controllers actions should always be async
• Controllers are stateless so context must be stored in cookies or cached
22. Asynchronous vs synchronous processing times
22
Asynchronous - 200ms
Process 1
Process 2
75 ms
Process 3
200 ms
150 ms
0 ms 425 ms
Synchronous - 425ms
Process 1 Process 2 Process 3
0 ms 425 ms
• Staying async — and in the future —
ensures that processing time is not
bounded by IO
• Async processing is limited by only
the longest running process
• Synchronous processing is limited by
the combined processing times
• Stay async!
24. An intro to sbt-web
24
• sbt-web brings the notion of a highly configurable asset pipeline to build files
pipelineStages := Seq(rjs, digest, gzip)!
• The above will order the RequireJs optimizer (sbt-rjs), the digester (sbt-digest) and
then compression (sbt-gzip)
• These tasks will execute in the order declared, one after the other
26. Asset pipelines
26
• Linting
• Inspect source code for suspicious language usage
• Uglification/minification
• Mangle and compress source files, e.g, remove whitespace, etc
• Fingerprinting
• Change the filename to reflect the contents of the file for cache busting
• Concatenation
• Combine multiple source files to reduce browser load times
27. sbt-web and asset fingerprinting
27
• Asset fingerprinting makes the name of a file dependent on the contents of the file
• HTTP headers can be set to encourage caches to keep their own copy of the content
• When the content is updated, the fingerprint will change
• This will cause the remote clients to request a new copy of the content
• Known as cache busting
28. Turning on asset fingerprinting
28
• Turning on asset fingerprinting only requires one additional route
GET /assets/*file! controllers.Assets.versioned(path="/public", file: Asset)
• Then request each asset as versioned
<link rel="stylesheet" href=“@routes.Assets.versioned('assets/images/example.png')">
• A digest file and new file will be created based on MD5
./target/web/digest/images/23dcc403b263f262692ac58437104acf-example.png!
./target/web/digest/images/example.png.md5
31. Model-tier considerations
31
Think in verbs rather than nouns…
• save(model)
• SRP — save is likely a simple function that does a single thing
• model.save()
• Violates SRP — tougher to test
• Play makes it easy to implement your preferred solution to persistence
• CRUD, CQRS (Command Query Responsibility Segregation), etc
32. Scala — Slick example
32
// This code:!
coffees.filter(_.price < 10.0).map(_.name)!
!
// Will produce a query equivalent to the following SQL:!
select COF_NAME from COFFEES where PRICE < 10.0
• Slick is a Functional Relational Mapping (FRM) library for Scala where you work with
relational data in a type-safe and functional way
• Developers benefit from the type-safety and composability of FRM as well as being
able to reuse the typical Scala collection APIs like filter, map, foreach, etc
• Can also use plain SQL for insertions, complex joins, etc
• http://typesafe.com/activator/template/hello-slick-2.1
33. Scala — JSON Writes example
33
• Simply define a Writes in
implicit scope before invoking
toJson
implicit val locationWrites = new Writes[Location] {!
def writes(location: Location) = Json.obj(!
"lat" -> location.lat,!
"long" -> location.long!
)!
}!
!
val json = Json.toJson(location)
34. Scala — JSON Reads example
• Also elegantly handles Reads
• Build in validate using standard
types (e.g, Double, Int, etc) or
define your own validators
34
implicit val locationReads: Reads[Location] = (!
(JsPath "lat").read[Double] and!
(JsPath "long").read[Double]!
)(Location.apply _)!
!
val json = { ... }!
!
val locationResult: JsResult[Location] = !
! json.validate[Location]
36. “If you want to parallelize a very deterministic algorithm, futures are the
way to go.”
- Derek Wyatt, Akka Concurrency
37. Futures
37
def index = Action.async {!
! val futureInt = scala.concurrent.Future { intensiveComputation() }!
! futureInt.map(i => Ok("Got result: " + i))!
}
• Great for handling immutable state
• Intensive computations, reading from a database, pulling from web services, etc
• Composition — futures guarantee order when chained
• Parallelizing a deterministic algorithm
38. “Add behaviour to an algorithm by inserting actors into the message
flow.”
- Derek Wyatt, Akka Concurrency
39. Actors
• Great for handling mutable state
• Easy for imperative developers to dive
into quickly
• Don't guarantee order
• Easy to change behaviour by inserting
new actors into the message flow
• Messages are directed to a specific actor,
avoiding callback hell
39
package actors!
!
import akka.actor._!
!
object SomeActor {!
! def props = Props(new GameActor)!
}!
!
class SomeActor extends Actor {!
! def receive = {!
! ! case request: SomeRequest => {!
! ! ! sender ! SomeResponse(...) !
! ! }!
! }!
}!
40. WebSockets
def websocketAction = WebSocket.acceptWithActor[JsValue, JsValue] { request => channel =>!
! SomeActor.props(channel)!
}!
40
• Play provides two different built in mechanisms for handling WebSockets
• Actors — better for discreet messages
• Iteratees — better for streams
• Both of these mechanisms can be accessed using the builders provided on WebSocket
42. Test framework comparison
42
• ScalaTest
• Human readable output — in English
• FeatureSpec
• Matchers
• http://www.artima.com/docs-scalatest-2.0.M8/#org.scalatest.Matchers
• Great writeup by Gilt
• http://tech.gilt.com/post/62430610230/which-scala-testing-tools-should-you-use
43. Test framework comparison
43
• Specs2
• Enabled by default in Play
• Good choice for international teams who gain less from English readability
• Both Specs2 and ScalaTest are fantastic!
45. Play 2.4
45
• Built-in dependency injection support
• Experimental support for running Play on akka-http
• Experimental support for handling IO in Java and Scala using Reactive Streams
• Slick over anorm, JPA over ebean
• Pull anorm/ebean support out into separate modules in GitHub playframework repo