Play 2.3 and 2.4 supported both Scala 2.10 and 2.11. Play 2.5 has dropped support for Scala 2.10 and now only supports Scala 2.11. There are a couple of reasons for this:

Play 2.5’s internal code makes extensive use of the scala-java8-compat library, which only supports Scala 2.11. The scala-java8-compat has conversions between many Scala and Java 8 types, such as Scala Futures and Java CompletionStages. (You might find this library useful for your code too.)

The next version of Play will probably add support for Scala 2.12. It’s time for Play to move to Scala 2.11 so that the upcoming transition to 2.12 will be easier.

Both Scala and Java users must configure sbt to use Scala 2.11. Even if you have no Scala code in your project, Play itself uses Scala and must be configured to use the right Scala libraries.

To set the Scala version in sbt, simply set the scalaVersion key, eg:

scalaVersion := "2.11.8"

If you have a single project build, then this setting can just be placed on its own line in build.sbt. However, if you have a multi project build, then the scala version setting must be set on each project. Typically, in a multi project build, you will have some common settings shared by every project, this is the best place to put the setting, eg:

Play WS has been upgraded to use AsyncHttpClient 2. This is a major upgrade that uses Netty 4.0. Most of the changes in AHC 2.0 are under the hood, but AHC has some significant refactorings which require breaking changes to the WS API:

allowPoolingConnection and allowSslConnectionPool are combined in AsyncHttpClient into a single keepAlive variable. As such, play.ws.ning.allowPoolingConnection and play.ws.ning.allowSslConnectionPool are not valid and will throw an exception if configured.

In order to reflect the proper AsyncHttpClient library name, package play.api.libs.ws.ning was renamed into play.api.libs.ws.ahc and Ning* classes were renamed into Ahc*. In addition, the AHC configuration settings have been changed to play.ws.ahc prefix, i.e. play.ws.ning.maxConnectionsPerHost is now play.ws.ahc.maxConnectionsPerHost.

The deprecated interface play.libs.ws.WSRequestHolder has been removed.

The play.libs.ws.play.WSRequest interface now returns java.util.concurrent.CompletionStage instead of F.Promise.

Static methods that rely on Play.current or Play.application have been deprecated.

Play WS would infer a charset from the content type and append a charset to the Content-Type header of the request if one was not already set. This caused some confusion and bugs, and so in 2.5.x the Content-Type header does not automatically include an inferred charset. If you explicitly set a Content-Type header, the setting is honored as is.

As part of the on going efforts to move away from global state in Play, GlobalSettings and the application Global object have been deprecated. For more details, see the Play 2.4 migration guide for how to migrate away from using GlobalSettings.

The Plugins API was deprecated in Play 2.4 and has been removed in Play 2.5. The Plugins API has been superseded by Play’s dependency injection and module system which provides a cleaner and more flexible way to build reusable components. For details on how to migrate from plugins to dependency injection see the Play 2.4 migration guide.

controllers.ExternalAssets is now a class, and has no static equivalent. controllers.Assets and controllers.Default are also classes, and while static equivalents exist, it is recommended that you use the class version.

Generally the components you use should not need to depend on the entire application, but sometimes you have to deal with legacy components that require one. You can handle this by injecting the application into one of your components:

Prior to Play 2.5, Play would add a charset parameter to certain content types that do not define a charset parameter, specifically application/json and application/x-www-form-urlencoded. Now the Content-Type is sent without a charset by default. This applies both to sending requests with WS and returning responses from Play actions. If you have a non-spec-compliant client or server that requires you to send a charset parameter, you can explicitly set the Content-Type header.

By default, Guice can resolve your circular dependency by proxying an interface in the cycle. Since circular dependencies are generally a code smell, and you can also inject Providers to break the cycle, we have chosen to disable this feature on the default Guice injector. Other DI frameworks also are not likely to have this feature, so it can lead to problems when writing Play modules.

Now there are four new methods on the Guice builders (GuiceInjectorBuilder and GuiceApplicationBuilder) for customizing how Guice injects your classes:* disableCircularProxies: disables the above-mentioned behaviour of proxying interfaces to resolve circular dependencies. To allow proxying use disableCircularProxies(false).* requireExplicitBindings: instructs the injector to only inject classes that are explicitly bound in a module. Can be useful in testing for verifying bindings.* requireAtInjectOnConstructors: requires a constructor annotated with @Inject to instantiate a class.* requireExactBindingAnnotations: disables the error-prone feature in Guice where it can substitute a binding for @Named Foo when injecting @Named(“foo”) Foo.

In order to make Play’s CSRF filter more resilient to browser plugin vulnerabilities and new extensions, the default configuration for the CSRF filter has been made far more conservative. The changes include:

Instead of blacklisting POST requests, now only GET, HEAD and OPTIONS requests are whitelisted, and all other requests require a CSRF check. This means DELETE and PUT requests are now checked.

Instead of blacklisting application/x-www-form-urlencoded, multipart/form-data and text/plain requests, requests of all content types, including no content type, require a CSRF check. One consequence of this is that AJAX requests that use application/json now need to include a valid CSRF token in the Csrf-Token header.

Stateless header-based bypasses, such as the X-Requested-With, are disabled by default.

There’s a new config option to bypass the new CSRF protection for requests with certain headers. This config option is turned on by default for the Cookie and Authorization headers, so that REST clients, which typically don’t use session authentication, will still work without having to send a CSRF token.

However, since the config option allows through all requests without those headers, applications that use other authentication schemes (NTLM, TLS client certificates) will be vulnerable to CSRF. These applications should disable the config option so that their authenticated (cookieless) requests are protected by the CSRF filter.

Finally, an additional option has been added to disable the CSRF check for origins trusted by the CORS filter. Please note that the CORS filter must come before the CSRF filter in your filter chain for this to work!

Play’s old default behaviour can be restored by adding the following configuration to application.conf:

Previously, a CSRF token could be retrieved from the HTTP request in any action. Now you must have either a CSRF filter or a CSRF action for CSRF.getToken to work. If you’re not using a filter, you can use the CSRFAddToken action in Scala or AddCSRFToken Java annotation to ensure a token is in the session.

Also, a minor bug was fixed in this release in which the CSRF token would be empty (throwing an exception in the template helper) if its signature was invalid. Now it will be regenerated on the same request so a token is still available from the template helpers and CSRF.getToken.

For more details, please read the CSRF documentation for Java and Scala.

From Play 1.x, Play has come with a Crypto object that provides some cryptographic operations. This used internally by Play. The Crypto object is not mentioned in the documentation, but is mentioned as “cryptographic utilities” in the scaladoc.

For a variety of reasons, providing cryptographic utilities as a convenience has turned out not to be workable. In 2.5.x, the Play-specific functionality has been broken into CookieSigner, CSRFTokenSigner and AESSigner traits, and the Crypto singleton object deprecated.

Cryptographic migration will depend on your use case, especially if there is unsafe construction of the cryptographic primitives. The short version is to use Kalium if possible, otherwise use KeyCzar or straight JCA.

Java (play.mvc.StatusHeader) and Scala (play.api.mvc.Results.Status) APIs had the following behavior before:

API

Method

Default

Scala

play.api.mvc.Results.Status.sendResource

inline

Scala

play.api.mvc.Results.Status.sendPath

attachment

Scala

play.api.mvc.Results.Status.sendFile

attachment

Java

play.mvc.StatusHeader.sendInputStream

none

Java

play.mvc.StatusHeader.sendResource

inline

Java

play.mvc.StatusHeader.sendPath

attachment

Java

play.mvc.StatusHeader.sendFile

inline

In other words, they were mixing inline and attachment modes when delivering files. Now, when delivering files, paths and resources uses inline as the default behavior. Of course, you can alternate between these two modes using the parameters present in these methods.