I guess this question applies to all versions of Vaadin, but for now I am asking about Vaadin 7. What triggers the detach? In my case, I close a browser window, but the corresponding UI is not “detached” until I shut down the entire VaadinSession with VaadinSession.invalidate(). I wanted it to be detached sooner. I tried catching the onunload and onbeforeunload events, but of course those can be tricky. So maybe understanding when the detachment occurs would help me find another solution to my problem.
I assume you mean UI detach specifically? The JavaDoc of the method says:
/**
* Called before the UI is removed from the session. A UI instance is
* detached exactly once, either:
* <ul>
* <li>after it is explicitly {@link #close() closed}.
* <li>when its session is closed or expires
* <li>after three missed heartbeat requests.
* </ul>
* <p>
* Note that when a UI is detached, any changes made in the {@code detach}
* methods of any children or {@link DetachListener}s that would be
* communicated to the client are silently ignored.
*/
although the “after three missed heartbeat requests” line is a bit vague; I think there needs to be another request after the missed heartbeats to trigger the detaching, otherwise the session needs to expire.
-Olli
OK, first step is to do a simple experiment: Login to my website on two browser tabs ( so same VaadinSession, different UIs ), close one of the tabs, and see how long it takes to “detach” that corresponding UI. If the heartbeat actually works and the document is accurate, it should “detach” after about 15 minutes ( based on the default heartbeat settings ).
My goal is to detach it as quickly as possible so I can, in my “onDetach” method, cleanup some resources connected to that UI. But maybe I am being too hasty, maybe the heartbeat does what I want, just takes longer than I was expecting.
Ok, if I wait 15+ minutes, “detach” is called. It is not 15 minutes exactly, of course, probably because of timing issues. So I guess this answers my question. I could reduce the heartbeat interval, as per the documentation, but this is such a weird situation ( user closes browser without logging out ) that I don’t think it is worth it.
Users close browsers without logging off routinely around here. We tried training, but it’s amazing how closing tabs/browsers is the default way to dismiss it when done.
Closing browser windows is perfectly logical from a user perspective, albeit irritating to us developers, and probably unsafe in many cases.
What I find shocking is that you can find stackoverflow posts at least as far back as 2009 asking how to know when the browser window/tab closes, and yet browsers are still resistant to that, or inconsistent in the handling of onunload. Granted, people tried to use onunload incorrectly ( to stop users from leaving page or popup a “are you sure” message ), instead of using onbeforeunload, but that is a separate issue. In my case, onunload worked in Eclipse debugging, but then stopped working on the server. Currently decided to just depend on the heartbeat timeout. Not as speedy, but works OK.
@ollit.1 What was the motivation behind not using three consecutive heartbeats to clear the UI on the server when its the only ui. why does it then need to wait for the session to expire? I don’t understand the motivation behind this decision.
Here you note that when the user closes the entire browser window (effectively closing all UIs at once so that no UI stays open, the heartbeat mechanism is no longer effective.
Note, however, that the heartbeat mechanism is only effective as long as there is at least one open UI. This happens because the detection of closed UIs on the server is only done every time there is a Vaadin request to the same session. Thus, if the user closes the entire browser window, waiting for three missed heartbeats doesn’t automatically free the UIs for garbage collection. The normal User Session Expiration mechanism covers situations where all UIs have been closed.
You then explain that the heartbeat interval can be changed:
The heartbeats occur at an interval of 5 minutes, which can be changed with the
heartbeatIntervalparameter of the servlet.
But for the special case where session-expiration comes into play you seem to talk about a state where all UIs are closed and then the session still lives for the duration of session timeout. But this state can never happen as at least the last UI will only be cleaned up after this same session timeout:
When all UIs have expired, the user session still remains. It’s removed from the server when the HTTP session timeout configured in the web application elapses, and the whole HTTP session is invalidated.
What am I missing?
And how would i configure the session timeout?
Setting server.servlet.session.timeout=1m did not work. the session was closed, but after a way longer duration than one minute.
For Science I set my last tab that still had my vaadin application open offline and waited. After waiting 10 minutes (which was really hard for a millennial like me) the UI was finally cleaned up on the server.
Is 10 minutes the default? I thought it was 30m.
What was the motivation behind not using three consecutive heartbeats to clear the UI on the server when its the only ui. why does it then need to wait for the session to expire? I don’t understand the motivation behind this decision.
If there’s only one UI and its browser tab is closed, there’s nothing happening (no requests coming) that could be used to trigger a cleanup action on the server.
Session timeout configuration depends on your setup. With Spring Boot, it’s server.session.timeout in application.properties. Minimum timeout is one minute (at least for Tomcat).