Using Play Framework 2 in production

10.204 Aufrufe

Veröffentlicht am

Talk at the Vienna Scala User Group on 2013-06-20

Veröffentlicht in: Technologie
0 Kommentare
17 Gefällt mir
  • Als Erste(r) kommentieren

Keine Downloads
Aufrufe insgesamt
Auf SlideShare
Aus Einbettungen
Anzahl an Einbettungen
Gefällt mir
Einbettungen 0
Keine Einbettungen

Keine Notizen für die Folie

Using Play Framework 2 in production

  1. 1. Using Play Framework 2in productionVSUG meetup 20.6.2013Christian
  2. 2. Technology choice• PHP, Java, C#, …• Easy to find developers• Big communities, lots of existing libraries• Scala• Hard to find developers• More expressive, probably more productive• A lot more fun
  3. 3. First steps with Play 2on Startup Live (January 2013)• IDE: IntelliJ IDEA• Git Repo hosted on Dropbox(yeah, I know…)• Quickstart with Play 2 console• Hotreload for development• Packaged app and put it on EC2
  4. 4. What did we learn?• Play is forgiving• Learn it while being productive• Adapt it to fit your needs
  5. 5. First production code// Controller for landing pagesobject Landing extends Controller {// show main landing pagedef showMain = Action {implicit request =>Ok(views.html.landing.main)}}(conf/routes)GET / controllers.Landing.showMain(Landing.scala)(main.scala.html)[…]
  6. 6. Does it stay that simple?
  7. 7. Does it stay that simple?Are you kidding me?
  8. 8. Serious production code(if you spot a bug, let us know :D )SEOAuthentication Caching DB AccessI18nobject Landing extends Controller {// show main landing pagedef landing(language: String) = RichAction {implicit request => Translate(language, otherLang => routes.Landing.landing(otherLang)) {implicit lang => {// fetch featured authors and guidesval (guides, authors) = Cache.getOrElse("landing.guides")(DB.default withSession {implicit session: Session => {(GuideItems.getFiltered(GuideFilter()), RichUsers.getAuthorSample)}})Ok(views.html.landing.landing(Random.shuffle(guides),Random.shuffle(authors)))}}}}
  9. 9. Play fundamentals// Controller for landing pagesobject Landing extends Controller {// show main landing pagedef showMain = Action {implicit request =>Ok(views.html.landing.main)}}(Landing.scala)Request: contains requested URL, parameters, Cookies, etc.Response: HTTP Response containing StatusCode, HTML/JSON/etc.Action: something that takes a request, and returns a response
  10. 10. Action Composition(how we extend the Play framework for DRYness)// represents an abstract request that may or may not be authenticatedabstract class RichRequest[A](private val request: Request[A])extends WrappedRequest(request) {def maybeUserSession: Option[UserSession]}// non-authenticated requestcase class DefaultRequest[A](maybeUserSession: Option[UserSession],private val request: Request[A])extends RichRequest[A](request)// represents an authenticated requestcase class AuthRequest[A](userSession: UserSession,private val request: Request[A])extends RichRequest[A](request)// run action with authenticated user data, or default request dataobject RichAction {def apply[A](f: RichRequest[A] => Result) =Action { request =>Auth.check(request) match {case Some(authRequest) => f(authRequest)case _ => f(DefaultRequest(None, None, request))}}}
  11. 11. Birds-eye viewLots of libraries to integrate
  12. 12. Play Framework 2Pitfalls
  13. 13. Mistake #1: CSS/less compilation• Play uses Rhino, a library that runs JS in Java, to compileless (it‘s very slow!)• Switched to lessc compiler for production• Switched to less.js during development
  14. 14. Mistake #2: HTTPS using Play 2• Don‘t use Play/netty to handle SSL• Now using nginx as reverse proxy
  15. 15. Mistake #3: Not managing Javascript• First we hardcoded javascript routesEg. In Javascript: „$´/edit/guide/save`, ...)“• Now:• Javascript Routes• JavascriptTranslations• Javascript minification / compilation
  16. 16. Mistake #4: Configuring play forsynchronous code (Slick)• Need to configure Play to have more threads• Reuse of data access code• Refactoring (where did I use this? Rename it!)
  17. 17. // filters guides which are visible on marketplacedef displayedGuides =(for { g <- Guides if g.visible === 1 } yield g)// return used category idsdef usedCategories(implicit session: Session) = (for {g <- displayedGuidescat <- GuideCategories if cat.guideId ===} yield cat.categoryId).groupBy(id => id).map(g => g._1).list• write Scala that’s compiled to SQL• keeps your database queries DRY
  18. 18. Why Play 2?Retrospective• Readable codebase: Learn idiomatic Scala while beingproductive!• Has everything you need built in, but allows you to throweverything out piece by piece as you have more advancedrequirements (less compilation, templates, etc.)• DRY• Play is (relatively) fast.How fast? Google „TechEmpower Performance benchmarks“
  19. 19. Summary:Why Play 2?• We know that code-bases eventually grow big. Scala helps.• Took the good stuff from other successful frameworks such as Ruby on Rails.„Embraces HTTP“Adopted byTypesafe as de-facto standard web framework for Scala• As a startup: attract people who want to learn and find better ways todevelop in the web.• Scala as a new and powerful, but stable language• Play 2 as a bleeding edge, but amazingly stable framework• For other languages/frameworks you might find more developers, butScala acts as a good filter to find the good ones.