Play framework productivity formula
Post on 01-Nov-2014
1415 Views
Preview:
DESCRIPTION
Transcript
Play Framework (Scala)
Productivity Formula by Sorin Chiprian
What is Play?
Play is a cool frameworkEasy to learn
Play supports both Scala & Java
What do I like mostBest error reporting ever seen
Hit refresh and works(this applies for configurations, templates or code changes)
What else?
Play is REST-ful
❖ Matches the web architecture which is stateless➢ the state will be stored on the other tiers
(Cookie, Database,Cache Server)
❖ Easy testing, easy sharing, easy bookmarking ➢ an url is what you need
❖ Horizontal scalability
# Routes
# This file defines all application routes (Higher priority routes first)
GET / controllers.Application.index
GET /:timeout controllers.Application.asyncURLGet(timeout: Int, url:String)
GET /clients/$id<[0-9]+> controllers.Clients.show(id: Long)
GET /clients controllers.Clients.list(page: Int ?= 1)
GET /hello/:name controllers.Application.hello(name:String)
Play has a powerful URL rooting
➔ url should be established before coding ➔ more complicated routing can be achieved by extending
GlobalSettings or by defining your own Router ➔ even more can be done with PathBindable➔ also possible to do reverse routing
routes.Application.hello("Bob")
Play has a very simple config
Play is a modern web framework
● application.confenvironment="development"
db.default.url = "jdbc:mysql://127.0.0.1:3306/mydb"
…
● production.confinclude "application.conf"
environment="production"
db.default.url = ${?MYSQL_URL}
Some Code Example
Request -> is the request performed by the clientAction -> something which converts a request into a responseResponse -> Is the HTTP Response with Status Code, Cookies, Headers, BodyBodyParser -> a function that transforms the request body in a Scala (or Java) value, based on Content-Type of the request
object Application extends Controller { def index = Action { Ok("It works!") }
def hello(name: String) = Action { Ok("Hello " + name) }}
GET / controllers.Application.index
GET /hello/:name controllers.Application.hello(name:String
The above example is not getting any reference from the incoming request, but we have another Action builder that takes as an argument a function Request => Result:def index = Action { request => Ok("Got request [" + request + "]")}
Simple example of serving a response
routes file
Action(parse.text) { request => val text = request.body Ok("Got request " + text )}
We can use a body parser in order to read the request.In this example we will use the play.api.mvc.BodyParsersparse.text -> parses the body as text if the Content-Type is text/plain.
Inside Play
Play has a MVC stack with a template system
TemplatesScala-based template engineTemplate markup syntax
@(title: String, content: String)<!DOCTYPE html><html> <head> <title>@title</title> </head> <body> @content </body></html>
Ok(views.html.main("title","content"))
Templates and assets are compiled so any error will be displayed immediately
app → Application sources └ assets → Compiled asset sources └ stylesheets → Typically LESS CSS sources └ javascripts → Typically CoffeeScript sources └ controllers → Application controllers └ models → Application business layer └ views → Templatesconf → Configurations files and other non-compiled resources └ application.conf → Main configuration file └ routes → Routes definitionpublic → Public assets └ stylesheets → CSS files └ javascripts → Javascript files └ images → Image filesproject → sbt configuration files └ build.properties → Marker for sbt project └ plugins.sbt → sbt plugins & declaration for Play itselflogs → Standard logs folder └ application.log → Default log filetarget → Generated stufftest → source folder for unit or functional tests
myProject
Where is the fun?
Load Balancer
Play Server
Play Server
Play Server
This is what we have until now- it’s cool but no fun -
This is fun !!!
Load Balancer
Play Server
Play Server
Play Server
Cloud Service
Memcache Service
Database
Cloud Storage
Cloud Service
Cloud Service
!!! The remote services latency in a threaded model could mean trouble !!!
Solving the issue
Play is built on top of Akka and Netty➔ you can use non-blocking I/O when making calls to remote services
In high traffic environments, thread pools management is painful❖ make threads on the fly
➢ This is expensive inefficient❖ use a thread pool with too few threads
➢ run up of threads -> latency issues❖ use a thread pool with too many threads
➢ context switching overhead➢ Memory overhead
Play comes with a WS LibraryWS.url(url).withHeaders("headerKey" -> "headerValue").get()
➔ request reading is also async➔ enables:
◆ WebSockets◆ Comet
Attention the database access most probably will not be async
Some async example
This can get even more fun
Play it’s production readyPlay is already being used by companies like:
Play is scalable
Instant deployment on
but you can found instruction for:CloudbeesCloud FoundryClever Cloud
Some other featuresDatabase evolutions
evolutions.use.locks=truedatabase locks are used to ensure that onlyone host applies any Evolutions
# Users schema # --- !Ups CREATE TABLE User ( id bigint(20) NOT NULL AUTO_INCREMENT, email varchar(255) NOT NULL, password varchar(255) NOT NULL, fullname varchar(255) NOT NULL, isAdmin boolean NOT NULL, PRIMARY KEY (id)); # --- !Downs DROP TABLE User;when running on multiple hosts only use evolutions if you are using Postgres or Oracle
Anorm, simple SQL data access
Pluginsclasses that extend the Plugins trait
conf/play.plugins file
10000:my.example.FirstPlugin10001:my.example.SecondPlugin
<priority>:<classname>
def enabled : Booleandef onStart (): Unitdef onStop (): Unit
in
can overwrite the following methods
conf/evolutions/default/1.sqlconf/evolutions/default/2.sql...
Dependency injection Activator Spring Subcut Macwire Guice
val appDependencies = Seq( javaJpa, "org.hibernate" % "hibernate-entitymanager" % "3.6.9.Final")
Unit testing Junit -> java Specs2 -> scalaintegration with Selenium
No built-in JPA implementation in Play, but you can add Hibernate
SQL("Select name,indepYear from Country")().map { row => row[String]("name") -> row[Int]("indepYear")}
What would you try
Java or Scalatry the samples folder
top related