Session / context lost in Play async / wait

The await() method seems to lose context:

 public static action() { session.put("key", "value"); await(someAsyncCall()); // Now, for some reason the session doesn't have "key" } 

Is this a known issue? Any workarounds?

+1
source share
2 answers

This is unfortunate. Since the session is a local thread variable, it does not pass between new threads (which happens in your example). What is misleading and surprising is that when the code resumes after the wait method, there is a session variable (but this is a different instance).

I would say that this is a mistake - I expect the session context to be maintained around the wait call.

However, I understand why this is difficult. When you use wait, you are actually writing code in at least three threads. Front end, job call / asynchronous call and subsequent part. Watch her, it's awesome.

However, I agree that the session state for the request must be maintained, so I suggest you indicate the problem: https://play.lighthouseapp.com/projects/57987-play-framework/tickets/new

The following is a workaround that copies the session card, passing it through an asynchronous call. You could write a simple Job wrapper that always does this.

 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())); } 

EDIT:

Alternatively, you can save the session map using Cache.set () - this is possibly cleaner than passing it.

As an aside, I rarely use a session to store user data. Each cookie (which is a session in the game) slows down your HTTP requests (read about how cookies work). I prefer to create a server-side map using a cache (e.g. Cache.set (session.getId (), userDataMap)). Obviously, each use case may differ, but I prefer this method to maintain the state of the user.

+2
source

A workaround for the game 1.2.5, if all that is required is to save the session identifier, instead of a direct call, wait for the next (...)

 protected static <T> T awaitSessionAware(Future<T> future) { final String sessionId = session.getId(); T result = await(future); session.put("___ID", sessionId); return result; } 

The above code is a workaround for the problem described here, where a new session is created after calling wait (..) instead of reusing an existing session. The reference to the original session identifier is used to reset the session identifier after a wait call (that is, session.put ("___ ID", sessionId) resets the session identifier to its expected value).

0
source

Source: https://habr.com/ru/post/1402966/


All Articles