• Save
Play framework 2 : Peter Hilton
Upcoming SlideShare
Loading in...5

Play framework 2 : Peter Hilton



This presentation introduces the key innovations that Play 2 brings to web application development in Java and Scala. The Play framework has brought high-productivity web development to Java with ...

This presentation introduces the key innovations that Play 2 brings to web application development in Java and Scala. The Play framework has brought high-productivity web development to Java with three innovations that changed the rules on Java EE: Java class and template save-and-reload that just works, a simplified stateless architecture that enables cloud deployment, and superior ease-of-use. Following Play's rapidly-growing popularity, Play 2.0 was released in March 2012 with innovations that are not just new in the Java world: type-safe view templates and HTTP routing, compile-time checking for static resources, and native support for both Java and Scala. Type safety matters. After dynamically-typed programming languages such as PHP and Ruby set the standard for high-productivity web development, Play built on their advantages and has created a type-safe web development framework with extensive compile-time checking. This is essential for applications that will scale to tens of thousands of lines of code, with hundreds of view templates. Meanwhile, Play avoids the architectural-complexity that is promoted by Java EE-based approaches. The result is that Play 2 first enables rapid initial application development and then Play 2 helps you build big, serious and scalable web applications.



Total Views
Views on SlideShare
Embed Views



1 Embed 22

http://lanyrd.com 22



Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
Post Comment
Edit your comment

Play framework 2 : Peter Hilton Play framework 2 : Peter Hilton Presentation Transcript

  • Play  framework  2@PeterHilton  at  #JAXLondon  on  17  October  2012
  • 2Peter  Hilton■ (sorry, I am not Guillaume Bort)■ Web developer and Operations Director at Lunatech Research in Rotterdam ■ Web application architecture, design and construction ■ Technical project management and functional design■ Play framework committer since 2010■ Co-author of the book Play for Scala (Manning)
  • 3About  Lunatech■ Founded  in  Ro*erdam  in  1993  as  an  IT  consul6ng,  product   research  and  development  team■ We  build  web  applica6ons,  web  services,  large-­‐scale  document-­‐ processing  and  message-­‐processing  applica6ons,  online  products■ Leverage  cuBng-­‐edge  open-­‐source  soCware  plaDorms■ Invest  in  product  research  and  development■ Play  framework;  Java  EE  -­‐  JBoss  AS,  Seam,  JPA,  jBPM,  Drools;   back-­‐end  -­‐  PostgreSQL,  Linux;  front-­‐end  -­‐  jQuery,  Backbone,  _.js■ Agile  soCware  development  -­‐  self-­‐managing  technical  teams
  • 4“ Play  introduces  high-­‐produc6vity   type  safe  web  development Presenta6on  goal:  show  you  how  cool  Play  is
  • 5Outline■ What Play is and why it matters (web architecture)■ High-productivity web development (but for Java and Scala developers)■ Developer Experience (DX) that doesn’t suck■ Type safe compile-time checked web development■ HTML5 front-end development
  • 6What  Play  is■ Full-stack web framework (what you need to build an app)■ Simple, flexible and powerful HTTP interface■ High-productivity web development■ High-performance scalable architecture■ Designed by web developers for web developers■ Play is fun
  • h&p://www.flickr.com/photos/roninsfx/5568957616/
  • h&p://www.flickr.com/photos/deerwooduk/579761138/
  • 9“ What  is  the  focal-­‐point  of  web   applica6on  architecture?
  • 10“ It’s  the  web  browser,  stupid
  • 11Why  Play  maCersThe  Back  bu*on  worksPlay’s  stateless  architecture  is  based  on  HTTP.  When  a  web  framework  starts  an  architecture  fight  with  the  web,  the  framework  loses.
  • 12Why  Play  maCers Back   The  Reload  bu*on  works bu*on During   development,   just   reload   the   page   to  see  changes  in  your  Java  (or  Scala)  code. That’s  high-­‐produc6vity  web  development.
  • 13Why  Play  maCers Back   You  design  the  URL Reload   bu*on bu*on You  can  use  ‘clean’  URLs: /products /product/42 /product/42/comments
  • 14Why  Play  maCers Back   Usability  (DX) URL Reload   bu*on bu*on Convenient  HTTP  API   and  template  syntax Clear  error  messages   and  short  stack  traces
  • 15“ What’s  the  story  behind  the  heart  icon?“ There  isn’t  one. Feel  free  to  make  one  up  :) Guillaume  Bort
  • 16“ Play  doesn’t  fight  web  architecture Stateless,  HTTP-­‐centric  architecture…
  • 18Stateless  architecture■ No state in the application’s web tier ■ e.g. Java Servlet API’s HTTP session (which isn’t actually part of HTTP)■ State belongs in other tiers ■ HTTP client, server cache or database■ Web application behaviour defined by URLs (requests)■ Exception for identifying authenticated user by cookie
  • 19Stateless  architecture  -­‐  why■ Simplifies application development and testing ■ (a URL is all you need for reproducability)■ Matches the web’s stateless HTTP architecture■ Avoids synchronising state between additional layers ■ (‘synchronisation’ should ring tech design alarm bells)■ Enables cloud deployment and horizontal scalability ■ (search the web for “Play framework Heroku”)
  • www.12factor.net
  • 21“ Dear  Java  devs,  PHP  and  Rails  devs   have  been  laughing  at  you  for  years …  every  6me  they  reload  a  page’s  code  changes
  • 22Code  reloading■ During development, reload the page to see changes in: ■ Java and Scala classes ■ configuration files ■ templates.■ Play pre-compiles classes and templates for better performance in production mode■ This just works out-of-the-box
  • 23“ URLs  want  to  be  loved  too REST  architecture  isn’t  just  for  web  service  APIs
  • 24h  t  t  p  :  /    a  p  p  .  e    a  m  p  l  e  .  c  o  m  /  W    r    o  o  t  D    r     / x a R i ec  t  o  r    1  /    e      l  e    s      A    l  a    e    s    s  s    o  n  I  d  =  x  8   y S rv t On P n ? e i1  n  j  3  8  a  v    g    L  O  L  d  x  p  a    e  w  q  &  a  c  t  i  o  n  =  N  e  x  t   n j nP  a  g    &  H    n  e    B  a  d    e  r      r    s  =    a  l  s  e    e  n  t    t  y   e o y g Ca e f & iI  d    1  2  9  9  1  2  7  4  3  &  p  r  o  c  e  s  s  N    m  e  =    n  l  a  d  e  n   = a US  w  a  l  l  o  w  C  o  m  p  u  t  a  t  i  o  n  &  r  o  l  e  =  p  e  o  n  &  d  a  t  e  =  1  4  %  2  F    2  %  2  F  2  0  1  2  &  f  l    g    e    t  i  n  g    =  0  1  0   0 a S t s1  0  1  1  &  r  e  t  u  r  n  =  %  2  F  v  i  d  e  o  s  %  2  F  r  i  c  k  r  o  l  l  .  a  v  i
  • h&p://www.flickr.com/photos/shyroii/4817446191/
  • 26URL  design  (HTTP  rouMng)■ Clean URLs are stable URLs: ■ http://example.com/products ■ http://example.com/product/42■ Read it, bookmark it, mail it, tweet it■ URL-centric design: ■ Design the URL scheme before you start coding ■ Configure your application’s URLs in one file
  • 27URL  design  (HTTP  rouMng)■ Designed URLs are clean URLs: ■ http://example.com/products ■ http://example.com/product/42■ Corresponding Play routing configuration: #  HTTP  routes  configuration  file #  method,  URL  path,  controller  action  method  (and  params) GET    /products            controllers.Products.list() GET    /product/:id      controllers.Products.details(id:Long)
  • 28#  HTTP  routes  configuraMon  fileGET        /                            controllers.Application.index()GET        /products            controllers.Products.list()POST      /products            controllers.Products.add(p:  Product)GET        /product/:id      controllers.Products.details(id:  Long)DELETE  /product/:id      controllers.Products.delete(id:  Long)GET  /products.json        controllers.Products.listJSON()GET  /product/:id.json  controllers.Products.detailsJSON(id:Long)
  • 29“ You  have  to  be  a  genius  to  successfully   use  some  web  frameworks For  the  rest  of  us,  there  are  good  error  messages
  • 30
  • 31Where’s  the  actual  error  message?13:07:55,796  ERROR  [[PersonServlet]]  Servlet.service()  for  servlet  PersonServlet  threw  exceptionjavax.ejb.EJBException:  null;  CausedByException  is:   null   at  org.jboss.ejb3.tx.Ejb3TxPolicy.handleExceptionInOurTx(Ejb3TxPolicy.java:46)   at  org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPolicy.java:70)   at  org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java:134)   at  org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:98)   at  org.jboss.aspects.tx.TxPropagationInterceptor.invoke(TxPropagationInterceptor.java:61)   at  org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:98)   at  org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(StatelessInstanceInterceptor.java:39)   at  org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:98)   at  org.jboss.aspects.security.AuthenticationInterceptor.invoke(AuthenticationInterceptor.java:63)   at  org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:98)   at  org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterceptor.java:32)   at  org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:98)   at  org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(AsynchronousInterceptor.java:91)   at  org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:98)   at  org.jboss.ejb3.stateless.StatelessContainer.dynamicInvoke(StatelessContainer.java:189)   at  org.jboss.aop.Dispatcher.invoke(Dispatcher.java:107)   at  org.jboss.ejb3.remoting.IsLocalInterceptor.invoke(IsLocalInterceptor.java:37)   at  org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:98)   at  org.jboss.ejb3.stateless.StatelessRemoteProxy.invoke(StatelessRemoteProxy.java:88)   at  $Proxy76.getAllPeople(Unknown  Source)   at  uk.co.mediaport.web.PersonServlet.showTelephones(PersonServlet.java:54)   at  uk.co.mediaport.web.PersonServlet.doPost(PersonServlet.java:45)   at  uk.co.mediaport.web.PersonServlet.doGet(PersonServlet.java:34)   at  javax.servlet.http.HttpServlet.service(HttpServlet.java:697)   at  javax.servlet.http.HttpServlet.service(HttpServlet.java:810)   at  org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)   at  org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)   at  org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:81)   at  org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)   at  org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)   at  org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)   at  org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)   at  org.jboss.web.tomcat.security.CustomPrincipalValve.invoke(CustomPrincipalValve.java:39)   at  org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:159)   at  org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:59)   at  org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)   at  org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)   at  org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)   at  org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)   at  org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:856)
  •   at  org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:744)   at  org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)   at  org.apache.tomcat.util.net.MasterSlaveWorkerThread.run(MasterSlaveWorkerThread.java:112) 32   at  java.lang.Thread.run(Thread.java:595)   java.lang.NullPointerException   at  uk.co.mediaport.core.PeopleBean.getAllPeople(PeopleBean.java:33)   at  sun.reflect.NativeMethodAccessorImpl.invoke0(Native  Method)   at  sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)   at  sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)   at  java.lang.reflect.Method.invoke(Method.java:585)   at  org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:109)   at  org.jboss.ejb3.AllowedOperationsInterceptor.invoke(AllowedOperationsInterceptor.java:32)   at  org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:98)   at  org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPolicy.java:66)   at  org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java:134)   at  org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:98)   at  org.jboss.aspects.tx.TxPropagationInterceptor.invoke(TxPropagationInterceptor.java:61)   at  org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:98)   at  org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(StatelessInstanceInterceptor.java:39)   at  org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:98)   at  org.jboss.aspects.security.AuthenticationInterceptor.invoke(AuthenticationInterceptor.java:63)   at  org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:98)   at  org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterceptor.java:32)   at  org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:98)   at  org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(AsynchronousInterceptor.java:91)   at  org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:98)   at  org.jboss.ejb3.stateless.StatelessContainer.dynamicInvoke(StatelessContainer.java:189)   at  org.jboss.aop.Dispatcher.invoke(Dispatcher.java:107)   at  org.jboss.ejb3.remoting.IsLocalInterceptor.invoke(IsLocalInterceptor.java:37)   at  org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:98)   at  org.jboss.ejb3.stateless.StatelessRemoteProxy.invoke(StatelessRemoteProxy.java:88)   at  $Proxy76.getAllPeople(Unknown  Source)   at  uk.co.mediaport.web.PersonServlet.showTelephones(PersonServlet.java:54)   at  uk.co.mediaport.web.PersonServlet.doPost(PersonServlet.java:45)   at  uk.co.mediaport.web.PersonServlet.doGet(PersonServlet.java:34)   at  javax.servlet.http.HttpServlet.service(HttpServlet.java:697)   at  javax.servlet.http.HttpServlet.service(HttpServlet.java:810)   at  org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)   at  org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)   at  org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:81)   at  org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)   at  org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)   at  org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)   at  org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)   at  org.jboss.web.tomcat.security.CustomPrincipalValve.invoke(CustomPrincipalValve.java:39)   at  org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:159)   at  org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:59)   at  org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)   at  org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)   at  org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)   at  org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
  • http://localhost/ 33Parse error: syntax error, unexpected T_VARIABLEin /usr/local/www/htdocs/index.php on line 3
  • 35“ Play  2  con6nues  the  innova6on First-­‐class  support  for  both  Java  and  Scala Type-­‐safe  templates Compile-­‐6me  checking Asynchronous  HTTP  programming
  • h&p://www.flickr.com/photos/anoldent/3642351368
  • 37Play  in  Java  and  Scala■ Play 2.0 provides parallel APIs for Java and Scala, for example, a controller action: //  Java  controller  action  method public  static  Result  index(String  name)  {    return  ok("Hello"  +  name); } //  Scala  controller  action  method def  hello(name:  String)  =  Action  {    Ok("Hello  "  +  name) }
  • 38Play  2.0  Scala  implementaMon■ Play 2.0 is itself implemented in Scala■ Scala removes the need for so much bytecode enhancement in the Java API (which is how Play 1.x works) ■ There is less ‘magic’ and strangeness in the API ■ The code you see in the IDE is the code that runs■ Scala source code not necessarily harder to read
  • 39“ Templates  want  to  be  beau6ful  too Type  safe  template  parameter  delcara6ons Minimal  interference  with  HTML  mark-­‐up
  • 40Type-­‐safe  template  parameters■ Templates include type-safe parameter declarations■ Similar to the lightweight template syntax in Play 1.x■ Templates are compiled into class files for run-time speed @(products:  List[Product]) <ul>   @for(product  <-­‐  products)  {    <li  class="@product.type">@product.name</li> }   </ul>
  • 41Template  funcMons■ Play 2.0’s template system is based on Scala■ A template is a Scala function that you call from your code //  Render  the  ‘Products.list’  template  in  Java  code. Html  html  =  views.html.Products.list.render(products); //  e.g.  as  the  result  of  a  controller  action  method. public  static  Result  list()  {    final  List<Product>  products  =  Products.list();    return  ok(views.html.Products.list.render(products)); }
  • Template syntax starts with @ 42 Template parameter declaration@(products:  List[Product])@if(products.isEmpty)  {    <h1>No  products</h1>} No delimiter for the end of a template syntax section
  • 43@(products:  List[Product])@if(products.isEmpty)  {    <h1>No  products</h1>}  else  {    <h1>@items.size  products</h1>} Output the value of an expression
  • 44 Define a ‘tag’ - output a details page link@display(product:  models.Product)  =  {    <a  href="@routes.Products.details(product.id)">        @product.name    </a>}<ul>@for(product  <-­‐  products)  {    @display(product)}  </ul> Use the ‘display’ tag
  • 45<section  class="content">    …</section>@footer() Include the ‘footer’ template (i.e. call the ‘footer’ function)
  • main.scala.html 46@(title:  String)(content:  Html)<!DOCTYPE  html><html> Two parameter lists    <head> (one parameter each)        <title>@title</title>    </head>    <body>        @content    </body> Define a page layout</html> template called ‘main’ index.scala.html@main("Home  page")  { Render the ‘main’ template,    <h1>Welcome</h1> passing two parameters}
  • 47“ Dear  PHP  and  Rails  developers,   run6me  errors  make  you  look  bad Using  unit  tests  to  find  syntax  errors  is  a  hack There  is  a  solu6on…
  • 48
  • 49Compile-­‐Mme  checking■ Not just Java and Scala classes ■ HTTP routes file (maps URLs to controller actions) ■ Templates ■ JavaScript files (using Google Closure Compiler) ■ CoffeeScript files (alternative to JavaScript) ■ LESS style sheets (alternative to CSS)■ Fewer errors at run-time
  • controllers/Products.java 50public  class  Products  extends  Controller  {    public  static  Result  details(final  Long  id)  {        return  ok();    }} conf/routesGET  /product/:id      controllers.Products.details(id:  String)
  • controllers/Products.java 50public  class  Products  extends  Controller  {    public  static  Result  details(final  Long  id)  {        return  ok();    }} Incompatible types conf/routesGET  /product/:id      controllers.Products.details(id:  String)
  • controllers/Products.java 50public  class  Products  extends  Controller  {    public  static  Result  details(final  Long  id)  {        return  ok();    }} Incompatible types conf/routesGET  /product/:id      controllers.Products.details(id:  String)
  • h&p://www.flickr.com/photos/jameswragg/4688532009/
  • @rainbow:  -­‐webkit-­‐gradient(linear,  left  top,  left  bottom,    color-­‐stop(0.00,  red),    color-­‐stop(20%,  orange),    color-­‐stop(25%,  yellow),    color-­‐stop(30%,  yellow),    color-­‐stop(45%,  green),    color-­‐stop(65%,  blue),    color-­‐stop(80%,  indigo),    color-­‐stop(1.00,  violet));
  • 57“ Use  HTML5  technologies Choose  a  web  framework  that  lets  you Hire  or  become  a  front-­‐end  expert Use  HTML  ‘bricks’  instead  of  moulded  components
  • 59
  • 60Modern  web  development■ Play is designed to work with HTML5 technologies■ No constraints on HTML output (front-end dev-friendly)■ UI components belong in the client, e.g. JQuery UI■ Built-in support for improvements to CSS and JavaScript: ■ LESS http://lesscss.org/ ■ CoffeeScript http://coffeescript.org/ ■ Closure Compiler http://code.google.com/closure/compiler
  • 61Single-­‐page  JavaScript  applicaMons■ Server-side HTML templates are not the only game in town■ JavaScript and mobile apps need web services■ Play is great for building web services ■ You’ve already seen HTTP routing ■ Play has a type safe API for parsing/generating JSON ■ Play application architecture is natural fit for REST ■ Functionality is not tied to view templates
  • 62GeneraMng  a  JSON  response$  curl  -­‐i  http://localhost:9000/products/5010255079763HTTP/1.1  200  OKContent-­‐Type:  application/json;  charset=utf-­‐8Content-­‐Length:  88{    "ean":5010255079763,    "name":"Paperclips  Large",    "description":"Large  Plain  Pack  of  1000"}
  • 63GeneraMng  a  JSON  response//  Value  objectcase  class  Product(ean:  Long,  name:  String,      description:  String)//  JSON  formatterimplicit  object  ProductWrites  extends  Writes[Product]  {        def  writes(p:  Product)  =  Json.toJson(        Map(            "ean"  -­‐>  Json.toJson(p.ean),            "name"  -­‐>  Json.toJson(p.name),            "description"  -­‐>  Json.toJson(p.description)        )    )}//  Controller  responseOk(Json.toJson(product))
  • 64Parsing  a  JSON  requestimplicit  object  ProductReads  extends  Reads[Product]  {    def  reads(json:  JsValue)  =  Product(        (json    "ean").as[Long],        (json    "name").as[String],        (json    "description").as[String]    )}//  Controller  method  -­‐  using  the  parse.json  body  parserdef  save(ean:  Long)  =  Action(parse.json)  {  request  =>    val  productJson  =  request.body    val  product  =  productJson.as[Product]    //  …}
  • h&p://www.flickr.com/photos/chris24dotca/3374782984/
  • 66Asynchronous  HTTP  programming  model■ The future of web programming is asynchronous: ■ Perform simultaneous web service requests ■ Process streams, instead of filling up memory or disk ■ Publish real-time data ■ Predictable and minimal resource consumption■ Play’s internal architecture uses a reactive model based on Iteratee IO (read about ‘Iteratees’ in the Play 2.0 docs)
  • 67Other  Play  2.0  features■ Asynchronous web programming■ Build environment based on sbt ■ Scala REPL (irb eat your heart out)■ Designed for easy cloud deployment, e.g. Heroku■ Persistence - use your favourite framework ■ Ebean (Java) or Anorm (Scala) included with Play■ Test framework integration
  • $  play  [info]  Loading  project  definition  from  /demo/project[info]  Set  current  project  to  demo  (in  build  file:/Users/pedro/Documents/code/examples-­‐play/demo/)              _                        _    _  __  |  |  __  _  _    _|  ||  _  |  |/  _  |  ||  |_||    __/|_|____|__  (_)|_|                        |__/                            play!  2.0.1,  http://www.playframework.org>  Type  "help"  or  "license"  for  more  information.>  Type  "exit"  or  use  Ctrl+D  to  leave  this  console.[demo-­‐app]  $
  • [jfokus-­‐app]  $  console[info]  Starting  scala  interpreter...[info]  Welcome  to  Scala  version  2.9.1.final  (Java  HotSpot(TM)  64-­‐Bit  Server  VM,  Java  1.6.0_31).Type  in  expressions  to  have  them  evaluated.Type  :help  for  more  information.scala>
  • scala>  views.html.rainbow.renderres0:  play.api.templates.Html  =  <!DOCTYPE  html><html>    <head>        <title>rainbow</title>        <link  rel="stylesheet"  type="text/css"  href="/assets/colours.css">    </head>    <body>            <div  class="nyan">    <div  class="trail"></div>    <div  class="cat">insert  meme</div>    </div>    </body></html>
  • 71Play  2  books■ Play 2 for Scala, Peter Hilton, Erik Bakker, Francisco Canedo http://bit.ly/playforscala■ Play 2 for Java, Nicolas Leroux, Sietse de Kaper http://bit.ly/playjava■ Early Access (MEAP) editions now available
  • @PeterHilton @PlayFrameworkwww.lunatech.com www.playframework.org