Vaadin 14.0.10
Configuration
vaadin.heartbeatInterval=10
server.servlet.session.timeout=90
vaadin.closeIdleSessions=true
vaadin.compatibilityMode = false
After 90 seconds there is a new VaadinSession, but the HTTP session id is the same.
Tried with
vaadin.heartbeatInterval=120
server.servlet.session.timeout=90
vaadin.closeIdleSessions=true
vaadin.compatibilityMode = false
After 90 seconds there is a new VaadinSession, and the HTTP session id changes.
Sample application:
public MainView() {
add(new Span(VaadinSession.getCurrent().getSession().getId()+" "+VaadinSession.getCurrent()));
}
Could that be related to the following plugin for V8? (https://vaadin.com/directory/component/cleanupservlet-add-on)
Your heartbeatInterval=10 in the first example won't let the session expire after your expected 90 seconds.
We need to get this problem resolved ASAP. Can I get a date when you expect to have a fix for this?
Looks like the title of the ticket doesn't match the ticket description and it's not clear what behavior is considered as a bug.
closeIdleSessions=true does not allow HTTP session to expire
It doesn't matter what value closeIdleSessions has : HTTP session won't expire with values
vaadin.heartbeatInterval=10
server.servlet.session.timeout=90
if closeIdleSessions=false either (if I correctly understood the behavior which is considered as a bug here).
closeIdleSessions means :
whether a session should be closed when all its open UIs have
been idle for longer than its configured maximum inactivity time.
A UI is idle if it is open on the client side but has no activity other
than heartbeat requests. If {@code isCloseIdleSessions() == false},
heartbeat requests cause the session to stay open for as long as there
are open UIs on the client side. If it is {@code true}, the session is
eventually closed if the open UIs do not have any user interaction.
I believe there is some misunderstanding here: Vaadin never close/invalidate HttpSession .
The session mentioned in the javadocs is VaadinSession and according to the description this session is closed.
HttpSession stays the same because heartbeat request (the interval set to 10) is sent several times during the interval which is used for HTTP session inactivity check : it's 90. So the HTTP session never expires because there is an activity (sending a heartbeat request) which prevents the session to be closed.
Setting the heartbeat interval value to 120 allows HTTP session expire because the inactivity in this case is longer than session timeout.
So the behavior is correct.
If you want to close HTTP session along with Vaadin session then you may just add a SessionDestroyListener and call HttpSession::invalidate.
Please note that the Vaadin session and the HTTP session are not the same thing. There can be several Vaadin sessions for the same HTTP session, it's not 1:1 but M:1. And this is exactly the reason why HTTP session is never closed by Vaadin : all settings are about Vaadin session which is not 1:1 to HTTP session.
So: do you think I can do something more about this?
It looks like our javadocs for DeploymentConfiguration::isCloseIdleSessions can be improved by removing confusion about session: it should be the Vaadin session (not just a session).
But I don't see what I can do more about this.
@JohnDavidJordan can you take a look at Denis's explanation and see if that makes sense to you?
So javadocs are fixed.
Can we close the ticket ?
So I'm closing the ticket since the functionality works as designed and Javadocs are improved.
What is the value of only destroying Vaadin Session but not Servlet session?
With these settings:
vaadin.heartbeatInterval=10
server.servlet.session.timeout=90
vaadin.closeIdleSessions=true
I'd expect the HTTP session to be closed eventually; perhaps not after 90 seconds but after 90s+3*heartbeats; I'd expect Vaadin to close+detach+disconnect UIs after three missed heartbeats.
The current status and documentation is creating a lot of confusion. Would it be possible to create a list of concrete cases and how Vaadin would react?
It would be really great if someone could link to some working code to achieve what the original posted actually wanted. i have been trying for years to get this right and there is just a lot of misinformation out there now.
What do I need to do to expire a vaadin session (together with its http session) after say 30 minutes of the user staring at the screen not touching a thing? That way the http session can be released, load balancers can start to work, the users session will automatically log out during lunch times making the system data safer.
Just saying that the code is working as designed doesn't help any reader of this issue on how to solve the actual issue the posted asked.
Please help.
Closing VaadinSession does not trigger the closing of HttpSession and and this is intentional. The HttpSession can be shared by multiple VaadinSessions in case you have more than one VaadinServlet inside the same application (packaged inside the same .war).
To kill the underlying HttpSession, once all the VaadinSessions are invalidated (one per each VaadinServlet) you should simply call theInvalidatedVaadinSession.getSession().invalidate(); . As you're probably closing the session automatically, you can register a SessionDestroyListener via VaadinService to do this.
EDIT: if this does not work and the HttpSession stays there, please create a new issue including the code/steps to reproduce the problem.
Quote from the current Vaadin 14 reference card at https://vaadin.com/vaadin-reference-card
_"NOTE:
The HTTP session doesn't expire if there is a browser window open. This is a side effect of the heartbeats. Use the closeIdleSessions configuration parameter to override this behavior."_
Closing
VaadinSessiondoes not trigger the closing ofHttpSessionand and this is intentional. TheHttpSessioncan be shared by multipleVaadinSessions in case you have more than oneVaadinServletinside the same application (packaged inside the same.war).To kill the underlying
HttpSession, once all theVaadinSessions are invalidated (one per eachVaadinServlet) you should simply calltheInvalidatedVaadinSession.getSession().invalidate();. As you're probably closing the session automatically, you can register aSessionDestroyListenerviaVaadinServiceto do this.EDIT: if this does not work and the
HttpSessionstays there, please create a new issue including the code/steps to reproduce the problem.
I have implemented the sessionDestroyListener to close the http session when the Vaadin session is closed. However when my users log out I call VaadinSession.getCurrent().close() as described in https://vaadin.com/docs/v14/flow/advanced/tutorial-application-lifecycle.html in section 'Closing a Session'.
This triggers the sessionDestroy listener, however at this point the session is null and there is no way to either find the http session to invalidate it, or to do any other actions.
Is there a listener that can be called before the actual session is nulled?
I have commented my CDI Vaadin app as follows:
@WebServlet(urlPatterns = "/*", name = "mayapp", asyncSupported = true, initParams = {
@WebInitParam(name = "closeIdleSessions", value = "true")
})
public class ApplicationServlet extends CdiVaadinServlet implements SessionInitListener, SessionDestroyListener, UIInitListener {
And my web.xml has
<session-config>
<session-timeout>30</session-timeout>
</session-config>
From the above discussion I would expect that regardless of the heartbeat setting, when the 30 minutes is up and the user is on lunch leaving his workstation unlocked and browser open, the session will automatically expire and be destroyed.
This doesn't happen - the sessions remain open indefinitely.
Surely this is a common use case for business software (which is the target market for vaadin apps) and is a solved problem?
Also, how do I indicate to a user that the session is about to expire due to inactivity?
Even with closeIdleSessions set to true, the sessions won't close automatically without user action because heartbeats will keep the session alive. So the sequence of events is something like this, assuming a 30 minute session timeout and closeIdleSessions set to true:
10:00 user clicks a button and goes to a meeting leaving the browser window open -> session is extended to close after 10:30
10:05 browser sends a heartbeat request -> session is extended to close after 10:35
10:10 browser sends a heartbeat request -> session is extended to close after 10:40
...
10:46 user returns from the meeting, browser window is still open. Session is due to close after 11:15. UI looks normal.
10:47 user clicks a button. Since the closeIdleSessions property is true and the last non-heartbeat request occurred at 10:00, it means that the session should be invalidated. User gets an "Out of sync" message (or something like that) on the next request.
The IdleAlarm add-on is one way to notify the user that the session is about to expire: https://vaadin.com/directory/component/idlealarm
Thanks Olli.
It seems I misunderstood how closeIdleSessions works, but I also really don't understand the use case for it after your explanation.
I have a very simple and basic use case - as is normal across most web applications. If the user goes out to lunch, after 29 minutes the UI will pop up an idle alarm. If no action is taken, at 30m I need the session to be closed to a) prevent data leakage, b) to release the vaadin session to free memory and c) to free the http session so that server load decreases and my load balancers sticky sessions will be released, thus allowing draining of session from a server being taken down for maintenance.
How do I configure such a scenario please?
@fschon We have the following working for us really well:
This Timer has special cases for:
So overall this reduced the 30min + (3*5min) to 33min (which was okay for us).
The IdleAlarm add-on is one way to notify the user that the session is about to expire: https://vaadin.com/directory/component/idlealarm
This IdleAlarm addon, as with the other similar ones available, is unfortunately for Vaadin Framework 8 and not applicable to this thread. I could not find one for Vaadin Flow in the directory.
@fschon We have the following working for us really well:
- custom heartbeat-interval of 60 seconds (instead of the default 5min)
- close idle sessions = true
- custom HeartBeatHandler that triggers "resetTimer" on our UIs / Components
- custom Timer (component that shows the current session timeout time to the user; which is updated by PUSH if the reset comes from the Heartbeat -> cause user already afk and no "real" interaction)
This Timer has special cases for:
- '> 2 min left? Only update "XYZ min left"
- ==2min left? Auto-Save the current open view (input fields)
- <= 1min left? Logout
So overall this reduced the 30min + (3*5min) to 33min (which was okay for us).
Thanks knoobie. I was hoping not to have to roll my own as this is a pretty standard requirement. Before I do so, is it sure that there is no official vaadin built-in solution to this common requirement?
This triggers the sessionDestroy listener, however at this point the session is null and there is no way to either find the http session to invalidate it, or to do any other actions.
Is there a listener that can be called before the actual session is nulled?
You can get the session from the event object which is passed to your SessionDestroyListener:
service.addSessionDestroyListener(event -> {
VaadinSession session = event.getSession(); // Use this rather than VaadinSession.getCurrent()
// ... your logic
});
Most helpful comment
What is the value of only destroying Vaadin Session but not Servlet session?
With these settings:
I'd expect the HTTP session to be closed eventually; perhaps not after 90 seconds but after 90s+3*heartbeats; I'd expect Vaadin to close+detach+disconnect UIs after three missed heartbeats.
The current status and documentation is creating a lot of confusion. Would it be possible to create a list of concrete cases and how Vaadin would react?