§Play 2.8 Migration Guide
This guide is for migrating from Play 2.7 to Play 2.8. See the Play 2.7 Migration Guide to upgrade from Play 2.6. It is also recommended to read Akka 2.5 to 2.6 migration guide since multiple changes there have an impact on Play 2.8.
§How to migrate
Before starting sbt
, make sure to make the following upgrades.
§Play update
Update the Play version number in project/plugins.sbt
:
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.8.x")
Where the “x” in 2.8.x
is the minor version of Play you want to use, for instance 2.8.0
.
§sbt upgrade
Although Play 2.8 still supports sbt 0.13, we recommend that you use sbt 1. This new version is supported and actively maintained. To update, change your project/build.properties
so that it reads:
sbt.version=1.2.8
At the time of this writing 1.2.8
is the latest version in the sbt 1.x family, you may be able to use newer versions too. Check the release notes for both Play’s minor version releases and sbt’s releases for details.
§API Changes
Multiple API changes were made following our policy of deprecating the existing APIs before removing them. This section details these changes.
§Scala 2.11 support discontinued
Play 2.8 support Scala 2.12 and 2.13, dropping support for 2.11, which has reached its end of life.
§Setting scalaVersion
in your project
Both Scala and Java users must configure sbt to use Scala 2.12 or 2.13. 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, for example:
scalaVersion := "2.13.1"
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, for example:
def commonSettings = Seq(
scalaVersion := "2.13.1"
)
val projectA = (project in file("projectA"))
.enablePlugins(PlayJava)
.settings(commonSettings)
val projectB = (project in file("projectB"))
.enablePlugins(PlayJava)
.settings(commonSettings)
§File serving methods changed the type of their filename
parameters
Methods for serving files, like ok(File content, ...)
(and similar) in the Java API or sendFile
, sendPath
and sendResource
in both Java’s StatusHeader
and Scala’s Status
class changed the type of their filename
parameters: Instead of using a plain String
, the Scala API now uses an Option[String]
as return type for its filename
parameter function. The Java API changed the parameter type to be an Optional<String>
.
This API change better reflects the fact that you can pass None
/ Optional.empty()
if you don’t want the Content-Disposition
header to include a filename.
§The Headers
class of the Java API is immutable
The class play.mvc.Http.Headers
is immutable now. Some methods have been deprecated and were replaced with new ones:
Deprecated method | New method |
---|---|
toMap() |
asMap() |
addHeader(String name, String value) |
adding(String name, String value) |
addHeader(String name, List<String> values) |
adding(String name, List<String> values) |
remove(String name) |
removing(String name) |
Be aware that the old deprecated methods return the original, modified Headers
object, whereas the new methods always return a new object, leaving the original object unmodified.
§Deprecated APIs were removed
Many APIs that were deprecated in earlier versions were removed in Play 2.8. If you are still using them we recommend migrating to the new APIs before upgrading to Play 2.8. Check the Javadocs and Scaladocs for migration notes. See also the migration guide for Play 2.7 for more information.
§Scala API
- xxx
- xxx
Some new methods were added to improve the Scala API too:
xxx
§Java API
- In Play 2.7 we deprecate
play.mvc.Http.Context
in favor of directly usingplay.mvc.Http.RequestHeader
orplay.mvc.Http.Request
. We have now removedHttp.Context
and if your application was still depending on it, you should read Play 2.7 migration guide instructions. - xxx
Some new methods were added to improve the Java API too:
xxx
§Cache Api changes
Caffeine
implementations of thegetOrElseUpdate
methods in bothSyncCacheApi
andAsyncCacheApi
are now atomic. (Note that EhCache implementations ofgetOrElseUpdate
methods are still non-atomic)Caffeine
implementations of thegetOrElseUpdate
methods lazily evaluate theorElse
part, that means if the item with the given key exists in cache then theorElse
part is not executedplay.cache.caffeine.CaffeineDefaultExpiry
class is now deprecated
§Internal changes
Many changes have been made to Play’s internal APIs. These APIs are used internally and don’t follow a normal deprecation process. Changes may be mentioned below to help those who integrate directly with Play internal APIs.
§Configuration changes
This section lists changes and deprecations in configurations.
§ObjectMapper
serialization change
Play 2.8 adopts Akka Jackson Serialization support and then uses the defaults provided by Akka. One of the changes is how Java Time types are rendered. Until Play 2.7 they were rendered as timestamps, which has better performance, but now they are rendered using ISO-8601 (rfc3339) format (yyyy-MM-dd'T'HH:mm:ss.SSSZ
).
If you need to use the old timestamps default format, then add the following configuration in your application.conf
:
akka.serialization.jackson.play.serialization-features.WRITE_DATES_AS_TIMESTAMPS = on
§Dropped the overrides for akka.actor.default-dispatcher.fork-join-executor
The overrides that Play had under akka.actor.default-dispatcher.fork-join-executor
have been dropped in favour of using Akka’s new-and-improved defaults.
See the section related to changes in the default dispatch in Akka’s migration guide for more details.
§IOSource
and FileIO
changes in Akka Streams
There are changes related to how Akka Streams handle errors for FileIO.toPath
, StreamConverters.fromInputStream
, and StreamConverters.fromOutputStream
. See the section related to these changes in Akka’s migration guide for more details.
§Configuration loading changes
Until Play 2.7, when loading configuration, Play was not considering the default Java System Properties if the user provides some properties. Now, System Properties are always considered, meaning that you can reference them in your application.conf
file even if you are also defining custom properties. For example, when embedding Play like the code below, both userProperties
and System Properties are used:
import java.util.Properties
import play.api.mvc.Results
import play.core.server.AkkaHttpServer
import play.core.server.ServerConfig
import play.api.routing.sird._
class MyApp {
def main(args: Array[String]): Unit = {
// Define some user properties here
val userProperties = new Properties()
userProperties.setProperty("my.property", "some value")
val serverConfig = ServerConfig(properties = userProperties)
val server = AkkaHttpServer.fromRouterWithComponents(serverConfig) { components => {
case GET(p"/hello") => components.defaultActionBuilder {
Results.Ok
}
}}
}
}
Keep in mind that system properties override user-defined properties.
§Debugging SSL Connections
Until Play 2.7, both Play and Play-WS were using a version of ssl-config which had a debug system that relied on undocumented modification of internal JSSE debug settings. These are usually set using javax.net.debug
and java.security.debug
system properties on startup.
This debug system has been removed, the debug flags that do not have a direct correlation in the new system are deprecated, and the new configuration is documented in ssl-config docs.
§I18n behavior changes
Matching of languages behavior now satisfies RFC 4647.
§Example
conf/application.conf
file:
play.i18n.langs = [ "fr", "fr-FR", "en", "en-US" ]
User’s accept-language:
en-GB
§Before
User’s accept-language en-GB
does not match any of the conf. The play app responds French page against user’s will.
§After
User’s accept-language en-GB
matches en
. The play app responds English page.
§Generalized server backend configurations
Play comes with two server backends:
- Akka HTTP (the default), which can be configured via
play.server.akka.*
- Netty, which can be configured via
play.server.netty.*
.
Until now, we kept these configurations separate, even if there were settings that applied to both backends and therefore were conclusively duplicates.
With Play 2.8 we start to generalize such duplicate server backend configurations and move them directly below play.server.*
:
play.server.akka.max-content-length
is now deprecated. It moved toplay.server.max-content-length
. Starting with Play 2.8 the Netty server backend will now also respect that config.play.server.akka.max-header-value-length
andplay.server.netty.maxHeaderSize
are both deprecated now. Those configs moved toplay.server.max-header-size
.
§The excludePaths
config of the Redirect HTTPS filter changed
The play.filters.https.excludePaths
config of the Redirect HTTPS filter now contains a list of paths instead of URIs.
That means query params don’t matter anymore. If the list contains /foo
the request /foo?abc=xyz
will now be excluded too.
Before Play 2.8, because the URI of a request (path + query params) was checked against the list, you needed to add exactly a request’s URI to exclude it from redirecting.
§Defaults changes
Some of the default values used by Play had changed and that can have an impact on your application. This section details the default changes.
§Content-Disposition: inline
header not send anymore when serving files
When serving files via the Scala API or the Java API Play by default generates the Content-Disposition
header automatically and sends it to the client.
Starting with Play 2.8 however, when the computed header ends up being exactly Content-Disposition: inline
(when passing inline = true
, which is the default, and null
as file name), it wont be send by Play automatically anymore. Because, according to RFC 6266 Section 4.2, rendering content inline is the default anyway.
Therefore this change should not effect you at all, since all browsers adhere to the specs and do not treat this header in any special way but to render content inline, like no header was send.
If you still want to send this exact header however, you can still do that by using the withHeader(s)
methods from Scala's
or Java's
Result
class.
§sbt: The playOmnidoc
key now defaults to false
The Play’s sbt plugin key playOmnidoc
, which used to default to true
(for non-snapshot version of Play) now
defaults to false
(and does so in sbt’s Global
scope). The impact is that any Play app that previously
enabled the PlayDocsPlugin
won’t get all the documentation they used when running the app and going tohttp://localhost:9000/@documentation
. You can reverse this change by setting ThisBuild / playOmnidoc :=
true
in your sbt build.
§Updated libraries
This section lists significant updates made to our dependencies.
§Removed libraries
To make the default play distribution a bit smaller we removed some libraries. The following libraries are no longer dependencies in Play 2.8, so you will need to add them manually to your build if you use them.
§Other important changes
Next: Play 2.7