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

Cannot invoke "org.atmosphere.cpr.AtmosphereResource.getBroadcaster()" because the return value of "com.vaadin.flow.server.communication.AtmospherePushConnection.getResource()" is null #15571

Closed
pogocode opened this issue Dec 22, 2022 · 11 comments · Fixed by #15767

Comments

@pogocode
Copy link

pogocode commented Dec 22, 2022

Upon session destruction through HttpSession.invalidate(), the following stack trace is often seen:

java.lang.RuntimeException: Push failed
    at com.vaadin.flow.server.communication.AtmospherePushConnection.push (AtmospherePushConnection.java:200)
    at com.vaadin.flow.server.communication.AtmospherePushConnection.push (AtmospherePushConnection.java:175)
    at com.vaadin.flow.component.UI.push (UI.java:702)
    at com.vaadin.flow.server.VaadinSession.unlock (VaadinSession.java:718)
    at com.vaadin.flow.server.VaadinService.ensureAccessQueuePurged (VaadinService.java:2025)
    at com.vaadin.flow.server.VaadinService.accessSession (VaadinService.java:1992)
    at com.vaadin.mpr.core.MprServletService.accessSession (MprServletService.java:165)
    at com.vaadin.server.VaadinSession.access (VaadinSession.java:1427)
    at com.vaadin.server.VaadinService.fireSessionDestroy (VaadinService.java:532)
    at com.vaadin.server.VaadinSession.valueUnbound (VaadinSession.java:313)
    at org.eclipse.jetty.server.session.Session.unbindValue (Session.java:349)
    at org.eclipse.jetty.server.session.Session.callSessionAttributeListeners (Session.java:327)
    at org.eclipse.jetty.server.session.Session.finishInvalidate (Session.java:953)
    at org.eclipse.jetty.server.session.SessionHandler.invalidate (SessionHandler.java:1232)
    at org.eclipse.jetty.server.session.DefaultSessionIdManager.invalidateAll (DefaultSessionIdManager.java:486)
    at org.eclipse.jetty.server.session.Session.invalidate (Session.java:854)
    at com.vaadin.flow.server.WrappedHttpSession.invalidate (WrappedHttpSession.java:101)
    at org.vaadin.mprdemo.LegacyView.lambda$attach$0 (LegacyView.java:35)
    at java.util.concurrent.Executors$RunnableAdapter.call (Executors.java:539)
    at java.util.concurrent.FutureTask.run (FutureTask.java:264)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run (ScheduledThreadPoolExecutor.java:304)
    at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1136)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:635)
    at java.lang.Thread.run (Thread.java:833)
Caused by: java.lang.NullPointerException: Cannot invoke "org.atmosphere.cpr.AtmosphereResource.getBroadcaster()" because the return value of "com.vaadin.flow.server.communication.AtmospherePushConnection.getResource()" is null
    at com.vaadin.flow.server.communication.AtmospherePushConnection.sendMessage (AtmospherePushConnection.java:215)
    at com.vaadin.flow.server.communication.AtmospherePushConnection.push (AtmospherePushConnection.java:198)
    at com.vaadin.flow.server.communication.AtmospherePushConnection.push (AtmospherePushConnection.java:175)
    at com.vaadin.flow.component.UI.push (UI.java:702)
    at com.vaadin.flow.server.VaadinSession.unlock (VaadinSession.java:718)
    at com.vaadin.flow.server.VaadinService.ensureAccessQueuePurged (VaadinService.java:2025)
    at com.vaadin.flow.server.VaadinService.accessSession (VaadinService.java:1992)
    at com.vaadin.mpr.core.MprServletService.accessSession (MprServletService.java:165)
    at com.vaadin.server.VaadinSession.access (VaadinSession.java:1427)
    at com.vaadin.server.VaadinService.fireSessionDestroy (VaadinService.java:532)
    at com.vaadin.server.VaadinSession.valueUnbound (VaadinSession.java:313)
    at org.eclipse.jetty.server.session.Session.unbindValue (Session.java:349)
    at org.eclipse.jetty.server.session.Session.callSessionAttributeListeners (Session.java:327)
    at org.eclipse.jetty.server.session.Session.finishInvalidate (Session.java:953)
    at org.eclipse.jetty.server.session.SessionHandler.invalidate (SessionHandler.java:1232)
    at org.eclipse.jetty.server.session.DefaultSessionIdManager.invalidateAll (DefaultSessionIdManager.java:486)
    at org.eclipse.jetty.server.session.Session.invalidate (Session.java:854)
    at com.vaadin.flow.server.WrappedHttpSession.invalidate (WrappedHttpSession.java:101)
    at org.vaadin.mprdemo.LegacyView.lambda$attach$

In turn, this means that any SessionDestroyListeners registered to be executed upon Vaadin session destruction will not be called (see com.vaadin.flow.server.VaadinService#fireSessionDestroy) as the exception is not caught.

Looking at the code, it seems that there is some attempt to guard against the resource being null, but it does appear that the resource is null at the point the push is attempted.

Minimal Reproducible Example

The following application exhibits this behaviour:

mpr-demo-mpr-6-atmosphere-push.zip

Start the application:

mvn -Pproduction jetty:run

Navigate to the following, which will open the view and schedule a session invalidation in 5 seconds time.

http://localhost:8080/legacy

View console output, see stack trace as shown in Actual Behaviour sction

Expected behaviour

All SessionDestroyListeners should be allowed to run as part of session destruction, even in the case of issues with the AtmospherePushConnection.

Actual behaviour

Exception thrown and SessionDestroyListeners not executed:

java.lang.RuntimeException: Push failed
    at com.vaadin.flow.server.communication.AtmospherePushConnection.push (AtmospherePushConnection.java:200)
    at com.vaadin.flow.server.communication.AtmospherePushConnection.push (AtmospherePushConnection.java:175)
    at com.vaadin.flow.component.UI.push (UI.java:702)
    at com.vaadin.flow.server.VaadinSession.unlock (VaadinSession.java:718)
    at com.vaadin.flow.server.VaadinService.ensureAccessQueuePurged (VaadinService.java:2025)
    at com.vaadin.flow.server.VaadinService.accessSession (VaadinService.java:1992)
    at com.vaadin.mpr.core.MprServletService.accessSession (MprServletService.java:165)
    at com.vaadin.server.VaadinSession.access (VaadinSession.java:1427)
    at com.vaadin.server.VaadinService.fireSessionDestroy (VaadinService.java:532)
    at com.vaadin.server.VaadinSession.valueUnbound (VaadinSession.java:313)
    at org.eclipse.jetty.server.session.Session.unbindValue (Session.java:349)
    at org.eclipse.jetty.server.session.Session.callSessionAttributeListeners (Session.java:327)
    at org.eclipse.jetty.server.session.Session.finishInvalidate (Session.java:953)
    at org.eclipse.jetty.server.session.SessionHandler.invalidate (SessionHandler.java:1232)
    at org.eclipse.jetty.server.session.DefaultSessionIdManager.invalidateAll (DefaultSessionIdManager.java:486)
    at org.eclipse.jetty.server.session.Session.invalidate (Session.java:854)
    at com.vaadin.flow.server.WrappedHttpSession.invalidate (WrappedHttpSession.java:101)
    at org.vaadin.mprdemo.LegacyView.lambda$attach$0 (LegacyView.java:35)
    at java.util.concurrent.Executors$RunnableAdapter.call (Executors.java:539)
    at java.util.concurrent.FutureTask.run (FutureTask.java:264)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run (ScheduledThreadPoolExecutor.java:304)
    at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1136)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:635)
    at java.lang.Thread.run (Thread.java:833)
Caused by: java.lang.NullPointerException: Cannot invoke "org.atmosphere.cpr.AtmosphereResource.getBroadcaster()" because the return value of "com.vaadin.flow.server.communication.AtmospherePushConnection.getResource()" is null
    at com.vaadin.flow.server.communication.AtmospherePushConnection.sendMessage (AtmospherePushConnection.java:215)
    at com.vaadin.flow.server.communication.AtmospherePushConnection.push (AtmospherePushConnection.java:198)
    at com.vaadin.flow.server.communication.AtmospherePushConnection.push (AtmospherePushConnection.java:175)
    at com.vaadin.flow.component.UI.push (UI.java:702)
    at com.vaadin.flow.server.VaadinSession.unlock (VaadinSession.java:718)
    at com.vaadin.flow.server.VaadinService.ensureAccessQueuePurged (VaadinService.java:2025)
    at com.vaadin.flow.server.VaadinService.accessSession (VaadinService.java:1992)
    at com.vaadin.mpr.core.MprServletService.accessSession (MprServletService.java:165)
    at com.vaadin.server.VaadinSession.access (VaadinSession.java:1427)
    at com.vaadin.server.VaadinService.fireSessionDestroy (VaadinService.java:532)
    at com.vaadin.server.VaadinSession.valueUnbound (VaadinSession.java:313)
    at org.eclipse.jetty.server.session.Session.unbindValue (Session.java:349)
    at org.eclipse.jetty.server.session.Session.callSessionAttributeListeners (Session.java:327)
    at org.eclipse.jetty.server.session.Session.finishInvalidate (Session.java:953)
    at org.eclipse.jetty.server.session.SessionHandler.invalidate (SessionHandler.java:1232)
    at org.eclipse.jetty.server.session.DefaultSessionIdManager.invalidateAll (DefaultSessionIdManager.java:486)
    at org.eclipse.jetty.server.session.Session.invalidate (Session.java:854)
    at com.vaadin.flow.server.WrappedHttpSession.invalidate (WrappedHttpSession.java:101)
    at org.vaadin.mprdemo.LegacyView.lambda$attach$0 (LegacyView.java:35)
    at java.util.concurrent.Executors$RunnableAdapter.call (Executors.java:539)
    at java.util.concurrent.FutureTask.run (FutureTask.java:264)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run (ScheduledThreadPoolExecutor.java:304)
    at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1136)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:635)
    at java.lang.Thread.run (Thread.java:833)

Versions:

Vaadin Framework: 8.16.1
Flow: 23.2.5
MPR: 6.0.2
Java JRE / JDK: 17
openjdk 17.0.2 2022-01-18 LTS
OpenJDK Runtime Environment Corretto-17.0.2.8.1 (build 17.0.2+8-LTS)
OpenJDK 64-Bit Server VM Corretto-17.0.2.8.1 (build 17.0.2+8-LTS, mixed mode, sharing)

@pogocode
Copy link
Author

Now updated with a minimal application exhibiting this behaviour. It seems that this exception occurs when the HttpSession is invalidated (which could be through some means other than via the Vaadin API, for example if the servlet container decides to destroy the seesion).

@pogocode
Copy link
Author

I've also confirmed that same issue occurs on Vaadin 23.3.1 / MPR 6.1.0.

@TatuLund
Copy link
Contributor

Thanks for the issue report. As this is quite clearly not bug in Vaadin 8, but possibly something either in Flow or MPR, I am going to move the ticket to either one of the repositories.

@TatuLund
Copy link
Contributor

MPR 6.1.0.

Just noting that 6.1.1 exists already. https://github.com/vaadin/multiplatform-runtime/releases/tag/6.1.1

@TatuLund TatuLund transferred this issue from vaadin/framework Dec 23, 2022
@TatuLund
Copy link
Contributor

May be related to #14887

And possibly fixed by #15517

@mcollovati
Copy link
Collaborator

mcollovati commented Dec 23, 2022

Still happens event with the fix.
I noticed that when push() is invoked the state of AtmospeherePushConnection is CONNECTED, but when sendMessage is called the AtmosphereResource is null.
It seems like that this happens because Vaadin 8 UI.setSession(...) is called with null and it starts a Thread that sets push connection to null, thus invoking disconnect() on Flow PushConnection

https://github.com/vaadin/framework/blob/master/server/src/main/java/com/vaadin/ui/UI.java#L517-L526

@mcollovati
Copy link
Collaborator

I can confirm that the problem is originated by the thread started by Vaadin 8 to disconnect PUSH.
Now we need to check if this should be fixed in Flow, MPR or Vaadin 8 (less probable)

@mcollovati mcollovati added the MPR label Dec 28, 2022
mcollovati added a commit that referenced this issue Jan 27, 2023
Disconnecting an AtmospherePushConnection while it is sending a message
may result in a NullPointerException if AtmosphereResource is nullified
before the message is sent.
This change synchronizes operations, so that disconnect will wait until
current push finishes, or push waits for disconnect to complete so that
the isConnected() method reflects correctly current state.

Fixes #15571
mshabarov pushed a commit that referenced this issue Feb 3, 2023
* fix: prevent concurrent disconnect and push operations

Disconnecting an AtmospherePushConnection while it is sending a message
may result in a NullPointerException if AtmosphereResource is nullified
before the message is sent.
This change synchronizes operations, so that disconnect will wait until
current push finishes, or push waits for disconnect to complete so that
the isConnected() method reflects correctly current state.

Fixes #15571

* fixed test
OLD Vaadin Flow bugs & maintenance (Vaadin 10+) automation moved this from New P2 to Closed Feb 3, 2023
vaadin-bot pushed a commit that referenced this issue Feb 3, 2023
* fix: prevent concurrent disconnect and push operations

Disconnecting an AtmospherePushConnection while it is sending a message
may result in a NullPointerException if AtmosphereResource is nullified
before the message is sent.
This change synchronizes operations, so that disconnect will wait until
current push finishes, or push waits for disconnect to complete so that
the isConnected() method reflects correctly current state.

Fixes #15571

* fixed test
vaadin-bot pushed a commit that referenced this issue Feb 3, 2023
* fix: prevent concurrent disconnect and push operations

Disconnecting an AtmospherePushConnection while it is sending a message
may result in a NullPointerException if AtmosphereResource is nullified
before the message is sent.
This change synchronizes operations, so that disconnect will wait until
current push finishes, or push waits for disconnect to complete so that
the isConnected() method reflects correctly current state.

Fixes #15571

* fixed test
vaadin-bot pushed a commit that referenced this issue Feb 3, 2023
* fix: prevent concurrent disconnect and push operations

Disconnecting an AtmospherePushConnection while it is sending a message
may result in a NullPointerException if AtmosphereResource is nullified
before the message is sent.
This change synchronizes operations, so that disconnect will wait until
current push finishes, or push waits for disconnect to complete so that
the isConnected() method reflects correctly current state.

Fixes #15571

* fixed test
vaadin-bot added a commit that referenced this issue Feb 3, 2023
* fix: prevent concurrent disconnect and push operations

Disconnecting an AtmospherePushConnection while it is sending a message
may result in a NullPointerException if AtmosphereResource is nullified
before the message is sent.
This change synchronizes operations, so that disconnect will wait until
current push finishes, or push waits for disconnect to complete so that
the isConnected() method reflects correctly current state.

Fixes #15571

* fixed test

Co-authored-by: Marco Collovati <marco@vaadin.com>
vaadin-bot added a commit that referenced this issue Feb 3, 2023
* fix: prevent concurrent disconnect and push operations

Disconnecting an AtmospherePushConnection while it is sending a message
may result in a NullPointerException if AtmosphereResource is nullified
before the message is sent.
This change synchronizes operations, so that disconnect will wait until
current push finishes, or push waits for disconnect to complete so that
the isConnected() method reflects correctly current state.

Fixes #15571

* fixed test

Co-authored-by: Marco Collovati <marco@vaadin.com>
vaadin-bot added a commit that referenced this issue Feb 3, 2023
* fix: prevent concurrent disconnect and push operations

Disconnecting an AtmospherePushConnection while it is sending a message
may result in a NullPointerException if AtmosphereResource is nullified
before the message is sent.
This change synchronizes operations, so that disconnect will wait until
current push finishes, or push waits for disconnect to complete so that
the isConnected() method reflects correctly current state.

Fixes #15571

* fixed test

Co-authored-by: Marco Collovati <marco@vaadin.com>
mcollovati added a commit that referenced this issue Feb 6, 2023
Disconnecting an AtmospherePushConnection while it is sending a message
may result in a NullPointerException if AtmosphereResource is nullified
before the message is sent.
This change synchronizes operations, so that disconnect will wait until
current push finishes, or push waits for disconnect to complete so that
the isConnected() method reflects correctly current state.

Fixes #15571
mshabarov pushed a commit that referenced this issue Feb 6, 2023
Disconnecting an AtmospherePushConnection while it is sending a message
may result in a NullPointerException if AtmosphereResource is nullified
before the message is sent.
This change synchronizes operations, so that disconnect will wait until
current push finishes, or push waits for disconnect to complete so that
the isConnected() method reflects correctly current state.

Fixes #15571
@vaadin-bot
Copy link
Collaborator

This ticket/PR has been released with Vaadin 23.2.16.

@vaadin-bot
Copy link
Collaborator

This ticket/PR has been released with Vaadin 23.3.6.

@vaadin-bot
Copy link
Collaborator

This ticket/PR has been released with Vaadin 14.9.6.

@vaadin-bot
Copy link
Collaborator

This ticket/PR has been released with Vaadin 24.0.0.beta2 and is also targeting the upcoming stable 24.0.0 version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment