Play vs. Grails Smackdown

James Ward and Matt Raible

@_JamesWard and @mraible

Why a Smackdown?

Play 2 and Grails 2 are often hyped as the most productive JVM Web Frameworks.

* We wanted to know how they enhanced the Developer Experience (DX).

Happy Trails Requirements


  • Server-side Templates
  • Play 2 with Java
  • Form Validation
  • Data Pagination
  • Authentication
  • Scheduled Jobs
  • Atom / RSS
  • Email Notifications
  • Unit / Integration Tests
  • Load Tests
  • Performance Tests

Stretch Goals: Search, Photo Upload to S3

Our Schedule

  • Week 1 - Data Model Definition
  • Week 2 - Data Layer & URL Design
  • Week 3 - Controllers & Auth
  • Week 4 - Views
  • Week 5 - Misc Polish

Intro to Play 2


Play is based on a lightweight, stateless, web-friendly architecture and features predictable and minimal resource consumption (CPU, memory, threads) for highly-scalable applications - thanks to its reactive model, based on Iteratee IO.
Play is based on a lightweight, stateless, web-friendly architecture and features predictable and minimal resource consumption (CPU, memory, threads) for highly-scalable applications - thanks to its reactive model, based on Iteratee IO.

My Top 10 Favorite Features

  • 0) Simple
  • 1) URL Routing
  • 2) Class Reloading
  • 3) Share-Nothing
  • 4) Java & Scala Support
  • 5) Great Testing Support
  • 6) JPA/EBean Support
  • 7) NIO Server (Netty)
  • 8) Asset Compiler
  • 9) Instant Deployment on Heroku

Intro to Grails 2


Powered by Spring, Grails outperforms the competition. Dynamic, agile web development without compromises.
Powered by Spring, Grails outperforms the competition. Dynamic, agile web development without compromises.

My Top 10 Favorite Features

  1. Documentation
  2. Clean URLs
  3. GORM
  4. IntelliJ IDEA Support
  5. Zero Turnaround
  6. Excellent Testing Support
  7. Groovy
  8. GSPs
  9. Resource Optimizer
  10. Instant Deployment on Heroku

Our Setup

  • IntelliJ IDEA for Development
  • GitHub for Source Control
  • CloudBees for Continuous Integration
  • Heroku for Production

Later added: QA Person and BrowserMob

Code Walk Through

We developed the same app, in similar ways, so let's look at the different layers.


Database - Grails

  • Hibernate is the default persistence provider
  • Create models, Hibernate creates the schema for you

grails-app/conf/DataSource.groovy

Database - Play

  • EBean is the default persistence provider in Java projects
  • Evolutions can be auto-applied
  • Initial evolution sql is auto-created
  • Subsequent changes must be versioned
  • Auto-created schema file is database dependent
  • Play 2 supports multiple datasources (Play 1 does not)


conf/evolutions/default/2.sql

Database - Play

Using Heroku Postgres in production rocks!

  • Postgres 9.1
  • Dataclips
  • Fork & Follow
  • Multi-Ingres

URL Mapping - Grails

grails-app/conf/UrlMappings.groovy

URL Mapping - Play

conf/routes

Models - Grails

  • All properties are persisted by default
  • Constraints
  • Mappings with hasMany and belongsTo
  • Override methods for lifecycle events

grails-app/domain/happytrails/Region.groovy

Models - Play

  • EBean + JPA Annotations
  • Declarative Validations (JSR 303)
  • Query DSL
  • Lazy Loading (except in Scala Templates)


app/models/Direction.java

Controllers - Grails

grails-app/controllers/happytrails/HomeController.groovy

Controllers - Play

  • Stateless - Composable - Interceptable
  • Clean connection between URLs and response code


app/controllers/RouteController.java

Views - Grails

  • Groovy Server Pages, like JSPs
  • GSP Tags
  • Layouts and Templates
  • Optimized Resources

grails-app/views/region/show.gsp

Views - Play

  • Scala Templates
  • Composable
  • Compiled


app/views/region.scala.html

Validation - Grails

grails-app/controllers/happytrails/RouteController.groovy

grails-app/views/route/create.gsp

Validation - Play

app/controllers/RouteController.java

app/views/signupForm.scala.html

IDE Support - Grails

IntelliJ Rocks!

IDE Support - Play


  • $ play idea
  • $ play eclipsify

  • Java!!!
  • Debugging Support via Remote Debugger
  • Limited Testing within IDE

Job - Grails

grails-app/jobs/happytrails/DailyRegionDigestEmailJob.groovy

Job - Play


  • Plain old `static void main`
  • Independent of web app


app/jobs/DailyRegionDigestEmailJob.java

Feed - Grails

  1. grails install-plugin feeds
  2. Add feed() method to controller

grails-app/controllers/happytrails/RegionController.groovy

Feed - Play


  • No direct RSS/Atom support
  • Dependency: "rome" % "rome" % "1.0"


app/jobs/DailyRegionDigestEmailJob.java

Email - Grails

grails-app/jobs/happytrails/DailyRegionDigestEmailJob.groovy

* powered by the mail plugin (built-in)

Email - Play

  • SendGrid Heroku Add-on
  • Dependency:
    "com.typesafe" %% "play-plugins-mailer" % "2.0.2"

app/jobs/DailyRegionDigestEmailJob.java

conf/prod.conf

Photo Upload - Grails

Photo Upload - Play

  • Amazon S3 for Persistent File Storage


app/models/S3Photo.java

app/controllers/RegionController.java

Testing - Grails

  • Unit Tests with @TestFor and @Mock
  • Test URL Mappings with UrlMappingsUnitTestMixin
  • Integration Testing with GroovyTestCase
  • Functional Testing with Geb

test/unit/happytrails/RouteTests.groovy

* Grails plugins often aren't in test scope.

Testing - Play

  • Standard JUnit
  • Unit Tests & Functional Tests
  • FakeApplication, FakeRequest, inMemoryDatabase
  • Test: Controllers, Views, Routing, Real Server, Browser


test/ApplicationControllerTest.java

Demo Data - Grails


grails-app/conf/BootStrap.groovy

Demo Data - Play


app/Global.java

Configuration - Grails

grails-app/conf/Config.groovy

Configuration - Play


  • Based on the TypeSafe Config Library
  • Override config with Java Properties:
    -Dfoo=bar
  • Environment Variable substitution
  • Run with different config files:
    -Dconfig.file=conf/prod.conf


conf/prod.conf

Authentication - Grails

Spring Security UI Plugin, I love you!

grails-app/conf/Config.groovy

Authentication - Play


  • Uses cookies to remain stateless


app/controllers/Secured.java


app/controllers/RegionController.java

Application Comparison

YSlow

PageSpeed

Lines of Code

Load Testing with BrowserMob

Load Testing - 1 Dyno

Bike (Grails)

Hike (Play)

Load Testing - 1 Dyno

Load Testing - 5 Dynos

Bike (Grails)

Hike (Play)

Load Testing - 5 Dynos

Load Testing - 5 Dynos

Load Testing - 5 Dynos + 100 users

Grails 2 vs. Play 2

Jobs

LinkedIn Skills

Google Trends

Indeed Job Trends

User Mailing List Traffic

Books on Amazon

2012 Releases

StackOverflow Questions

Hacker News

Conclusions: Code

  • From a code perspective, very similar frameworks.
  • Code authoring good in both, but lacking for Scala Templates.
  • Grails Plugin Ecosystem is excellent.
  • TDD-Style Development easy with both.
  • Type-safety in Play 2 was really useful, especially routes.

Conclusions: Statistical Analysis

  • Grails has better support for FEO (YSlow, PageSpeed)
  • Grails has less LOC! (6 lines less, but 40% more files)
  • 1 Dyno - Grails had 2x transactions!
    • Grails experienced OOM about halfway through.
  • Apache Benchmark with 10K requests:
    • Requests per second: {Play: 251, Grails: 198}
  • Load Test with 100 Real Users:
    • Grails: 10% more transactions, 0 errors

Conclusions: Ecosystem Analysis

  • "Play" is difficult to search for.
  • Grails is more mature.
  • Play has momentum issues.
  • LinkedIn: more people know Grails than Spring MVC.
  • Play has 3x user mailing list traffic.
  • We had similar experiences with documentation and questions.
  • Outdated documentation is a problem for both.
  • Play has way more hype!

Questions?

* Presentation created with Reveal.js, Google Charts and GitHub Files.

Action!

Learn something new*!

* Or prove that we're wrong...