Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vaadin 14: remove broadcast registration on page refresh

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?

like image 644
user15905221 Avatar asked May 26 '21 09:05

user15905221


2 Answers

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.

like image 69
Erik Lumme Avatar answered Oct 21 '22 15:10

Erik Lumme


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.

like image 3
ollitietavainen Avatar answered Oct 21 '22 17:10

ollitietavainen