How to extract result content from play.mvc.Result object in play application?
Asked Answered
R

7

5

actually I am doing redirect from one play application to another play application, finally I receive response as Result object.. Below is the action in two applications. I am redirecting from apllication1 to application2. Application 2 will return JSON string, that I need to extract.

How can I retrieve JSON content from Result object?

Application1:

public static Result redirectTest(){

    Result result =  redirect("http://ipaddress:9000/authenticate");
    /*** here I would like to extract JSON string from result***/
    return result;
}

Application2:

@SecuredAction
public static Result index() {
     Map<String, String> response = new HashMap<String, String>();
     DemoUser user = (DemoUser) ctx().args.get(SecureSocial.USER_KEY);

       for(BasicProfile basicProfile: user.identities){
           response.put("name", basicProfile.firstName().get());
           response.put("emailId", basicProfile.email().get());
           response.put("providerId", basicProfile.providerId());
           response.put("avatarurl", basicProfile.avatarUrl().get());
       }

    return ok(new JSONObject(response).toString());
}
Rangefinder answered 10/10, 2014 at 13:55 Comment(0)
O
7

I think play.test.Helpers.contentAsString is what you're looking for.

public static java.lang.String contentAsString(Result result)

Extracts the content as String.

Still available in Play 2.8.x.

Otolith answered 2/5, 2019 at 14:0 Comment(0)
F
5

Use JavaResultExtractor, example:

Result result = ...;
byte[] body = JavaResultExtractor.getBody(result, 0L);

Having a byte array, you can extract charset from Content-Type header and create java.lang.String:

String header = JavaResultExtractor.getHeaders(result).get("Content-Type");
String charset = "utf-8";
if(header != null && header.contains("; charset=")){
    charset = header.substring(header.indexOf("; charset=") + 10, header.length()).trim();
}
String bodyStr = new String(body, charset);
JsonNode bodyJson = Json.parse(bodyStr);

Some of above code was copied from play.test.Helpers

Fibro answered 10/10, 2014 at 14:4 Comment(3)
JavaResultExtractor.getBody(result, 0L) gives timeout even if i change it from 0 to 100kLandgrave
Wondering why don't use play.test.Helpers.contentAsString(result) ?Touchandgo
Helpers class have test scope.Fibro
A
2

This functions works fine for me.. Thanks to Mon Calamari

public static JsonNode resultToJsonNode(Result result) {

    byte[] body = JavaResultExtractor.getBody(result, 0L);

    ObjectMapper om = new ObjectMapper();
    final ObjectReader reader = om.reader();
    JsonNode newNode = null;
    try {
        newNode = reader.readTree(new ByteArrayInputStream(body));
        Logger.info("Result Body in JsonNode:" + newNode.toString());
    } catch (JsonProcessingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return newNode;
}

}

Azerbaijani answered 16/12, 2015 at 7:4 Comment(1)
JavaResultExtractor.getBody is giving timeoutexception, even if i increased value from 0 to 100k.Landgrave
P
2

You'll need to pass an instance of akka.stream.Materializer into JavaResultExtractor's getbody method.

Use Google Guice for Injecting at constructor level or declaration level.

@Inject
Materializer materializer;

and Further you can convert Result into String or any other type as required:

    Result result = getResult(); // calling some method returning result
    ByteString body = JavaResultExtractor.getBody(result, 1, materializer);
    String stringBody = body.utf8String(); // get body as String.
    JsonNode jsonNodeBody = play.libs.Json.parse(stringBody); // get body as JsonNode.
Paralogism answered 27/6, 2017 at 10:45 Comment(1)
After one and a half days of searching, this was the only place where I found this solution for "creating" a "Materializer" in Play-2.5-context. This should really have been mentioned in the migration guide from Play 2.4 to Play 2.5...Frostwork
C
1

redirect return results with error code 303, which cause the caller (browser) to do another request to the given url.
What you need to do is actually proxying. Application1 should make a request to Application2, and handle the response.
Play have very nice Web Service API which allow doing this easily.

Caphaitien answered 11/10, 2014 at 8:10 Comment(0)
I
0

In the context of a controller method you could try:

import play.libs.Json;
import play.mvc.Result;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.node.ObjectNode;
...
public static Result redirectTest(){
     ObjectNode body = (ObjectNode) request().body().asJson();
     String providerId = body.get("providerId").asText();
}

This SO question may also help: JSON and Play

Incapacitate answered 10/10, 2014 at 14:35 Comment(0)
C
-1

First i write this scala method to convert Enumerator[Array[Byte]] to Future[Array[Byte]]:

class EnumeratorHelper {

  def getEnumeratorFuture(body: Enumerator[Array[Byte]]) ={
    Iteratee.flatten(body |>> Iteratee.consume[Array[Byte]]()).run
  }

}

Then convert returned Future to Promise and finally get promise value:

final F.Promise<Result> finalResultPromise = delegate.call(ctx);
finalResultPromise.onRedeem(result -> {
    F.Promise<byte[]> requestBodyPromise = F.Promise.wrap(new EnumeratorHelper().getEnumeratorFuture(result.toScala().body()));

    requestBodyPromise.onRedeem(bodyByte -> handleBody(new String(bodyByte, "UTF-8")));

});
Casuistry answered 5/1, 2016 at 6:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.