Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jetty: IllegalStateException on WebSocket connection lost #20783

Open
mperktold opened this issue Dec 23, 2024 · 3 comments
Open

Jetty: IllegalStateException on WebSocket connection lost #20783

mperktold opened this issue Dec 23, 2024 · 3 comments

Comments

@mperktold
Copy link

Description of the bug

We get the following errors:

Invalid for read: id=node0xdir7h1o3wfh1d3gb3f0z9drn0 not resident
	java.lang.IllegalStateException: Invalid for read: id=node0xdir7h1o3wfh1d3gb3f0z9drn0 not resident
		at org.eclipse.jetty.session.ManagedSession.checkValidForRead(ManagedSession.java:479)
		at org.eclipse.jetty.session.ManagedSession.getAttribute(ManagedSession.java:487)
		at org.eclipse.jetty.ee10.servlet.SessionHandler$ServletSessionApi.getAttribute(SessionHandler.java:342)
		at com.vaadin.flow.server.WrappedHttpSession.getAttribute(WrappedHttpSession.java:54)
		at com.vaadin.flow.server.VaadinService.readFromHttpSession(VaadinService.java:2236)
		at com.vaadin.flow.server.VaadinService.loadSession(VaadinService.java:2212)
		at com.vaadin.flow.server.VaadinService.findUI(VaadinService.java:1179)
		at com.vaadin.flow.server.communication.PushHandler.handleConnectionLost(PushHandler.java:433)
		at com.vaadin.flow.server.communication.PushHandler.connectionLost(PushHandler.java:370)
		at com.vaadin.flow.server.communication.PushAtmosphereHandler.onStateChange(PushAtmosphereHandler.java:62)
		at org.atmosphere.cpr.AsynchronousProcessor.invokeAtmosphereHandler(AsynchronousProcessor.java:538)
		at org.atmosphere.cpr.AsynchronousProcessor.completeLifecycle(AsynchronousProcessor.java:480)
		at org.atmosphere.cpr.AsynchronousProcessor.endRequest(AsynchronousProcessor.java:584)
		at org.atmosphere.websocket.DefaultWebSocketProcessor.executeClose(DefaultWebSocketProcessor.java:689)
		at org.atmosphere.websocket.DefaultWebSocketProcessor.close(DefaultWebSocketProcessor.java:635)
		at org.atmosphere.container.JSR356Endpoint.onClose(JSR356Endpoint.java:318)
		at org.eclipse.jetty.ee10.websocket.jakarta.common.JakartaWebSocketFrameHandler.notifyOnClose(JakartaWebSocketFrameHandler.java:295)
		at org.eclipse.jetty.ee10.websocket.jakarta.common.JakartaWebSocketFrameHandler.onClosed(JakartaWebSocketFrameHandler.java:273)
		at org.eclipse.jetty.websocket.core.WebSocketCoreSession.lambda$closeConnection$0(WebSocketCoreSession.java:248)
		at org.eclipse.jetty.server.handler.ContextHandler$ScopedContext.run(ContextHandler.java:1507)
		at org.eclipse.jetty.server.handler.ContextHandler$ScopedContext.run(ContextHandler.java:1500)
		at org.eclipse.jetty.websocket.core.server.internal.AbstractHandshaker$1.handle(AbstractHandshaker.java:179)
		at org.eclipse.jetty.websocket.core.WebSocketCoreSession.lambda$closeConnection$1(WebSocketCoreSession.java:248)
		at org.eclipse.jetty.util.Callback$4.completed(Callback.java:227)
		at org.eclipse.jetty.util.Callback$Completing.succeeded(Callback.java:384)
		at org.eclipse.jetty.ee10.websocket.jakarta.common.JakartaWebSocketFrameHandler.onError(JakartaWebSocketFrameHandler.java:315)
		at org.eclipse.jetty.websocket.core.WebSocketCoreSession.lambda$closeConnection$2(WebSocketCoreSession.java:260)
		at org.eclipse.jetty.server.handler.ContextHandler$ScopedContext.run(ContextHandler.java:1513)
		at org.eclipse.jetty.server.handler.ContextHandler$ScopedContext.run(ContextHandler.java:1500)
		at org.eclipse.jetty.websocket.core.server.internal.AbstractHandshaker$1.handle(AbstractHandshaker.java:179)
		at org.eclipse.jetty.websocket.core.WebSocketCoreSession.closeConnection(WebSocketCoreSession.java:260)
		at org.eclipse.jetty.websocket.core.WebSocketCoreSession.onEof(WebSocketCoreSession.java:230)
		at org.eclipse.jetty.websocket.core.WebSocketConnection.onClose(WebSocketConnection.java:209)
		at org.eclipse.jetty.io.SelectorManager.connectionClosed(SelectorManager.java:347)
		at org.eclipse.jetty.io.ManagedSelector$DestroyEndPoint.run(ManagedSelector.java:1094)
		at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:979)
		at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.doRunJob(QueuedThreadPool.java:1209)
		at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1164)
		at java.base/java.lang.Thread.run(Unknown Source)

Apparently, when the web socket is closed or loses connection, it tries to find the associated Vaadin UI instance. But if the underlying session has been closed already, the getAttribute method throws this exception.

It has probably something to do with us manually calling vaadinSession.getSession().invalidate().

Expected behavior

There should not be an exception when the web socket is closed.

Minimal reproducible example

I haven't been able to reproduce this yet. I've tried creating a button with a click listener that calls vaadinSession.getSession().invalidate() and waiting until the web socket is closed, but that alone doesn't seem to be enough.

Versions

  • Vaadin / Flow version: 24.4.20
  • Java version: openjdk version "21.0.5" 2024-10-15 LTS
    OpenJDK Runtime Environment Temurin-21.0.5+11 (build 21.0.5+11-LTS)
    OpenJDK 64-Bit Server VM Temurin-21.0.5+11 (build 21.0.5+11-LTS, mixed mode, sharing)
  • OS version: Windows 11
@mcollovati
Copy link
Collaborator

What Jetty version are you using? Do you have custom configuration for Jetty SessionCache or SessionDataStore?

@mcollovati
Copy link
Collaborator

mcollovati commented Dec 31, 2024

Looking at the code, it seems the HTTP session gets invalidated right after PushHandler got the VaadinSession from it.

        VaadinSession session = null;
        try {
            session = service.findVaadinSession(vaadinRequest);   // <----- Gets VaadinSession from HTTP session 
        } catch (SessionExpiredException e) {
            ....
            return session;
        }

        UI ui;
        session.lock();
        try {
            VaadinSession.setCurrent(session);
            ui = service.findUI(vaadinRequest); // <----- Failure is caused by this calls

When service.findVaadinSession(vaadinRequest) is called, the HTTP session is still valid, otherwise the IllegalStateException would have been raised there.
However, service.findUI(vaadinRequest) is called, the HTTP session is not valid anymore.

@mcollovati
Copy link
Collaborator

Currently, I cannot see a way to handle this exception, other than suppressing the log in DefaultErrorHandler

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: 🆕 Needs triage
Development

No branches or pull requests

2 participants