看來await()
方法失去方面:會話/上下文播放異步丟失/伺機
public static action() {
session.put("key", "value");
await(someAsyncCall());
// Now, for some reason the session doesn't have "key"
}
這是一個已知的問題?任何解決方法?
看來await()
方法失去方面:會話/上下文播放異步丟失/伺機
public static action() {
session.put("key", "value");
await(someAsyncCall());
// Now, for some reason the session doesn't have "key"
}
這是一個已知的問題?任何解決方法?
這是不幸的。由於會話是線程局部變量,因此它不會在新線程之間傳遞(這發生在您的示例中)。什麼是誤導和令人驚訝的是,當代碼在await方法後恢復時有一個會話變量(但它是一個不同的實例)。
我會說這是一個錯誤 - 我希望會話環境在await調用周圍維護。
這就是說,我明白爲什麼這是棘手的。當你使用await時,你實際上至少在三個線程中編寫代碼。前一部分,工作/異步調用和後一部分。追蹤它,這有點令人驚異。
即使如此,我同意了該請求的會話狀態應該保持,所以我建議您提交的問題:https://play.lighthouseapp.com/projects/57987-play-framework/tickets/new
下面是一個變通方法,副本使其通過異步調用的會話映射。你可以寫一個簡單的包裝器Job,總是這樣做。
public static void test() {
Logger.debug("before: Session.current() " + Session.current());
Session.current().put("key", new Date().toString());
Job<Session> async = new Job<Session>() {
Session sessionPassed = Session.current();
@Override
public Session doJobWithResult() throws Exception {
Logger.debug("during job: Session.current() "
+ Session.current());
Logger.debug("during job: sessionPassed " + sessionPassed);
Thread.sleep(1000L);
// you could do something like this to wrap a real
// async call and maintain the session context. If
// the async job returns a result, you'll have to return
// a map or POJO with the session and the result.
actualJob.now();
return sessionPassed;
}
};
Session sessionReturned = await(async.now());
Logger.debug("after: Session.current() ="
+ (Session.current() == null ? "no session" : Session.current()));
Logger.debug("after: " + sessionReturned);
Session.current().all().putAll(sessionReturned.all());
Logger.debug("finally: "
+ (Session.current() == null ? "no session" : Session.current()));
}
編輯:
或者,你可以存儲使用Cache.set會議地圖() - 這也許不是圍繞它傳遞乾淨。
另外,我很少使用會話來存儲用戶數據。每個cookie(這是一個會話在播放的內容)會減慢你的http請求(瞭解cookie的工作原理)。我更喜歡使用Cache在服務器端創建一個映射(例如Cache.set(session.getId(),userDataMap))。顯然,每個用例可能會有所不同,但我更喜歡這種方式來維護用戶狀態。
變通辦法對於播放1.2.5,如果是需要的只是堅持會話ID,請使用以下的地方直接調用的等待(...)
protected static <T> T awaitSessionAware(Future<T> future) {
final String sessionId = session.getId();
T result = await(future);
session.put("___ID", sessionId);
return result;
}
上面的代碼是一個解決問題的解決方法here其中在await(..)調用後創建新會話,而不是重用現有會話。對原始會話ID的引用用於在等待呼叫之後重置會話ID(即,session.put(「___ID」,sessionId)將會話ID重置爲其預先等待值)。
也許一些解釋會有所幫助。 – MrBoJangles
順便說一句,這個錯誤是由相同的行爲引起的:https://play.lighthouseapp.com/projects/57987/tickets/1180-session-id-changes-with-suspended-requests –