Играть! Framework. Может ли мой шаблон просмотра быть локализованным при рендеринге его как AsyncResult?
Недавно я начал использовать Play! framework (v2.0.4) для написания веб-приложения Java. В большинстве моих контроллеров я следую парадигме приостановления 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! код пытается получить доступ к исходному HTTP-запросу и получить заголовок accept-languages
, чтобы узнать, какой пакет сообщений использовать. Но кажется, что HTTP-запрос недоступен из метода async.
Я вижу пару (неудовлетворительных) способов обойти это:
- Вернитесь к парадигме "один поток для каждого запроса" и блокируйте потоки, ожидающие ответов.
- Определите, какой язык использовать на уровне контроллера, и укажите этот выбор в мой шаблон.
Я также подозреваю, что это может быть не проблема в багажнике. Я знаю, что в 2.0.4 аналогичная проблема связана с тем, что не удалось получить доступ или изменить объект Session
, который недавно был исправлен. Тем не менее я застрял на 2.0.4 на данный момент, так есть лучший способ решить эту проблему?
Ответы
Ответ 1
Собираюсь ответить на мой собственный вопрос здесь. Мой коллега нашел то, что было в конечном счете простым решением:
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()));
}
}));
}
- Получить ссылку на контекст HTTP в начале действия
- Восстановить его в ThreadLocal, когда вы находитесь в блоке
async