1. Having Fun with
or, how a perfectly normal
dynamic language developer
fell in love with Java
Clinton R. Nixon, Viget Labs
2. i am a robot come
About Me from the year 2082
in order to prevent
java from becoming
stale and borinG
3. “We are fully aware that we made choices that are pretty
uncommon in the Java world, and that Play does not
blindly follow all the so-‐called Java ‘good practices’. But
all members of the Play teams are very experienced Java
developers and we are totally aware of the choices we
made and the rules we broke.
“Java itself is a very generic programming language and
not originally designed for web application development.
It is a very different thing to write a generic and reusable
Java library and to create a web application. A web
application itself doesn’t need to be designed to be
reusable. You need less abstraction, less conEiguration.
Reusability does exist for Web applications, but through
Web service API rather than language-‐level integration.”
– Guillaume Bort, from the Play! FAQ (emphasis mine)
4. What is Play!?
(a) A web framework with unnecessary punctation
in its name that I am now dropping.
(b) A web framework written in Java that doesn’t
use servlets, portlets, XML, EJBs, JSPs, or PCP.
(c) A share-‐nothing, REST-‐aware, super-‐fast, MVC-‐
structured web framework that takes the best
from Ruby on Rails, Django, and the like and
adds its own strengths.
(d) All of the above.
5. Our example app: PDFless
A way to build PDFs
using simple tools:
HTML + CSS.
Good candidate for a
system like Play. Uses
FlyingSaucer, a Java
library.
6. Starting our app
cnixon@moro ~/Projects> play new pdfless
~ _ _
~ _ __ | | __ _ _ _| | Look at tha t ASCII art!
~ | '_ | |/ _' | || |_|
~ | __/|_|____|__ (_) Now we’re having fun.
~ |_| |__/
~
~ play! 1.1-‐unstable-‐r785, http://www.playframework.org
~
~ The new application will be created in /Users/cnixon/Projects/pdfless
~ What is the application name? PDFless
~
~ OK, the application is created.
~ Start it with : play run pdfless
~ Have fun!
8. Creating our model
package models;
import play.data.validation.Email;
app/models/Document.java
import play.data.validation.Required;
public fields
import play.data.validation.URL;
import play.db.jpa.Model;
import javax.persistence.Entity;
@Entity
public class Document extends Model {
@Required @URL
public String url;
@Required @Email
public String email;
@Required
public boolean processed; annotations for validation
public Document(String url, String email) {
this.url = url;
this.email = email;
this.processed = false;
}
}
9. Where’s the database?
# Database configuration
# ~~~~~
# To quickly set up a development database, use either:
# -‐ mem : for a transient in memory database (HSQL in memory)
# -‐ fs : for a simple file written database (HSQL file stored)
db=fs
# for testing, I’m using an in-memory DB
# To connect to a local MySQL5 database, use:
# db=mysql:user:pwd@database_name
#
# If you need a full JDBC configuration use the following :
# db.url=jdbc:postgresql:database_name
# db.driver=org.postgresql.Driver
# db.user=root
# db.pass=secret
There’s no migration system:
Hibernate will auto-update your
tables unless you configure it otherwise.
13. A simple controller
package controllers;
import models.Document;
What does this remind me of?
import play.data.validation.Valid;
import play.mvc.Controller;
public class Documents extends Controller {
public static void index() {
render();
}
public static void create(@Valid Document doc) {
if (validation.hasErrors()) {
render("Documents/index.html");
} else {
doc.save();
}
}
}
14. Ok, this smells like a train yard
# Routes
# This file defines all application routes (Higher priority routes first)
# ~~~~
this took some getting used to
# Home page
GET / Documents.index
GET /documents Documents.index
POST /documents Documents.create
# Map static resources from the /app/public folder to their paths
GET /public/ staticDir:public
# Catch all
* /{controller}/{action} {controller}.{action}
sigh - but it is helpful with rapid development
16. In case you didn’t catch that
• No compiling
• Awesome error pages
• Request params bind to
controller method
params
17. Let’s see that redirection code
This is hard to understand,
if (Modifier.isPublic(ctMethod.getModifiers()) &&
((ctClass.getName().endsWith("$") &&
but look at this!
!ctMethod.getName().contains("$default$")) ||
(Modifier.isStatic(ctMethod.getModifiers()) &&
ctMethod.getReturnType().equals(CtClass.voidType))) &&
!isHandler) {
try {
ctMethod.insertBefore(
"if(!
play.classloading.enhancers.ControllersEnhancer.ControllerInstrumentation.isActionCallAllowed
()) {"+
"play.mvc.Controller.redirect(""+ctClass.getName().replace("$", "")+
"."+ctMethod.getName()+"", $args);"+
"}"+
"play.classloading.enhancers.ControllersEnhancer.ControllerInstrumentation.stopActionCall();"
);
} catch (Exception e) { ... }
}
18. Translation to human
Before each method, add “If we’re already in an action call
ctMethod.insertBefore(
"if(!play.classloading.enhancers.
ControllersEnhancer.ControllerInstrumentation.
isActionCallAllowed()) {"+
"play.mvc.Controller.redirect(""+ send a redirect
ctClass.getName().replace("$", "")+ to this new
"."+ctMethod.getName()+"", $args);"+ action
"}"+ to the browser
"play.classloading.enhancers.
ControllersEnhancer.ControllerInstrumentation.
stopActionCall();"
);
and stop the original action.”
20. #{extends 'main.html' /} this is Groovy
#{set title:'PDFLess' /}
#{ifErrors}
<div class="error">Please correct the errors below.</div>
#{/ifErrors}
#{form @Documents.create()}
<p>
<label for="doc.url">Enter the URL to make a PDF out of:</label>
<input type="text" id="doc.url" name="doc.url" value="${params['doc.url']}"/>
#{ifError 'doc.url'}
<span class="error">#{error 'doc.url' /}</span>
#{/ifError}
</p> this is gross
<p>
<label for="doc.email">Enter the email address to send your PDF to:</label>
<input type="text" id="doc.email" name="doc.email"
value="${params['doc.email']}"/>
#{ifError 'doc.email'}
<span class="error">#{error 'doc.email' /}</span>
#{/ifError}
</p>
<input type="submit" id="doc.submit" />
#{/form}
but this is kind of
awesome
21. tags are just
app/views/tags/textField.html
<p> HTML + Groovy
<label for="${_arg}">#{doBody /}</label>
<input type="text" id="${_arg}" name="${_arg}" value="${params[_arg]}"/>
#{ifError _arg}
<span class="error">#{error _arg /}</span>
#{/ifError}
</p> and are used like
app/views/Documents/index.html built-in tags
#{form @Documents.create()}
#{textField 'doc.url'}Enter the URL to make a PDF out of:#{/textField}
#{textField 'doc.email'}
Enter the email address to send your PDF to:
#{/textField}
#{textField 'code'}Please type the code below:#{/textField}
<p>
<input type="hidden" name="randomID" value="${randomID}" />
<img class="captcha" src="@{Application.captcha(randomID)}" />
</p>
<input type="submit" id="doc.submit" value="Make My PDF" />
#{/form}
32. Young, but shows promise
The mailing list for Play is
very active, and new
modules are being created
all the time.
Reminds me of Rails
around 1.0.
Could easily blow up;
could easily slowly die off.
33. Awesome things we don’t have time for
• Suspendable requests
• Easiest Eile uploads ever
• Bespin module to code your application inside your
application
• Automatic type extensions in templates
• Simple i18n
34. Summary
Play comes to Java with as few preconceptions as
possible.
It hooks into existing Java libraries easily.
It’s surprisingly fun to use and quick to develop with.
It’s a project with lots of room for individuals to
make a difference.
If you liked this talk, please http://playframework.org
consider donating to the
Buy Clinton IntelliJ fund.
http://crnixon.org
My free tial ends in 3 days. @crnixon