Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [servlet-dev] WebSocket and HttpSession

On 12/06/2023 15:27, Greg Wilkins wrote:

Mark,

Something like that might be possible, but I don't really don't like many aspects of this proposal.

Fair enough. Happy to keep discussing until we find a consensus. My aim is to try and find a solution to the problem.

The Session object returned from request.getSession was never intended to be used beyond the scope of the request lifecycle.

I don't think the spec makes that clear one way or the other. I can see how it could be read that way but I can also see the counter argument.

  Putting startAccess/endAccess on the session API would be problematic for several of our implementations as we really don't like objects that have been passivated suddenly becoming active again. Doing so is just asking for races!   Nor are all our implementations intended to be shared between multiple requests, let alone other threads. Thus I think the API needs to be on something else other than the session.

I understand the points you are making. I worry slightly that we are constraining the solution space to suit the current implementations of one container but lets see if using some other object could work.

Applications can call unmatched endAccess.

Fixing that was a detail I was intending to leave until later if the general approach was agreeable.

  It would be far better to have something like access(Consumer<Session>) that could be called with the activated session.  Hmmm but that is blocking.  Maybe something like access(BiConsumer<Session, Runnable>, with the Runnable being the end event.

I like the access(Consumer<Session>) suggestion.

Session access is currently blocking so I'm not overly concerned about blocking vs non-blocking. In what scenarios do you see non-blocking being useful here?

All in all, session semantics are poorly defined enough for incoming HTTP requests, without adding this complication.

Hopefully we can improve the definition of the semantics. I do think defining this behaviour it terms of an HTTP request - even if it isn't - would aid simplicity. Something like:

For the purposes of session access, validity, passivation, activation, etc. the actions taken during this method should be considered equivalent to an HTTP request starting, performing the actions and then finishing. (I'm sure that wording can be improved.)

Actually that might be a better solution: let websocket use actual HTTP requests sent over a local connector to hit the application normally, so all normal session semantics will apply.  I.e. we should provide a simple way to create locally HTTP invocations.

That should be largely doable with the existing API. I don't really like the idea of processing a full HTTP request just to update the session. It seems rather inefficient.

Going back to your "do this via some other object" suggestion, did you have anything in mind?

If we are going to add a access(Consumer<Session>) method then it needs to be added to an object where the current session is implied or we need to provide the session ID as well.

Currently the WebSocket HandshakeRequest doesn't have access to much. The HttpSession looks like the most likely candidate. Something like

Xxxxxxx HttpSession.getXxxxxxx()

where new class Xxxxxxx has the method

Xxxxxxx.access(Consumer<Session>)

(I'm using Xxxxxxx as I can't think of a good name right now.)



Mark



On Mon, 12 Jun 2023 at 12:38, Mark Thomas <markt@xxxxxxxxxx <mailto:markt@xxxxxxxxxx>> wrote:

    On 09/06/2023 18:34, Greg Wilkins wrote:
     > On Thu, 8 Jun 2023 at 17:58, Mark Thomas <markt@xxxxxxxxxx
    <mailto:markt@xxxxxxxxxx>
     > <mailto:markt@xxxxxxxxxx <mailto:markt@xxxxxxxxxx>>> wrote:
     >
     >
     >     My proposal is to add the following method to HttpSession:
     >
     >     public void access()
     >
     >
     > That may not be sufficient, because there are two states of a
    session
     > that websockets needs to avoid: invalidation and passivation!

    I agree the proposal will not be sufficient for all scenarios. However,
    if it is sufficient for some scenarios then I think it is worth
    considering.

     > Having an access method could well prevent invalidation due to an
    idle
     > timeout, but it will stop passivation if that is configured on the
     > container.      Typically a session is passivated some time interval
     > after the active request count goes to 0.  Often this timeout is
    much
     > shorter than the idle timeout and we have some deployments that
    have a
     > zero passivation timeout, so the session is passivated as soon as
    the
     > last request exits the servlet container.
     >
     > A passivated session will not be available to be accessed by a
    websocket
     > endpoint.
     >
     > There are further complications with websocket endpoint accessing
     > sessions.  For example, what is the dirty semantic? i.e. if the
     > websocket endpoint modifies the session, then when are those changes
     > persisted/distributed in the cluster?  We HTTP request, we have
    commit
     > and complete events on which we can flush a dirty session.
     >
     > Session semantics is really poorly defined and barely sufficient for
     > purpose for HTTP requests/responses.   I've very dubious that it's
     > semantics can be extended to websockets without creating some more
     > horrid corner cases.   Very careful thought is needed and I do
    not think
     > there are any simple solutions.

    I agree a complete solution may not be simple. I'm happy to look at the
    wider problem (we have a number of open issues against the Servlet spec
    for those) but I'd also like to make progress on this WebSocket
    issue if
    we can.

    I'm not sure I like it but something that could work would be two
    methods:
    public void startAccess()
    public void endAccess()

    These would be intended for non-HTTP based application components (e.g.
    WebSocket) to work with the session. Roughly (details to be fleshed out
    if the principal is acceptable):

    - startAccess()
        - container treats it as the start of an HTTP request
        - active request count is incremented
        - last access time is updated

    - endAccess()
        - container treats it as the start of an HTTP request
        - active request count is incremented
        - changes to the session are distributed/persisted

    The idea being that if WebSocket (or anything else) wants to update the
    session it needs to do so between startAccess() and endAccess().

    Mark
    _______________________________________________
    servlet-dev mailing list
    servlet-dev@xxxxxxxxxxx <mailto:servlet-dev@xxxxxxxxxxx>
    To unsubscribe from this list, visit
    https://www.eclipse.org/mailman/listinfo/servlet-dev
    <https://www.eclipse.org/mailman/listinfo/servlet-dev>



--
Greg Wilkins <gregw@xxxxxxxxxxx <mailto:gregw@xxxxxxxxxxx>> CTO http://webtide.com <http://webtide.com>

_______________________________________________
servlet-dev mailing list
servlet-dev@xxxxxxxxxxx
To unsubscribe from this list, visit https://www.eclipse.org/mailman/listinfo/servlet-dev


Back to the top