4

最近Playを使い始めました!Java Webアプリケーションを作成するためのフレームワーク(v2.0.4)。私のコントローラーの大部分では、Webサービス応答の約束が果たされるまでHTTP要求を一時停止するというパラダイムに従っています。約束が果たされたら、私はを返します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()));
        }
    }));
}

現在、アプリを国際化しようとしていますが、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]

つまり、ビューテンプレートにメッセージバンドルルックアップがある場合は、Play!コードは、accept-languages使用するメッセージバンドルを知るために、元のHTTPリクエストにアクセスしてヘッダーを取得しようとしています。しかし、非同期メソッドからHTTPリクエストにアクセスできないようです。

これを回避するためのいくつかの(不十分な)方法を見ることができます:

  1. 「リクエストごとに1つのスレッド」パラダイムに戻り、スレッドが応答を待機するのをブロックします。
  2. コントローラレベルで使用する言語を把握し、その選択をテンプレートにフィードします。

また、これはトランクの問題ではないかもしれないと思います。Session最近修正されたオブジェクトにアクセスまたは変更できないことに関して、2.0.4にも同様の問題があることを私は知っています。しかし、私は当分の間2.0.4に固執しているので、この問題を解決するためのより良い方法はありますか?

4

1 に答える 1

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()));
        }
    }));
}
  1. アクションの開始時にHTTPコンテキストへの参照を取得します
  2. asyncブロックに入ったら、ThreadLocalに復元します
于 2012-11-30T17:02:05.473 に答える