Documentation

You are viewing the documentation for the 2.7.0-M4 development release. The latest stable release series is 3.0.x.

§Java Http.Context changes

Multiple changes were made to Http.Context. The idea is to move more and more away from Http.Context which uses a thread local. The methods on Result are easier to test and harder to misuse.

§Http.Context Request tags removed from args

Request tags, which have been deprecated in Play 2.6, have finally been removed in Play 2.7.
Therefore the args map of a Http.Context instance no longer contains these removed request tags as well.
Instead you can use the contextObj.request().attrs() method now, which provides you the equivalent request attributes.

§CSRF tokens removed from args

The @AddCSRFToken action annotation added two entries named CSRF_TOKEN and CSRF_TOKEN_NAME to the args map of a Http.Context instance. These entries have been removed.
Use the new correct way to get the token.

§Http.Response deprecated

Http.Response was deprecated with other accesses methods to it. It was mainly used to add headers and cookies, but these are already available in play.mvc.Result and then the API got a little confused. For Play 2.7, you should migrate code like:

import play.mvc.Http;
import play.mvc.Result;
import play.mvc.Controller;

public class FooController extends Controller {

    // This uses the deprecated response() APIs
    public Result index() {
        response().setHeader("Header", "Value");
        response().setCookie(Http.Cookie.builder("Cookie", "cookie value").build());
        response().discardCookie("CookieName");
        return ok("Hello World");
    }

}

Should be written as:

import play.mvc.Http;
import play.mvc.Result;
import play.mvc.Controller;

public class FooController extends Controller {

    // This uses the deprecated response() APIs
    public Result index() {
        return ok("Hello World")
                .withHeader("Header", "value")
                .withCookies(Http.Cookie.builder("Cookie", "cookie value").build())
                .discardCookie("CookieName");
    }

}

If you have action composition that depends on Http.Context.response, you can also rewrite it like. For example, the code below:

import play.mvc.Action;
import play.mvc.Http;
import play.mvc.Result;

import java.util.concurrent.CompletionStage;

public class MyAction extends Action.Simple {

    @Override
    public CompletionStage<Result> call(Http.Context ctx) {
        ctx.response().setHeader("Name", "Value");
        return delegate.call(ctx);

    }
}

Should be written as:

import play.mvc.Action;
import play.mvc.Http;
import play.mvc.Result;

import java.util.concurrent.CompletionStage;

public class MyAction extends Action.Simple {

    @Override
    public CompletionStage<Result> call(Http.Context ctx) {
        return delegate.call(ctx)
                .thenApply(result -> result.withHeader("Name", "Value"));
    }
}

§Http.Context.changeLang and Http.Context.clearLang deprecated

That means other methods that depend directly on these two were also deprecated:

  1. play.mvc.Controller.changeLang
  2. play.mvc.Controller.clearLang

The new way of changing lang now is to have a instance of play.i18n.MessagesApi injected and call corresponding play.mvc.Result methods. For example:

§Before

import play.mvc.Result;
import play.mvc.Results;
import play.mvc.Controller;

import play.i18n.MessagesApi;

public class FooController extends Controller {
    public Result action() {
        changeLang(Lang.forCode("es"));
        return Results.ok("Hello");
    }
}

§After

import play.mvc.Result;
import play.mvc.Results;
import play.mvc.Controller;

import play.i18n.MessagesApi;

public class FooController extends Controller {
    private final MessagesApi messagesApi;

    public FooController(MessagesApi messagesApi) {
        this.messagesApi = messagesApi;
    }

    public Result action() {
        return Results.ok("Hello").withLang(Lang.forCode("es"), messagesApi);
    }
}

If you are using changeLang to change the Lang used to render a template, you should now pass the Messages itself as a parameter. This will make the template clearer and easier to read. For example in an action method you have to create a Messages instance like:

Messages messages = this.messagesApi.preferred(Lang.forCode("es"));
return ok(myview.render(messages));

Or if you want to have a fallback to the languages of the request you can do that as well:

Lang lang = Lang.forCode("es");
// Get a Message instance based on the spanish locale, however if that isn't available
// try to choose the best fitting language based on the current request
Messages messages = this.messagesApi.preferred(request().addAttr(Messages.Attrs.CurrentLang, lang));
return ok(myview.render(messages));

Note: To not repeat that code again and again inside each action method you could e.g. create the Messages instance in an action of the action composition chain and save that instance in a request Attribute so you can access it later.

Now the template:

@(implicit messages: play.i18n.Messages)
@{messages.at("hello")}

Note: Declaring messages as implicit will make it available to sub-views that implicitly require a MessagesProvider without the need to pass them one.

And the same applies to clearLang:

§Before

import play.mvc.Result;
import play.mvc.Results;
import play.mvc.Controller;

import play.i18n.MessagesApi;

public class FooController extends Controller {
    public Result action() {
        clearLang();
        return Results.ok("Hello");
    }
}

§After

import play.mvc.Result;
import play.mvc.Results;
import play.mvc.Controller;

import play.i18n.MessagesApi;

public class FooController extends Controller {
    private final MessagesApi messagesApi;

    public FooController(MessagesApi messagesApi) {
        this.messagesApi = messagesApi;
    }

    public Result action() {
        return Results.ok("Hello").clearingLang(messagesApi);
    }
}

§Http.Context.session() deprecated

That means other methods that depend directly on it were also deprecated:

  1. play.mvc.Controller.session()
  2. play.mvc.Controller.session(String key, String value)
  3. play.mvc.Controller.session(String key)

The new way to retrieve the session of a request is the call the session() method of a Http.Request instance.
The new way to manipulate the session is to call corresponding play.mvc.Result methods. For example:

§Before

import play.mvc.Result;
import play.mvc.Results;
import play.mvc.Controller;

public class FooController extends Controller {
    public Result info() {
        String user = session("current_user");
        return Results.ok("Hello " + user);
    }

    public Result login() {
        session("current_user", "[email protected]");
        return Results.ok("Hello");
    }

    public Result logout() {
        session().remove("current_user");
        return Results.ok("Hello");
    }

    public Result clear() {
        session().clear();
        return Results.ok("Hello");
    }
}

§After

import play.mvc.Result;
import play.mvc.Results;
import play.mvc.Controller;

public class FooController extends Controller {
    public Result info() {
        String user = request().session().get("current_user");
        return Results.ok("Hello " + user);
    }

    public Result login() {
        return Results.ok("Hello")
            .addingToSession(request(), "current_user", "[email protected]");
    }

    public Result logout() {
        return Results.ok("Hello")
            .removingFromSession(request(), "current_user");
    }

    public Result clear() {
        return Results.ok("Hello")
            .withNewSession();
    }
}

§Http.Context.flash() deprecated

That means other methods that depend directly on it were also deprecated:

  1. play.mvc.Controller.flash()
  2. play.mvc.Controller.flash(String key, String value)
  3. play.mvc.Controller.flash(String key)

The new way to retrieve the flash of a request is the call the flash() method of a Http.Request instance.
The new way to manipulate the flash is to call corresponding play.mvc.Result methods. For example:

§Before

import play.mvc.Result;
import play.mvc.Results;
import play.mvc.Controller;

public class FooController extends Controller {
    public Result info() {
        String message = flash("message");
        return Results.ok("Message: " + message);
    }

    public Result login() {
        flash("message", "Login successful");
        return Results.redirect("/dashboard");
    }

    public Result logout() {
        flash().remove("message");
        return Results.redirect("/");
    }

    public Result clear() {
        flash().clear();
        return Results.redirect("/");
    }
}

§After

import play.mvc.Result;
import play.mvc.Results;
import play.mvc.Controller;

public class FooController extends Controller {
    public Result info() {
        String message = request().flash().get("message");
        return Results.ok("Message: " + message);
    }

    public Result login() {
        return Results.redirect("/dashboard")
            .flashing("message", "Login successful");
    }

    public Result logout() {
        return Results.redirect("/")
            .removingFromFlash("message");
    }

    public Result clear() {
        return Results.redirect("/")
            .withNewFlash();
    }
}

Next: Play 2.6