Play 2.3 Highlights
This template walks through the highlights of Play 2.3.Tweet
This template walks through the highlights of Play 2.3.Tweet
There are several ways to get this template.
play-2.3-highlightsin the Lightbend Activator UI.
Already have Lightbend Activator (get it
here)? Launch the UI then
play-2.3-highlights in the list of
play-2.3-highlightsproject as a zip archive
If you haven't installed Activator, you can get the code
by downloading the template bundle
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:
This will start Lightbend Activator and open this template in your browser.
C:\Users\typesafe\play-2.3-highlights> activator ui
play-2.3-highlightsproject from the command line
If you have Lightbend Activator, use its command line mode
to create a new project from this template.
activator new PROJECTNAME play-2.3-highlights on the command line.
The creator of this template maintains it at https://github.com/playframework/playframework/tree/2.3.x/templates/play-2.3-highlights.
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.
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.
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.
node command on your
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"
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
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.
Many of the sbt-web plugins come with built insupport, enabled by default. If you 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.
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.
*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.
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 := Seq(rjs, digest, gzip)
Each stage is provided by a plugin:
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.
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.
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 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.
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.
There are various fixes included in new Anorm (type safety, option parsing, error handling, ...) and new interesting features.