How are Response and Result in Play Framework related?
Asked Answered
H

1

5

I am learning Play Framework in Java.

I cannot get a clear understanding of the difference between a Response and a Result. I mean, what is actually sent back, Result or both? Is Response part of Result?

I've been trying to look at the source code. Response contains Cookies and a Map as headers. Result contains Cookies and ResponseHeader, and more stuff like body and session. So there is some overlap.

What confuses me more is code like this:

public Result index() {
    response().setHeader(CACHE_CONTROL, "max-age=3600");
    response().setHeader(ETAG, "xxx");
    return ok("<h1>Hello World!</h1>").as("text/html");
}

I traced the ok() function calling in source code to constructor functions of Result, and it seems not using any data from the Response object in Context that is returned by response() function.

So my questions are:

So the cookies and headers in Response will be finally combined with cookies and headers in Result by the Framework before sent back?

And, if so, What's the rationale of making 2 classes rather than one, and put cookies/headers in 2 places?

If not, does Result includes Response data in someway I have not discovered?

Hakon answered 29/7, 2017 at 15:29 Comment(2)
Could you mention where you saw that code? I don't know the answer to your question but I do know that I've found a lot of outdated and weird code samples online for the Play framework because it's gone through so many revisions, so it would help answerers if they knew where that code came from.Chesser
The code is from 2.6 Play Java documentation. linkHakon
M
7

A play.api.mvc.Result represents a HTTP response; it encapsulates a status code, HTTP headers and a body to be sent to the web client.

Play provides helpers to create create common results e.g. ok(responseBody) is a shortcut to a Result with Http Status 200.

Your controllers will typically return a Result using one of those static helper methods to create the Result instance. However, you may want to tweak the HTTP response encapsulated by the Result instance, perhaps to set header values, by using the response() static helper method.

This helper method sets the response headers in a thread local variable (Context.current()), Play propagates this thread local variable to the thread which handles the HTTP response callback and in that call JavaHelpers.createResult(…) converts the play.mvc.Result instance to its Scala form and invokes withHeaders() and withCookies() copying any headers and cookies which were provided via the response() invocations.

So, in the code you posted:

public Result index() {
    response().setHeader(CACHE_CONTROL, "max-age=3600");
    response().setHeader(ETAG, "xxx");
    return ok("<h1>Hello World!</h1>").as("text/html");
}

The response() calls set headers on a thread local variable, the ok() call creates a play.mvc.Result and in the process of returning this Result to the client Play copies the the headers you provided into that result.

I think this answers:

So the cookies and headers in Response will be finally combined with cookies and headers in Result by the Framework before sent back?

As for this part of the question …

And, if so, What's the rationale of making 2 classes rather than one, and put cookies/headers in 2 places?

… I think only a Play author could explain why this implementation was chosen. Perhaps it is a consequence of Play's two-headedness with the Java implementation being a thin wrapper over the Scala foundations. However, from the perspective of a user of Play it might suffice to know that whatever you set via response() will be merged with whatever Result you create.

Millicent answered 1/8, 2017 at 11:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.