2012-12-31 70 views
1

看來await()方法失去方面:會話/上下文播放異步丟失/伺機

public static action() { 
    session.put("key", "value"); 
    await(someAsyncCall()); 

    // Now, for some reason the session doesn't have "key" 
} 

這是一個已知的問題?任何解決方法?

回答

2

這是不幸的。由於會話是線程局部變量,因此它不會在新線程之間傳遞(這發生在您的示例中)。什麼是誤導和令人驚訝的是,當代碼在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))。顯然,每個用例可能會有所不同,但我更喜歡這種方式來維護用戶狀態。

+0

順便說一句,這個錯誤是由相同的行爲引起的:https://play.lighthouseapp.com/projects/57987/tickets/1180-session-id-changes-with-suspended-requests –

0

變通辦法對於播放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重置爲其預先等待值)。

+0

也許一些解釋會有所幫助。 – MrBoJangles