Vaadin 7 - reliable close detection?

Bumping this thread because I’m at a loss to figure this out.

Mark me down as another who is experience session close/clean up issues if an explicit UI.close() is not called (i.e, browser/tab shutdown). The heartbeat doesn’t appear to be honored at all. I’m using PUSH with streaming and Vaadin 7.1.10. This wasn’t a problem when we were using 7.0.x and ICEPush.

I have a DetachListener and a ComponentDetachListener added to the UI. Both of them will call close().

The problem is that the session is not cleaned up if we use different browsers. i.e, use Chrome and open a vaadin session, grab some sort of lock. If the browser/tab is closed then the lock is not released in 3 * heartbeatInterval seconds (ish). Opening a different browser - like Safari long after 3 x heartbeat will show that the lock is still held by the previous session.

If we open the page with the same browser (i.e, Chrome) then the close() will be called at 3 times (both detach listeners plus some other clean up). This leads me to believe that there is a session/cookie identification needed to clean up the previous session. Perhaps the Response that does the clean up is stuck in Atmosphere/Vaadin.

Any guidance would be really helpful. I’ve been staring at this problem for a couple of days now.

Same problem here: (VAADIN 7.1.10)

Here is my observation, if it helps:

  • if Push mode is enabled, NO close within SAFARI browser. Missing detach event is fired when the TOMCAT server is properly shutdown, but that’s too late.
  • if Pushmode is DISABLED, close event appear as expected.

Other browsers like Firefox 26, IE11, Chrome work without a problem in any mode.

Another Thx for clearing the matter.
Gerd

any news about this problem?

i think it is caused by UI lock within getUI().access() method, it blocks the detach event and keeps instance alive with everything it holds… makes push quite useless in some scenarios… funny they have push clock in their examples, because thats example of scenario which will most likely block your instance in memory after closing the tab due to pushing every second…

did you tried this…

i have written this piece of code in my UI class. and working fine…

this.addDetachListener(new DetachListener() {
            public void detach(DetachEvent event) {
                System.out.println("######### Detached ##########");
            }
        });

        JavaScript.getCurrent().addFunction("aboutToClose", new JavaScriptFunction() {
            @Override
            public void call(org.json.JSONArray arguments)
                    throws org.json.JSONException {
                System.out.println("Window/Tab is Closed.");

                //TODO Call Method to Clean the Resource before window/Tab Close.

            }
        });

         Page.getCurrent().getJavaScript().execute("window.onbeforeunload = function (e) { var e = e || window.event; aboutToClose(); return; };");

I have noticed that the “close request” is not received properly when closing UIs that use WebSocket communication. It will happen later at some point if there are no “heartbeat requests”. If you want to release resources eagerly, just set heartbeat interval to some smaller value.

cheers,
matti

this.addDetachListener(new DetachListener() { public void detach(DetachEvent event) { System.out.println("######### Detached ##########"); } }); JavaScript.getCurrent().addFunction("aboutToClose", new JavaScriptFunction() { @Override public void call(org.json.JSONArray arguments) throws org.json.JSONException { System.out.println("Window/Tab is Closed."); //TODO Call Method to Clean the Resource before window/Tab Close. } }); Page.getCurrent().getJavaScript().execute("window.onbeforeunload = function (e) { var e = e || window.event; aboutToClose(); return; };"); It works very well when i close the tab, but it doesn’t work when i close the Firefox application, what’s the difference?
Where can i find the added event in the html page after the execution of vaadin? like:
Thank you.

This worked perfectly for me! Thanks!

Is this still a good way to handle this kind of situation? I also need to do cleanup on closing tabs or windows.

This still works, at least for 7.7.13. In my case, I did this inside my UI.init:

		final UI currentUI = UI.getCurrent();
		currentUI.addDetachListener(e->onDetach(e));
		
        JavaScript.getCurrent().addFunction("aboutToClose", new JavaScriptFunction() {
			@Override
			public void call(JsonArray arguments) {
				if( currentUI.getSession() instanceof VaadinSession )
					LOGGER.info( "Tab being closed for session/UI " + currentUI.getSession() + "/" + currentUI );
				else
					LOGGER.info( "Tab being closed for UI " + currentUI );
				currentUI.detach();
			}
        });

         Page.getCurrent().getJavaScript().execute(
        		 "window.onbeforeunload = function (e) { var e = e || window.event; aboutToClose(); return; };");

In theory, something similar should work in my MPR Vaadin Flow version, but I have not tried it yet.

Shouldn’t something like that be incorporated into the framework? Or does V7/V8 already work like this? You’d still need the heartbeat, I presume, for the case where they just close the browser (or crashes) since you cannot block a browser from ending by running more JavaScript code in that browser.

There might be limitations at the browser level. That seems to be implied in some comments I have read. Why this is not a common feature for browsers to support I don’t know, seems weird to me considering how many people ask the question.

Anyway, does anyone know if this is better supported in Vaadin Flow?

BTW, as per many posts online, onbeforeunload also triggers on other events besides closing tab/browser. So I was calling an add-on to export a Grid to Excel and it triggered this event, which is NOT what I wanted to happen. I only want the closing of the browser tab/window, nothing else. So then I tried onunload, but that seems to be unreliable. It worked in Chrome when I was debugging in Eclipse with Jetty, but did not work in Chrome when I ran it from the server running Tomcat. So just be aware that this seems very unreliable.

I am sort of shocked that something I see questions on going back until at least 2009 still does not have a good solution via HTML or JavaScript. Has no one found anything that works reliably?

Ok, my code worked at one time and now does not. Does anyone know of any changes in the past 10-12 months that would stop the basic idea above to stop working? For instance, browser changes?

Never mind. Somewhere along the way, I made it so I only had this:

Page.getCurrent().getJavaScript().execute(
        		 "window.onunload = function (e) { var e = e || window.event; aboutToClose(); return; };");

Once I added this back, it worked:

         Page.getCurrent().getJavaScript().execute(
        		 "window.onbeforeunload = function (e) { var e = e || window.event; aboutToClose(); return; };");

What is weird is that, with onunload, when I added debugger; to the function definition so it would stop in the browser, it would stop but still not actually call the aboutToClose() method. Regardless, the second I added onbeforeunload, it seemed to work. I will do further testing, but I expect no problems…