I went into describing how to implementing Command Query Responsibility Segregation in Play, but there was a fairly long question and answer section about Play as well. I couldn’t go into detail on some of the answers and missed some others, so I’ll fill in the details here.
The core API is Action, which take in a
Request and return a
Request is immutable, but you can
wrap it with extra
information, which you’ll typically do with action composition.
2.1.1 introduced EssentialAction, which uses
(RequestHeader => Iteratee[Array[Byte], Result]) instead of Action’s
(Request => Result) and makes building Filters easier.
Again, Play’s core is simple. About as simple as you can get.
Streaming is handled by Iteratees, which can be a confusing topic for many people. There are good writeups here and here. lila is the best application to look at for streaming, especially for sockets and hubs.
Also worth nothing: the Streaming API has changed repeatedly, and is probably still under active development. Somehow lila is typically ahead of any mailing list or documentation, so if something breaks in a new version of Play, then check if lila changed the API interaction recently.
Having good streaming primitives is something that I didn’t get into that much in the talk, but is still vitally important to ”real time web” stuff.
Play comes packaged with its own template language, Twirl, but you’re not required to use it. There is an integration into Scalate that gives you Mustache, Jade, Scaml and SSP. There’s also an example project that shows how to integrate Play with Freemarker.
One thing that Play doesn’t address directly is how to set up a structure for page layouts. Play provides you with index.scala.html and main.scala.html, but doesn’t provide you with any more structure than that. If you set up a header and footer and allow for subdirectories to use their own templates, you can minimize the amount of confusion in the views.
Play’s JSON API is very well done, and is a great way to pass data around without getting into the weeds or having to resort to XML. It goes very well with case classes.
The documentation isn’t bad, but Pascal Voitot (the author of play-json) has a series of blog posts that go the extra mile: reading JSON with JsPath, writing JSON formats, transforming JSON, and even defining JSON macros.
Form handling is always painful. The documentation helps, but really if you want to know how to do validation, using the sample forms application is the best way to pick things up. There are many useful nuggets that aren’t explicitly discussed in the documentation. In particular, the ability to make custom constraints is extremely useful.
There’s only one routing API replacement that I know of, Play Navigator, a routing DSL for REST services. However, you can use custom data types in the routing table using QueryStringBindable and PathBindable, and save yourself some “string2foo” conversion.
Optimizing Play can be tricky, for a couple of reasons.
The first reason is that it’s easy to think you’re optimizing something that you’re not. Sadek Drobi gives a nice overview, and there’s an exhaustive mailing list discussion about asynchronous code in Play.
The second bit of trickiness is that Play 2.0 and Play 2.1 do not use Akka in the same way.
Play 2.0 uses Akka for almost everything internally.
Play 2.1 does not use Akka to handle incoming requests, or iteratees, or internal code. It uses
scala.concurrent.Future instead with its own thread pools.
Play 2.1 also uses a default thread pool, which is Akka backed –
and is used for the application code, i.e. the stuff inside
In addition to the “play” actor system, there’s a Play Akka plugin. The Akka plugin is actually packaged with
Play itself, and you can find it under
So, if Play already uses Akka, then why define an Akka plugin?
I believe it’s because the Akka plugin defines a distinct
ActorSystem("application") that can be used for backend
tasks like sending email, and can be configured without impacting the “play” ActorSystem. The Akka plugin provides a
useful default and enforces seperation between Play’s actors and the application’s actors.
Given that most of the CQRS talks I’ve read have been from the enterprise perspective, it was nice to talk about CQRS in the context of functional programming and statelessness.
Message passing is something that is typically mentioned in inter process communication, or in message oriented middleware. Akka – a message passing architecture on the thread level – allows us to build “zero coupling” systems . As message passing patterns, CQRS and DDD are a good set of idioms to think about domain logic together, especially since they already assume eventual consistency and indeterminate time.
If you’re using Scala, there are two good authentication options, RememberMe (ahem) and SecureSocial. SecureSocial has better documentation and has been around longer, but RememberMe has better security resistance to some attacks. I’m working to integrate RememberMe’s functionality into SecureSocial, but you’ll want to check out both of them.
There’s also a pure Java authentication option: Play Authenticate. I haven’t used this, but the code looks reasonable.
If you’d rather go it alone or need a basic starter application, you may find Play20StartApp useful (password reset, account confirmation, etc.)
Play does fairly well on security compared to other frameworks. For example, it will set a CORS header to protect against clickjacking, will sign the session cookie with an HMAC to protect against broken authentication, supports SSL, etc.
However, there are some things that Play doesn’t do.
Play doesn’t encrypt the session cookie, so you shouldn’t store any sensitive information in there.
Play won’t protect you from replay attacks, as Play is stateless by default. You can specify a nonce or request counter to counteract this, and RememberMe uses a token based approach for persistent login cookies.
Play won’t protect you from insecure cryptography practices. Education helps, but there’s a lot of misinformation out there as well; watch this video (and slides) and be wary of things you read on Stack Overflow and Hacker News.
Play won’t protect you from failure to restrict URL access; that’s up to the authorization framework.
Play does have cross site request forgery protection, but it will only be effective if you enable the filter and explicitly pass the CSRF helper function in through every single form. There is an authenticity token approach as well, though I haven’t used it.
Most importantly, Play won’t tell you about how web application security fails. I recommend The Tangled Web as an excellent overview on how web applications are stitched together out of different technologies, and how to secure them.
The underlying logger for Play is Logback. Logback is one of the few hardcoded dependencies in Play, which has caused some issues. Fortunately, Play uses Logback through the SLF4J logging API, but there’s no option built into Play to allow Logback to be swapped out easily. There are reports of people swapping out Logback for other logging frameworks, but I haven’t tried them.
There have also been issues with the logging configuration conflicting in places or being unclear. One thing that has
tripped people up repeatedly is that all the logging configuration
must be done in one place. You can’t
have some logging configuration in
application.conf and some configuration in logger.xml.
While Play uses SLF4J under the hood, it doesn’t expose SLF4J functionality in
play.api.Logger. In fact,
there are only two method signatures for logging:
This doesn’t really cover the way I like to log, and it doesn’t provide even the features that are available in SLF4J, such as parameterized logging. My own answer was to ignore the Play logging API entirely and write a Logging wrapper directly against SLF4J (with kestrel combinators, natch), but you may want to use something out of the box.
For example, Typesafe Logging, uses SLF4J and provides you with this:
1 2 3 4 5 6
Or you can use loglady, which uses the Python API style with printf syntax:
I said in the Q&A that I didn’t think you could package Play 2 applications as WAR files. Well, it turns out that there is a plugin available, and it works with Servlet 3.0 and 2.5 containers (Tomcat 6/7, Jetty 7/8/9, JBoss 5/6/7, etc). You may need to tweak the logger to work in the container correctly.
I don’t know how Play’s performance is affected by running inside a servlet container; let me know if it works for you.
Email is one of those things that I think should be divorced as much as possible from Play. It’s backend and async by nature, and this makes it something that is best handled through Akka.
However, there are other options:
- Ostrich, the Twitter metrics library.
- Metrics, with the metrics-scala from Erik Van Oosten, cross-compiled for multiple versions. This is what I use.
- Pillage, which has a Scala option (I have not tried this).
- statsd module for Play 2.
When you’re load testing, it helps to be able to profile the application as well. I usually use Apache JMeter to load the system, and then use jconsole to connect to Play through JMX. YourKit is apparently a good option for profiling as well.
There are a number of different ways to deploy Play projects. Using
play dist gets you most of the way, but you may want to deploy with Ansible or Chef or Fabric. Or you can use upstart or even git hooks.
If you just want to push changes to a staging server as they happen, you can do this with
rsync -avz --delete -e ssh $deployed_code staging:/opt/play-app, although this isn’t so great for production.
If you have suggestions or want to point something out, please email me at firstname.lastname@example.org, and I’ll fill out this post with more details.