Play 2.6 introduced the usage of Akka’s Coordinated Shutdown but still didn’t use it all across the core framework or exposed it to the end user. Coordinated Shutdown is an Akka Extension with a registry of tasks that can be run in an ordered fashion during the shutdown of the Actor System.

Coordinated Shutdown internally handles Play 2.7 Play’s lifecycle and an instance of CoordinatedShutdown is available for injection. Coordinated Shutdown gives you fine grained phases - organized as a directed acyclic graph (DAG) - where you can register tasks instead of just having a single phase like Play’s application lifecycle. For example, you can add tasks to run before or after server binding, or after all the current requests finishes. Also, you will have better integration with Akka Cluster.

Guice, the default dependency injection framework used by Play, was upgraded to 4.2.2 (from 4.1.0). Have a look at the 4.2.2, 4.2.1 and the 4.2.0 release notes. This new Guice version introduces breaking changes, so make sure you check the Play 2.7 Migration Guide.

Until Play 2.6, the only way to retrieve a file that was uploaded via a multipart/form-data encoded form was by callingrequest.body().asMultipartFormData().getFile(...) inside the action method.

Starting with Play 2.7 such an uploaded file will now also be bound to a Java Form. If you are not using a custom multipart file part body parser all you need to do is add a FilePart of type TemporaryFile to your form:

If the binding was successful (form validation passed) you can access the file:

MyForm myform = form.get();
myform.getMyFile();

Some useful methods were added as well to work with uploaded files:

// Get all files of the form
form.files();
// Access the file of a Field instance
Field myFile = form.field("myFile");
field.file();
// To access a file of a DynamicForm instance
dynamicForm.file("myFile");

All of the constraint annotations defined by play.data.validation.Constraints are now @Repeatable. This change lets you, for example, reuse the same annotation on the same element several times but each time with different groups. For some constraints however it makes sense to let them repeat itself anyway, like @ValidateWith:

When using advanced validation features you can now pass a ValidationPayload object, containing useful information sometimes needed for a validation process, to a Java validate or isValid method.To pass such a payload to a validate method just annotate your form with @ValidateWithPayload (instead of just @Validate) and implement ValidatableWithPayload (instead of just Validatable):

Note: Don’t get confused with ValidationPayload and ConstraintValidatorContext: The former class is provided by Play and is what you use in your day-to-day work when dealing with forms in Play. The latter class is defined by the Bean Validation specification and is used only internally in Play - with one exception: This class emerges when your write your own custom class-level constraints, like in the last example above, where you only need to pass it on to the reportValidationStatus method however anyway.

Play now offers a CacheApi implementation based on Caffeine. Caffeine is the recommended cache implementation for Play users.

To migrate from EhCache to Caffeine you will have to remove ehcache from your dependencies and replace it with caffeine. To customize the settings from the defaults, you will also need to update the configuration in application.conf as explained in the documentation.

The previous setting of enabling CSP by default and setting it to default-src 'self' was too strict, and interfered with plugins. The CSP filter is not enabled by default, and the contentSecurityPolicy in the SecurityHeaders filter is now deprecated and set to null by default.

The CSP filter uses Google’s Strict CSP policy by default, which is a nonce based policy. It is recommended to use this as a starting point, and use the included CSPReport body parsers and actions to log CSP violations before enforcing CSP in production.

Play WS enables you to create play.libs.ws.WSRequestFilter to inspect or enrich the requests made. Play provides a “log as curl” filter, but this was lacking for Java developers. You can now write something like:

Play 2.7 brings two new implementations for play.api.http.HttpErrorHandler. The first one is JsonHttpErrorHandler, which will return errors formatted in JSON and is a better alternative if you are developing an REST API that accepts and returns JSON payloads. The second one is HtmlOrJsonHttpErrorHandler which returns HTML or JSON errors based on the preferences specified in client’s Accept header. It is a better option if your application uses a mixture of HTML and JSON, as is common in modern web apps.