Vaadin 14: remove broadcast registration on page refresh
Asked Answered
J

3

5

I followed the Vaadin tutorial (Creating Collaborative Views) for broadcasting events and register on them.

Registration eventRegistration;

@Override
protected void onAttach(AttachEvent attachEvent) {
    log.debug("In attach...");
    UI ui = attachEvent.getUI();
    eventRegistration= Broadcaster.register(
        "eventName", 
        message -> ui.access(() -> {
           log.debug("Request to refresh grid...");
           presenter.refreshGrid();
           ui.push();
        }));
}

@Override
protected void onDetach(DetachEvent detachEvent) {
    log.debug("In detach...");
    if(eventRegistration != null) {
        eventRegistration.remove();
        eventRegistration = null;
    }
}

Everything works except the fact that when refreshing the page, the logic in the onDetach() is not executed. After refresh, however, you will enter the onAttach() method. Because of this you are actually going to register several of 'the same' listeners without removing the previous one and you actually get a doubling of listeners. The onDetach() method is only accessed if you go to another menu item, for example.

You can find an example log below. application log

What is the Vaadin recommended way to remove these listeners before/during refresh?

Juggle answered 26/5, 2021 at 9:52 Comment(0)
B
4

The onDetach method should be called eventually.

No event is sent to the server when you close or refresh a tab, and as such the server is not aware that the old UI should be detached.

This is where the heartbeat requests come in. The UIs send heartbeat requests every 5 minutes per default, and if the server notices that the old UI has missed three heartbeats, it will be detached. Alternatively, it will be detached when the session expires.

In other words, the onDetach method should be called after about 20 minutes.

The reason no event is sent to the server when the tab is closed or refreshed is that this could prevent the tab from refreshing/closing while the request is being handled, which is bad user experience. Also, this wouldn't cover the cases where the computer is turned off or the network disconnected.

There is something called the Beacon API that could be used to notify the server when a tab is refreshed or closed without causing a delay in the browser. There is an issue for using this to immediately detach UIs.

Bachelor answered 26/5, 2021 at 10:17 Comment(0)
H
3

I'd recommend using the Unload Beacon add-on: https://vaadin.com/directory/component/unload-beacon-for-vaadin-flow or a similar approach which is demonstrated in the Cookbook: https://cookbook.vaadin.com/notice-closed - essentially, it's executing the JavaScript snippet to add an event listener for Window's unload event:

ui.getElement().executeJs(
"window.addEventListener('unload', function() {navigator.sendBeacon && navigator.sendBeacon($0)})", relativeBeaconPath);

and the beacon is sent to a custom SynchronizedRequestHandler.

Herrmann answered 26/5, 2021 at 10:29 Comment(0)
R
0

Simplest way to workaround the problem would be checking if eventRegistration is null before adding one.

@Override
protected void onAttach(AttachEvent attachEvent) {
    log.debug("In attach...");
    UI ui = attachEvent.getUI();
    if (eventRegistration == null) {
       eventRegistration= Broadcaster.register(
          "eventName", 
          message -> ui.access(() -> {
             log.debug("Request to refresh grid...");
             presenter.refreshGrid();
             ui.push();
          }));
    }
}

Check the other answer by Erik why calling of onDetach is delayed.

Regulable answered 26/5, 2021 at 10:18 Comment(2)
This is not possible in my case. The Registration instance 'eventRegistration' is a class field of a view (extends PolymerTemplate). So refreshing the view always results in a Registration instance with value null so it will cause the same behavior.Juggle
I see, I obviously thought that you are using PreserveOnRefresh, but yes, you did not state that.Regulable

© 2022 - 2024 — McMap. All rights reserved.