Upload
kevin-webber
View
833
Download
3
Tags:
Embed Size (px)
DESCRIPTION
A deep-dive into the core features of the Typesafe Activator and Play Framework.
Citation preview
Play Framework and ActivatorGetting started with the Play Framework with Activator
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?
Introduction to Typesafe Activator
“Typesafe Activator is a browser-based or command-line tool that helps developers get started with the Typesafe Reactive Platform.”
Getting started with the Typesafe Activator UI
5
• Download Typesafe Activator
• https://typesafe.com/platform/getstarted
• Optional (Mac)
• ~ $ rm -R .sbt
• ~ $ rm -R .ivy
• Unarchive and execute (Mac)
• $ ./activator ui
Activator tutorials and seeds
6
Activator Overview
7
• Learn — In depth tutorials
• Develop — Code, compile, test, run, inspect
• Deliver — Monitoring integration with AppDynamics and New Relic
Code view
8
• Activator • Browse code
• Make small changes • IDE
• Generate IDEA or Eclipse project files
• Dig into the template in your favourite IDE
Development monitoring
9
• Incoming requests • Controller • HTTP verb (GET, POST, etc)
• Response code
• Invocation time
Inspect — Development monitoring
10
• Actor metrics • Throughput — messages/s
• Max time — high watermark
• Max size — mailbox
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
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
The Typesafe Activator UI is a Play framework application. !
Peek behind the covers… !
https://github.com/typesafehub/activator/tree/master/ui
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
Play application overview
15
View
Controller
ModelJSON
Slick JPA WS
DB
Akka
Network
Creating your first view
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
HTML for views.html.admin(...)
Browser Play
CDN
HTTP GET (mydomain.com/admin/settings)
JS, CSS, images, etc
HTTP GET (mydomain.com/ws/some/services)
JSON
Example template with AngularJS
18
• Scala template rendered by Twirl and returned by Play controller
• HTML inserted into ng-view by Angular controller after initial page render
@(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>
HeaderPlay handles navigation
Footer
load async || fail whale
load async || omit
AngularJS
Creating your first routes and controllers
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)
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
Asynchronous vs synchronous processing times
22
Process 1
Process 2
Process 3
0 ms 425 ms
200 ms
75 ms
150 ms
Asynchronous - 200ms
Process 1 Process 2 Process 3
0 ms 425 ms
Synchronous - 425ms
• 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!
Asset pipeline and sbt-web
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
Asset pipelines
25
• Example asset pipeline
• source file →
• step 1: linting →
• step 2: uglification/minification →
• step 3: fingerprinting →
• step 4: concatenation (optional)
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
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
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
sbt-web plugins
29
• sbt-coffeescript
• sbt-concat
• sbt-css-compress
• sbt-digest
• sbt-filter
• sbt-gzip
• sbt-handlebars
• sbt-html-minifier
• sbt-imagemin
• sbt-jshint
• sbt-jst
• sbt-less
• sbt-mocha
• sbt-purescript
• sbt-reactjs
• sbt-rjs
• sbt-stylus
• sbt-uglify
Model-tier and data access
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
Scala — Slick example
32
• 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
// 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
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)
Scala — JSON Reads example
34
• Also elegantly handles Reads • Build in validate using standard
types (e.g, Double, Int, etc) or define your own validators
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]
Futures, Actors, and WebSockets
- Derek Wyatt, Akka Concurrency
“If you want to parallelize a very deterministic algorithm, futures are the way to go.”
Futures
37
• 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
def index = Action.async {!! val futureInt = scala.concurrent.Future { intensiveComputation() }!! futureInt.map(i => Ok("Got result: " + i))!}
- Derek Wyatt, Akka Concurrency
“Add behaviour to an algorithm by inserting actors into the message flow.”
Actors
39
• 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
package actors!!import akka.actor._!!object SomeActor {!! def props = Props(new GameActor)!}!!class SomeActor extends Actor {!! def receive = {!! ! case request: SomeRequest => {!! ! ! sender ! SomeResponse(...) !! ! }!! }!}!
WebSockets
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
def websocketAction = WebSocket.acceptWithActor[JsValue, JsValue] { request => channel =>!! SomeActor.props(channel)!}!
Testing
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
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!
Coming soon to Play 2.4
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
Questions?
©Typesafe 2014 – All Rights Reserved