PLAY IN PRACTICE/Will Sargent @will_sargent
PREAMBLE
This is going to be a broad talk.
USAGE
This talk does not attempt to be universal to all situations.
YMMV.
WHAT IS PLAY?
Play is a web application framework.
THESIS STATEMENT
Play is awesome.
WHY PLAY IS AWESOME?
Because Play is Simple.
HERE'S WHAT PLAY DOES:
Takes in an HTTP request.
Returns (or streams) a response.
HERE'S WHAT PLAY DOESN'T DO:
It doesn't tie an HTTP request to a thread.
It doesn't tie an HTTP session to memory.
It doesn't assume you want convenient but unsafe
practices.
It doesn't mandate a particular object relational
framework.
It doesn't mandate a particular template library.
It doesn't mandate a particular routing format.
HERE'S WHAT PLAY PROVIDES AS OPTIONS:
"Always-on" Build System
HTTP API
Templates
Form Handling
JSON support
BUILD SYSTEM
Modified SBT, recompiles pages on the fly in development
mode.
Type "play idea" or "play eclipse" to generate the files for
your IDE.
FRONT CONTROLLER
Routing API (with LangPathBindable and
QueryStringBindable)
Action: asynchronous and stateless by default.
Immutable HTTP: cookies, request, response, headers, etc.
Backed by Akka and Netty.
PRESENTATION
Compiled template language (Twirl, Scaml, Jade).
Built-in helpers for rendering forms.
Support for Twitter Bootstrap, LESS, jQuery, etc.
JSON
Formatting to JSON
Parsing of JSON objects
JsPath, automatic validation, read and write combinators
SO, WHY DOES THIS MATTER?
THE BUSINESS REQUEST
Make a website!
MAKE TWO WEBSITES!
Product
Admin
MAKE MORE WEBSITES!
Product
Admin
Customer Service
Business Analytics
Business Content
Jobs Queue
THE PROBLEM
In a complex web application, many different front ends need
to look at the same data, from different angles.
Touching the database directly is dangerous and messy.
THE SOLUTION
In complex applications, use loosely coupled, stateless,
composable services.
HOW?
Create a Play HTTP front end, backed by Akka.
Create a business domain services, backed by Akka.
Use Akka to pass messages between Play and the domain
services.
Present information using query services.
ALAN KAY ON OOP
“ I thought of objects being like biological cells
and/or individual computers on a network,
only able to communicate with messages (so
messaging came at the very beginning -- it
took a while to see how to do messaging in a
programming language efficiently enough to
be useful). ”
COMMAND / QUERY RESPONSIBILITY
SEGREGATION (CQRS)
Command: a message intending a change of state.
Event: a message indicating that state has changed.
Fault: a message indicating failure to execute a command.
CQRS MAPPED ONTO PLAY
Processing Commands using POST
Querying for Data with GET
Broadcasting Events with Streaming
PROCESSING COMMANDS
Validate all input.
where possible.
Be very careful when handling passwords and credit card
numbers.
Use value classes
COMMANDS
def sendCommand(command : Command) : Future[Either[Fault,Event]]
CQRS
COMMAND
trait Command extends Product
sealed abstract class AuthenticationCommand extends Command
case class AuthenticateWithPasswordCommand(email:Email,
password:String,
rememberMe:Boolean)
extends AuthenticationCommand {
override def toString = "AuthenticateWithPasswordCommand("
+ email + "," + rememberMe + ")"
}
EVENT
case class UserAuthenticatedEvent(userId: UserID,
series: Option[Long] = None,
token: Option[Long] = None)
extends AuthenticationEvent
FAULT
trait AuthenticationFault
case class InvalidSessionCookieFault() extends AuthenticationFault
QUERY
case class UserInfo(id: UUID, email: Email, fullName: String)
class UserInfoService {
def lookup(uuid: UUID)(implicit c:Credentials): Option[UserInfo]
def findByName(name: String)(implicit c:Credentials) : TraversableOnce[UserIn
}
QUERY PRACTICES:
Objects should be immutable
Return ranges or streams over unbounded lists.
Don't expose repository logic (i.e. HQL, CQL, etc)
Making a good query builder is hard; avoid yak shaving.
CONTEXT AND AUTHENTICATION
Use or to set up a
WrappedRequest context.
Pass the request context around implicitly in every
template.
The request context will contain all the state you need (i.e.
Credentials).
Make helpers take the context as an implicit as needed.
Sidenote: helpers are great for keeping logic out of
templates.
play2-rememberme SecureSocial
EXAMPLE TEMPLATE
@(u: UserInfo)(implicit ctx: Context)
@layout(title = "User Page") {
@ctx.me.map { u =>
<p>
This is your user page.
</p>
}
<p>
User page of @{u.fullName}.
</p>
}
STREAMING
You send an event.
Event goes through an Iteratee.
Iteratee broadcasts event using Socket and Hub model.
Play uses Server Sent Events to stream JSON to clients
Javascript picks up that JSON from SSE, handles display.
is the best reference.
Sidenote: also check out
lila
vert.x
EVERYTHING ELSE
Logging
Metrics
Testing
LOGGING
Play's internal logger isn't the greatest.
Fortunately, it's not hardcoded and you can ignore it.
Make your own wrapper over SF4LJ & Logback (or
grizzled, or typesafe logging).
METRICS
has a Scala option.
Map it through Global's onRequest method.
Metrics
TESTING
Unit testing a stateless app is very easy.
Swapping out services with mocks/stubs may be easier
with DI (I use Subcut).
Functional and integration testing with FakeRequest and
Fluentlenium almost painless.
LOAD TESTING
Use jconsole and .
Don't know how useful Typesafe Console is.
Apache JMeter
QUESTIONS?
There's an award!

Play in practice

  • 1.
    PLAY IN PRACTICE/WillSargent @will_sargent
  • 2.
    PREAMBLE This is goingto be a broad talk.
  • 3.
    USAGE This talk doesnot attempt to be universal to all situations. YMMV.
  • 4.
    WHAT IS PLAY? Playis a web application framework.
  • 5.
  • 6.
    WHY PLAY ISAWESOME? Because Play is Simple.
  • 7.
    HERE'S WHAT PLAYDOES: Takes in an HTTP request. Returns (or streams) a response.
  • 8.
    HERE'S WHAT PLAYDOESN'T DO: It doesn't tie an HTTP request to a thread. It doesn't tie an HTTP session to memory. It doesn't assume you want convenient but unsafe practices. It doesn't mandate a particular object relational framework. It doesn't mandate a particular template library. It doesn't mandate a particular routing format.
  • 9.
    HERE'S WHAT PLAYPROVIDES AS OPTIONS: "Always-on" Build System HTTP API Templates Form Handling JSON support
  • 10.
    BUILD SYSTEM Modified SBT,recompiles pages on the fly in development mode. Type "play idea" or "play eclipse" to generate the files for your IDE.
  • 11.
    FRONT CONTROLLER Routing API(with LangPathBindable and QueryStringBindable) Action: asynchronous and stateless by default. Immutable HTTP: cookies, request, response, headers, etc. Backed by Akka and Netty.
  • 12.
    PRESENTATION Compiled template language(Twirl, Scaml, Jade). Built-in helpers for rendering forms. Support for Twitter Bootstrap, LESS, jQuery, etc.
  • 13.
    JSON Formatting to JSON Parsingof JSON objects JsPath, automatic validation, read and write combinators
  • 14.
    SO, WHY DOESTHIS MATTER?
  • 15.
  • 16.
  • 17.
    MAKE MORE WEBSITES! Product Admin CustomerService Business Analytics Business Content Jobs Queue
  • 18.
    THE PROBLEM In acomplex web application, many different front ends need to look at the same data, from different angles. Touching the database directly is dangerous and messy.
  • 19.
    THE SOLUTION In complexapplications, use loosely coupled, stateless, composable services.
  • 20.
    HOW? Create a PlayHTTP front end, backed by Akka. Create a business domain services, backed by Akka. Use Akka to pass messages between Play and the domain services. Present information using query services.
  • 21.
    ALAN KAY ONOOP “ I thought of objects being like biological cells and/or individual computers on a network, only able to communicate with messages (so messaging came at the very beginning -- it took a while to see how to do messaging in a programming language efficiently enough to be useful). ”
  • 22.
    COMMAND / QUERYRESPONSIBILITY SEGREGATION (CQRS) Command: a message intending a change of state. Event: a message indicating that state has changed. Fault: a message indicating failure to execute a command.
  • 23.
    CQRS MAPPED ONTOPLAY Processing Commands using POST Querying for Data with GET Broadcasting Events with Streaming
  • 24.
    PROCESSING COMMANDS Validate allinput. where possible. Be very careful when handling passwords and credit card numbers. Use value classes
  • 25.
    COMMANDS def sendCommand(command :Command) : Future[Either[Fault,Event]]
  • 26.
  • 27.
    COMMAND trait Command extendsProduct sealed abstract class AuthenticationCommand extends Command case class AuthenticateWithPasswordCommand(email:Email, password:String, rememberMe:Boolean) extends AuthenticationCommand { override def toString = "AuthenticateWithPasswordCommand(" + email + "," + rememberMe + ")" }
  • 28.
    EVENT case class UserAuthenticatedEvent(userId:UserID, series: Option[Long] = None, token: Option[Long] = None) extends AuthenticationEvent
  • 29.
    FAULT trait AuthenticationFault case classInvalidSessionCookieFault() extends AuthenticationFault
  • 30.
    QUERY case class UserInfo(id:UUID, email: Email, fullName: String) class UserInfoService { def lookup(uuid: UUID)(implicit c:Credentials): Option[UserInfo] def findByName(name: String)(implicit c:Credentials) : TraversableOnce[UserIn }
  • 31.
    QUERY PRACTICES: Objects shouldbe immutable Return ranges or streams over unbounded lists. Don't expose repository logic (i.e. HQL, CQL, etc) Making a good query builder is hard; avoid yak shaving.
  • 32.
    CONTEXT AND AUTHENTICATION Useor to set up a WrappedRequest context. Pass the request context around implicitly in every template. The request context will contain all the state you need (i.e. Credentials). Make helpers take the context as an implicit as needed. Sidenote: helpers are great for keeping logic out of templates. play2-rememberme SecureSocial
  • 33.
    EXAMPLE TEMPLATE @(u: UserInfo)(implicitctx: Context) @layout(title = "User Page") { @ctx.me.map { u => <p> This is your user page. </p> } <p> User page of @{u.fullName}. </p> }
  • 34.
    STREAMING You send anevent. Event goes through an Iteratee. Iteratee broadcasts event using Socket and Hub model. Play uses Server Sent Events to stream JSON to clients Javascript picks up that JSON from SSE, handles display. is the best reference. Sidenote: also check out lila vert.x
  • 35.
  • 36.
    LOGGING Play's internal loggerisn't the greatest. Fortunately, it's not hardcoded and you can ignore it. Make your own wrapper over SF4LJ & Logback (or grizzled, or typesafe logging).
  • 37.
    METRICS has a Scalaoption. Map it through Global's onRequest method. Metrics
  • 38.
    TESTING Unit testing astateless app is very easy. Swapping out services with mocks/stubs may be easier with DI (I use Subcut). Functional and integration testing with FakeRequest and Fluentlenium almost painless.
  • 39.
    LOAD TESTING Use jconsoleand . Don't know how useful Typesafe Console is. Apache JMeter
  • 40.