Typesafe Activator

Play 2.3 Highlights

Play 2.3 Highlights

Typesafe
Source
May 19, 2015
playframework scala java

This template walks through the highlights of Play 2.3.

How to get "Play 2.3 Highlights" on your computer

There are several ways to get this template.

Option 1: Choose play-2.3-highlights in the Typesafe Activator UI.

Already have Typesafe Activator (get it here)? Launch the UI then search for play-2.3-highlights in the list of templates.

Option 2: Download the play-2.3-highlights project as a zip archive

If you haven't installed Activator, you can get the code by downloading the template bundle for play-2.3-highlights.

  1. Download the Template Bundle for "Play 2.3 Highlights"
  2. Extract the downloaded zip file to your system
  3. The bundle includes a small bootstrap script that can start Activator. To start Typesafe Activator's UI:

    In your File Explorer, navigate into the directory that the template was extracted to, right-click on the file named "activator.bat", then select "Open", and if prompted with a warning, click to continue:

    Or from a command line:

     C:\Users\typesafe\play-2.3-highlights> activator ui 
    This will start Typesafe Activator and open this template in your browser.

Option 3: Create a play-2.3-highlights project from the command line

If you have Typesafe Activator, use its command line mode to create a new project from this template. Type activator new PROJECTNAME play-2.3-highlights on the command line.

Option 4: View the template source

The creator of this template maintains it at https://github.com/playframework/playframework/tree/2.3.x/templates/play-2.3-highlights.

Option 5: Preview the tutorial below

We've included the text of this template's tutorial below, but it may work better if you view it inside Activator on your computer. Activator tutorials are often designed to be interactive.

Preview the tutorial

Welcome to Play 2.3.9

This template showcases a few of the new features in Play 2.3.

You can navigate this tutorial to see some of the new features using the arrows above, or you can jump to any particular feature at any time by clicking the title of the current part of the tutorial, which will open a drop down.

sbt-web

The largest new feature for Play 2.3 is the introduction of sbt-web. In summary sbt-web allows HTML, CSS and JavaScript functionality to be factored out of Play's core into a family of pure sbt plugins. There are two major advantages to you:

  • Play is less opinionated on the HTML, CSS and JavaScript; and
  • sbt-web can have its own community and thrive in parallel to Play's.

There are other advantages including the fact that sbt-web plugins are able to run within the JVM via Trireme, or natively using Node.js.

Browse to plugins.sbt. You can see that we have quite a number of SBT web plugins installed, from LESS to CoffeeScript to RequireJS to Mocha testing. The configuration you see here is all that is needed to enable these plugins, their default settings will be included in any project that is using sbt-web (and this includes any project that is using Play). This is utilising the new sbt auto plugins functionality.

Of course, this is not the complete list of sbt-web plugins that are available, you can see that list here.

As we said earlier, it is possible to switch between using a completely in JVM JavaScript engine based on Trireme, or running natively on Node. If you browse to build.sbt, you can see a configuration setting for the engine type commented out. If you uncomment this, and then restart Activator, sbt-web will use Node instead (assuming you have a node command on your PATH).

Of course, tying a particular build to a particular runtime is probably not a good idea, so we recommend that rather than putting this configuration in your build file, you add it to your environment via the SBT_OPTS environment variable, like so:

export SBT_OPTS="$SBT_OPTS -Dsbt.jse.engineType=Node"

WebJars

sbt-web comes with built in support for WebJars. WebJars allow you to manage your client side dependencies, such as jQuery and Bootstrap, as a normal dependency in your build tool, with support for transitive dependencies.

Browse to build.sbt. In the list of library dependencies you can see that we add in both bootstrap and jquery. All of the regular benefits in using sbt to declare dependencies are available here e.g. resolving dependencies that may otherwise clash with each other. In addition you can leverage any existing infrastructure such as Sonatype and Artifactory repositories.

Browse to main.scala.html. sbt-web will automatically expand the contents of each of the declared WebJars into a folder that is referenced using "lib". The next directory on this path is the name of the WebJars artifact e.g. "org.webjars" % "bootstrap" % "3.1.1" is referenced starting with "lib/bootstrap".

When WebJars are used other parts of sbt-web can perform certain optimizations e.g. the RequireJS Optimzer is able to automatically resolve access to WebJar based assets to a CDN; all with no explicit configuration being required on your part. More on that later.

WebJars can also be used in combination with just about every other sbt-web plugin. For example, browse to main.less to see how you might integrate the LESS files provided with Bootstrap into your own LESS files.

Source Map support

Many of the sbt-web plugins come with built in Source Map support, enabled by default. If you run this application, and then visit the index page, you'll notice in your browsers developer tools (if it supports source maps) that you can click on references to less files when looking at computed styles, and also that you can set break points in CoffeeScript files.

Mocha Testing

If you open Controller.coffee, you'll notice a lot of fragile logic regarding the state of the page, the WebSocket, and so on. You'll also notice that we've implemented this in such a way that all the logic in talking to the DOM, as well as all the logic in how to actually connect and talk to the WebSocket have been abstracted away into other services.

This practice of separating our client side logic from the DOM and other APIs is a best practice recommended by ThoughtWorks in their January 2014 Technology Radar. And because we've followed it, we can easily unit test it, using sbt-web's Mocha test plugin.

If you run the tests on the command line (using activator test) you can see a few tests being run. These tests are declared in ControllerSpec.coffee.

By default, all code that compiles to JavaScript files *Spec.js or *Test.js in the test/assets directory will be executed as tests.

You can see here we're also using Squire.js to mock RequireJS dependencies. This setup for using RequireJS and Squire on node is done in the Setup.coffee file, which is configured to be loaded for all test runs in build.sbt.

Asset Pipeline

There is a new asset pipeline for post-processing web assets. The pipeline is a series of stages that transform assets. Each stage runs one after the other. The asset pipeline is typically where assets are optimized and tuned.

Browse to build.sbt. You'll see a configuration option called pipelineStages.

pipelineStages := Seq(rjs, digest, gzip)

Each stage is provided by a plugin:

  1. the RequireJS plugin (sbt-rjs) optimizes and combines assets
  2. the digest plugin (sbt-digest) generates hashes that can be used to identify assets for caching (also known as "fingerprinting")
  3. the gzip plugin (sbt-gzip) compresses assets ahead of time to save CPU later

RequireJS and gzip encoding will be familiar from Play 2.2. However the RequireJS plugin has changed in Play 2.3. The digest plugin and its support for asset caching is completely new. Read on to find out what's changed with the RequireJS plugin and to learn about the new digest plugin.

The asset pipeline is generally used when staging and distributing your application (production mode). On the following pages you may be asked to run your application in production mode (activator start) to see a demonstration.

RequireJS

Play includes much better support for the RequireJS Optimizer than it did before. RequireJS is a module loading system for the browser. To demonstrate, let's start Play in production mode. Stop the currently running app in Activator, and then on the command line, run activator start, and then visit http://localhost:9000.

If you look at the network resources that your application has loaded, first you'll see that with no changes, your application is only loading one of your JavaScript files, main.js, and inspecting that file, you'll see it incorporates all the other files. This is expected from RequireJS optimization.

However, you may also notice that it is loading jquery from http://cdn.jsdelivr.net/webjars/jquery/2.1.0/jquery.min.js. In development mode, it was loading jquery from the local server, but in production mode it has automatically switched to the minified version from a CDN. This CDN is one that all WebJars are deployed to. This is the default for WebJars, however it is possible to change this behaviour by setting:

RjsKeys.webJarCdn := None

Asset Fingerprinting

Asset fingerprinting is a caching technique that uses hashes to identify when assets change. Each file has a hash added into its name so that its content can be uniquely identified by its URL and cached aggressively.

For example, a file called main.css cannot be cached for too long, in case we need to publish a new version with different content. However, a file called 84a01dc6c53f0d2a58a2f7ff9e17a294-main.css can be safely cached forever because, if its content changes, then it will have a different name. Therefore we can use very aggressive caching for these assets, a technique called far future expires.

To use asset fingerprinting you need to enable hash generation by adding the the digest plugin to the asset pipeline. Once you've done that you use the Assets.versioned method in your application routes and reverse routes.

Browse to build.sbt. You'll see that digest is part of the pipelineStages setting. This plugin calculates hashes for all assets ahead of time, so that assets can be served fast in production.

Browse to routes. You can see that the Assets.versioned method is being used to serve assets instead of the Assets.at method (which is used to serve unfingerprinted assets).

GET        /assets/*file        controllers.Assets.versioned(path="/public", file: Asset)

Browse to a template like index.scala.html. You'll see that all the assets are looked up by getting a reverse route to Asset.versioned. Reverse routing will return names with hashes in them.

<link rel="stylesheet" media="screen" href="@routes.Assets.versioned("stylesheets/main.css")">

Asset fingerprinting, like other parts of the asset pipeline, doesn't generally need to run when you're working in development mode, so it won't generally be available in the Activator UI or when you use Activator with the run command. You'll need to use the start command to try out this feature.

If you run your application in production mode (using activator start) and inspect the application traffic then you'll see asset fingerprinting in action. All asset names will have hashes in them and all assets will be have Expires headers set one year in the future.

Improved WebSockets support

There are three main new features in Play's WebSocket support. The first is that it is now possible to reject a WebSocket with an HTTP response such as Not Found or Forbidden. The second is that you can now specify different frame formatters for incoming and outgoing message types. And the final feature is that there is now a very easy to use method for handling a WebSocket as an actor.

Open SumController.scala to see a WebSocket that demonstrates all three of these.

Firstly we are authenticating based on the passed in password, if it's secret, we accept the WebSocket with Right, if it's not, we send Left with the failed result.

Secondly, you can see we've declared it to handle Sum messages for incoming messages, and SumResult messages for outgoing messages. The frame formatters for these are declared in SumActor.scala, they're parsing the messages as JSON.

Finally, actually handling the messages is done by an actor, this is done by returning a function that takes the ActorRef to send out going messages to, and returns the Props of an actor to handle the WebSocket.

Have a look at SumActor.scala, you can see the actor is very simple.

Improved Anorm

There are various fixes included in new Anorm (type safety, option parsing, error handling, ...) and new interesting features.

  • String interpolation is available to write SQL statements more easily, with less verbosity (passing arguments) and performance improvements (up to x7 faster processing parameters). e.g. SQL"SELECT * FROM table WHERE id = $id".
  • Multi-value (sequence/list) can be passed as parameter. e.g. SQL"""SELECT * FROM Test WHERE cat IN (${Seq("a", "b", "c")})"""
  • It's now possible to parse column by position. e.g. val parser = long(1) ~ str(2) map { case l ~ s => ??? }
  • Query results include not only data, but execution context (with SQL warning).
  • More types are supported as parameter and as column: java.util.UUID, numeric types (Java/Scala big decimal and integer, more column conversions between numerics), temporal types (`java.sql.Timestamp`), character types.
comments powered by Disqus