Play! on Heroku

Listen to this article

Developers with experience in both Java and Ruby web development often ask the question: Why is web app development so complicated in Java, and so much simpler in Ruby, with Rails?

There are many ways to answer this question. But importantly, none of them should blame the Java language itself. The people behind Play! Framework proved this by creating a Java based web framework that is as elegant and productive as Rails for Ruby.

It is our pleasure to announce Play! on Heroku in public beta.

Download and install Play! version 1.2.3 or later. Then, create a new Play! app:

$ play new helloworld ~ _ _ ~ _ __ | | __ _ _ _| | ~ | '_ \| |/ _' | || |_| ~ | __/|_|\____|\__ (_) ~ |_| |__/ ~ ~ play! 1.2.3, http://www.playframework.org ~ ~ The new application will be created in /Users/jjoergensen/dev/tmp/helloworld ~ What is the application name? [helloworld] ~ ~ OK, the application is created. ~ Start it with : play run helloworld ~ Have fun! ~ $ cd helloworld

Create a Procfile :

web: play run --http.port=$PORT $PLAY_OPTS

Commit to Git, then create an app on the [Cedar] stack and deploy:

$ git init $ git add . $ git commit -m init $ heroku create --stack cedar $ git push heroku master Counting objects: 30, done. Delta compression using up to 4 threads. Compressing objects: 100% (22/22), done. Writing objects: 100% (30/30), 35.95 KiB, done. Total 30 (delta 1), reused 0 (delta 0) -----> Heroku receiving push -----> play app detected -----> Installing Play!..... done -----> Building Play! application... ~ _ _ ~ _ __ | | __ _ _ _| | ~ | '_ \| |/ _' | || |_| ~ | __/|_|\____|\__ (_) ~ |_| |__/ ~ ~ play! 1.2.3, http://www.playframework.org ~ 1.2.3 Play! application root found at ./ Resolving dependencies: .play/play dependencies ./ --forceCopy --sync --silent -Duser.home=/tmp/build_2rgcv7zjrtyul 2>&1 ~ Resolving dependencies using /tmp/build_2rgcv7zjrtyul/conf/dependencies.yml, ~ ~ ~ No dependencies to install ~ ~ Done! ~ Precompiling: .play/play precompile ./ --silent 2>&1 Listening for transport dt_socket at address: 8000 16:14:33,716 INFO ~ Starting /tmp/build_2rgcv7zjrtyul 16:14:34,372 INFO ~ Precompiling ... 16:14:37,656 INFO ~ Done. -----> Discovering process types Procfile declares types -> web -----> Compiled slug size is 26.2MB -----> Launching... done, v5 http://blazing-water-545.herokuapp.com deployed to Heroku

Visit your app's URL to see it running on Heroku.

For as long as developers have been writing web apps in Java, web frameworks have proliferated to try to make web development easier. But no existing frameworks have taken a clean-room approach. They've been bound by various self-imposed restrictions such as compatibility with servlet containers, support for JSP, compatibility with the standard Java web app layout, and conformance to Java and OO principles even when they don't make sense.

Play! is the first Java web framework to start fresh. It is a built-for-deployment framework that borrows heavily from Rails. Play! applications are meant to be deployed, not packaged and distributed. This allows developers to throw away deeply nested Java package structures, control flow in XML, forget about packaging WAR files, and instead structure projects for optimal clarity and developer productivity.

For example, the helloworld app created above contains a single Java class, the controller:

package controllers; import play.*; import play.mvc.*; import java.util.*; import models.*; public class Application extends Controller { public static void index() { render(); } }

This class defines a single HTTP entry point processed by the index() method which delegates rendering of output to an index.html template using the render() method.

No boilerplate classes or XML config files are needed. The framework takes a fresh approach to packaging conventions, and uses static code where it makes sense. For example, since controller entry points are stateless, and HTTP-oriented instead of object-oriented, they are implemented as static methods (the index() method above).

Add in developer-convenience features like automatic compilation during development, and you'll find that Play! is dramatically more productive to work with than any existing Java web framework.

Jetty has always been at the forefront of containerless deployment, but it has been a lonely place for more than a decade. And the experience can be clunky, because little attention has been paid to optimizing the developer experience for containerless apps. Play! shows how simple and elegant containerless development and deployment can be when it's directly supported by a framework. Running your app locally is as simple as executing play run . Running it in production is as simple as pushing the entire project to production and executing play run --%prod .

Heroku was designed exactly for this model. Play! applications find a natural home on the Heroku platform. When developing on Heroku, you test your app locally with play run , or foreman start . When you are ready to deploy, you simply push your whole project with git push heroku master and heroku will execute play run in production mode. This results in a deployment workflow with minimal and easily understandable differences between deployment and production. In fact, you can run it locally exactly the same way it runs on Heroku eliminating any problems caused by environment differences.

One might jump to the conclusion that Play! is overly focused on ease of use at the cost of performance and robustness. After all, isn't that the reason other frameworks were built on existing, highly optimized libraries?

Look under the covers of Play! and you will find that the start-from-scratch approach gives performance benefits as well. Play! is designed from the ground up to support asynchronous processing of web requests, a technique that is gaining widespread adoption with Node.js, Python's Twisted, and Ruby's EventMachine.

Play! uses Netty, a non-blocking I/O protocol library built by the JBoss team. It combines non-blocking I/O with an elegant continuation-based programming model to deliver asynchronous processing of requests.

For example, the rendering of a PDF can be done in the background while suspending the incoming request as simple as this:

public static void generatePDF(Long reportId) { Promise<InputStream> pdf = new ReportAsPDFJob(report).now(); InputStream pdfStream = await(pdf); renderBinary(pdfStream); }

Play! also does away with the use of stateful sessions, which are so common in other Java web frameworks. By embracing a share-nothing model, Play! makes it easy to scale out applications horizontally by adding more nodes.

We think you'll find Play! not only productive, but fun. Dive in and start building apps!

Special thanks to the Play! Framework team at Zenexity, in particular Guillaume Bort for his support and stewardship and Erwan Loisant for accepting and integrating several feature requests.