玩!框架 - 将我的视图模板渲染为AsyncResult时,是否可以对其进行本地化?

avi*_*vik 4 internationalization playframework-2.0

我最近开始使用Play!用于编写Java Web应用程序的框架(v2.0.4).在我的大多数控制器中,我遵循暂停HTTP请求的范例,直到满足Web服务响应的承诺.一旦履行承诺,我就会回复AsyncResult.这就是我的大多数动作都是这样的(省略了一堆代码):

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()));
        }
    }));
}
Run Code Online (Sandbox Code Playgroud)

我现在正在尝试国际化我的应用程序,但在尝试从async方法渲染模板时遇到以下错误:

[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]
Run Code Online (Sandbox Code Playgroud)

简而言之,我在视图模板中有一个消息包查找,一些Play!代码试图访问原始HTTP请求并检索accept-languages标头,以便知道要使用哪个消息包.但似乎异步方法无法访问HTTP请求.

我可以看到一些(不令人满意的)解决方法:

  1. 回到'每个请求一个线程'范例,让线程阻塞等待响应.
  2. 找出在Controller级别使用哪种语言,并将该选择提供给我的模板.

我也怀疑这可能不是主干上的问题.我知道2.0.4中存在类似的问题,即无法访问或修改Session最近修复过的对象.但是我暂时停留在2.0.4上,那么有更好的方法可以解决这个问题吗?

avi*_*vik 5

要在这里回答我自己的问题.我的一位同事发现了最终的简单解决方案:

public static Result myActionMethod() {

    final Context ctx = ctx(); // (1)
    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) {

            Context.current.set(ctx); // (2)

            // Validate response...
            return ok(myScalaViewTemplate.render(response.data()));
        }
    }));
}
Run Code Online (Sandbox Code Playgroud)
  1. 在操作开始时获取对HTTP上下文的引用
  2. 一旦你进入async街区,就在ThreadLocal中恢复它

  • 这应该在2.1.0中修复 (2认同)