Play! Framework - Can my view template be localised when rendering it as an AsyncResult?

Posted by avik on Stack Overflow See other posts from Stack Overflow or by avik
Published on 2012-11-16T11:11:15Z Indexed on 2012/11/30 17:04 UTC
Read the original article Hit count: 169

I've recently started using the Play! framework (v2.0.4) for writing a Java web application. In the majority of my controllers I'm following the paradigm of suspending the HTTP request until the promise of a web service response has been fulfilled. Once the promise has been fulfilled, I return an AsyncResult. This is what most of my actions look like (with a bunch of code omitted):

public static Result myActionMethod() {

    Promise<MyWSResponse> wsResponse;
    // Perform a web service call that will return the promise of a MyWSResponse...

    return async(wsResponse.map(new Function<MyWSResponse, Result>() {
        @Override
        public Result apply(MyWSResponse response) {

            // Validate response...
            return ok(myScalaViewTemplate.render(response.data()));
        }
    }));
}

I'm now trying to internationalise my app, but hit the following error when I try to render a template from an async method:

[error] play - Waiting for a promise, but got an error: There is no HTTP Context available from here.
java.lang.RuntimeException: There is no HTTP Context available from here.
    at play.mvc.Http$Context.current(Http.java:27) ~[play_2.9.1.jar:2.0.4]
    at play.mvc.Http$Context$Implicit.lang(Http.java:124) ~[play_2.9.1.jar:2.0.4]
    at play.i18n.Messages.get(Messages.java:38) ~[play_2.9.1.jar:2.0.4]
    at views.html.myScalaViewTemplate$.apply(myScalaViewTemplate.template.scala:40) ~[classes/:na]
    at views.html.myScalaViewTemplate$.render(myScalaViewTemplate.template.scala:87) ~[classes/:na]
    at views.html.myScalaViewTemplate.render(myScalaViewTemplate.template.scala) ~[classes/:na]

In short, where I've got a message bundle lookup in my view template, some Play! code is attempting to access the original HTTP request and retrieve the accept-languages header, in order to know which message bundle to use. But it seems that the HTTP request is inaccessible from the async method.

I can see a couple of (unsatisfactory) ways to work around this:

  1. Go back to the 'one thread per request' paradigm and have threads block waiting for responses.
  2. Figure out which language to use at Controller level, and feed that choice into my template.

I also suspect this might not be an issue on trunk. I know that there is a similar issue in 2.0.4 with regards to not being able to access or modify the Session object which has recently been fixed. However I'm stuck on 2.0.4 for the time being, so is there a better way that I can resolve this problem?

© Stack Overflow or respective owner

Related posts about internationalization

Related posts about playframework-2.0