Mark, Stuart,
The reason I was thinking about asynchronous access was for the case when a container has an aggressive passivation setting, so sessions are passivated either immediately (or soon) after request count goes to zero (or in some deployments after every request when the session instance is not shared between requests). A websocket app might like to hold the session in memory for an extended period of time, which could be done with start/end methods, but not with an access(Consumer<Session>) approach... unless they block within the consumer.
But the flip side of this is that we really don't want websockets pretending to be really long request handling to subvert container configuration. They'd be better off tuning the passivation settings rather than trying to trick them. So, yeah, let's just go blocking.
I also thought about an AutoCloseable based API, but that doesn't provide the Session instance, so the websocket would still need to retain a reference to the session object itself, which I'd really like to avoid.
With regards to limitations from "current implementations of one container", it is not so much what Jetty does, but how I have seen it used in many different deployments. Request and Session objects are often wrapped and have resources associated with them. The session management mechanism is also often extended so we have some big deployments implementing very specific session semantics that fill in the gaps of the specification. So I agree that there is nothing much in the spec either way, on many of these issues, but I do think we have been pretty consistent in saying that references to objects provided by the container should not be kept beyond the request lifecycle.
Thus I do not think it would be good to suddenly after all these decades, suddenly say that it is OK to keep request and/or session references beyond the end of the request lifecycle. Doing so is not going to just break "one container", but many applications/frameworks/deployments that have extended containers based on the non reference assumption.
However, we could add a method to the request or session to get an object that explicitly can be held long term on which the access can be called. This is a bit ugly but would capture the semantic:
Consumer<Consumer<Session>> Session.getAccessor()
I.e when asked, the session can provide a consumer of Consumer<Session> that can be kept long term. When they want to access the session, then call that consumer with their Consumer<Session>, which is called back with the session instance.
We can also allow this method to return null, so that websockets know in advance they can't keep the session active (and fail or take some other action) rather than keeping a reference to the session and hoping it works.
cheers