VaadinSession - How to detect when a VaadinSession is over?

Hi
Is there anyway in a Vaadin based application (UI object) I can get a notification when a session is gone away? I have some session based data which I need to make sure ‘unsubsribe’ from the backend server for house keeping. Please let me know what the best practices is

thanks
Rajeev

You should be able to do it with a SessionDestroyListener added to the VaadinService. The best place to do that is in a servletInitialized() method in a custom servlet class.

Something like:


class MyServlet extends VaadinServlet {
    @Override
    protected void servletInitialized() throws ServletException {
        super.servletInitialized();
        VaadinService.getCurrent().addSessionDestroyListener(new SessionDestroyListener() {
            ... do your stuff ...
        });
    }
}

Marko,

could a SessionDestroyListener be the solution for fixing this issue as well?


https://vaadin.com/forum/-/message_boards/view_message/2784775

Stefan

Thanks Marko. so if you are extending UI class , then something like below will do the job?

		super.getSession().getService()
				.addSessionDestroyListener(new SessionDestroyListener() {

					@Override
					public void sessionDestroy(SessionDestroyEvent event) {
						

					}
				});

That would create a lot of listeners which would be left in the VaadinService which has much longer lifetime than the UI or VaadinSession instances. Therefore, the only correct place to add them is in a custom servlet.

Well, I suppose you could add them in a UI if you use some mechanism to check that the’re only one such listener.

To Marko Grönroos,

Can you explain more about your answer?

Here, and in other forum responses, and in the Book of Vaadin 7
Lifecycle
page, you suggest subclassing the VaadinServlet.

(a) I find myself reluctant to subclass the core servlet. One vague reason for my reluctance is that it seems that I should not have to subclass the main Vaadin engine – I should be informing Vaadin what I want my app to do after the main engine has been started and warmed up. A more specific reason is that I don’t know how. How does subclassing the servlet affect Eclipse creating my WAR file? Do I have to edit the web.xml file to specify my subclass as the servlet to be run by the web server + Servlet Container? None of that seems “Vaadin-ish”.

(b) You say we should not add to the VaadinService because it has a longer lifetime than a UI or VaadinSession. But wouldn’t our servlet subclass live even longer?

(c) Is there exactly zero or one VaadinService instances for each Vaadin app/servlet in a Servlet Container? Sort of like a class/static member variable on a Java class? In contrast we have potentially many instances of VaadinSession, one instance for each user’s browser accessing the Vaadin app/servlet?

(d) You say:

Do you mean we should only have a single
SessionInitListener
or
SessionDestroyListener
instance for the entire Servlet instance? Usually the “Listener” term suggests a collection of multiple instances all listening and all getting notified (have method invoked) when an event occurs.

Overall, it seems that I and others are finding these basic lifecycle issues (set up & tear down) of Vaadin 7 to be unclear. I would not expect such confusion when answering the simple questions of:
• Where do I write code to set up my user’s app session? (Register JDBC drivers, start logging, configure user-authentication info)
• Where do I write code to clean up when the user’s session ends? (Close database connections, unregister JDBC drivers, stop logging, tell all open UI instances to point their browser window/tab to a logout page)

–Basil Bourque

The servlet is really the only place to do things before a UI is created, especially for handling session initialization, as sessions are created before UIs. Overriding the servlet is a more common task in Vaadin 7 than it was in Vaadin 6, where the Application was essentially a session object. However, VaadinSession shouldn’t be extended like Application was. You can store session parameters, such as a user name or object, in the VaadinSession attributes.

Well, you can do certain tasks elsewhere than in the servlet as well, for example you can define a UIProvider class in web.xml with a UIProvider parameter for the servlet. You can also add UIProviders in a SessionInitListener, so it’s just an alternative way.

Yes you need to use the custom servlet class in the web.xml instead of VaadinServlet. It’s a very simple task.

The VaadinService (or more exactly VaadinServletService) is a member of VaadinServlet with 1:1 relationship, to handle some sub-tasks in the service() method of the servlet class. It is created in the initialization of the servlet, so its lifetime is essentially the same. Its name may be a bit misleading, as it’s not a “service” in the “web service” sense.


As illustrated in the application overview
, VaadinServlet has 1:n VaadinSessions, which in turn has 1:n UIs. I guess there should be a more detailed diagram illustrating also the VaadinService and the lifecycle.

Well, you usually add just one listener, but may sometimes need more. For example, subclasses of VaadinServlet can add a listener at different levels. For example, TouchKitServlet extends Vaadin servlet and adds a SessionInitListener. If you have a custom servlet, which actually is the normal way to configure TouchKit, you could also add a SessionInitListener there. Also, some class that you use in a servlet might want to add such listeners for internal purposes, like the TouchKitSettings class does in TouchKit.

I’d say usually in a SessionInitListener and SessionDestroyListener, but depending on how you need to handle the tasks. For example, you might want to manage a DB connection pool in the servlet (not one connection for each session) and then get a connection from the pool for making each individual request. Well, if you use container binding, you might need to reserve the connections longer.

I suppose it’s
possible
to handle them also with static (or more probably ThreadLocal) references in a UI, in the UI constructor and a DetachListener, but that’s probably not recommended and is more difficult than doing them in a servlet.

You can’t “tell all open UI instances to point their browser window/tab to a logout page” (unless you use server push).

It’s good that you brought this up, it probably needs more attention in the book.

Hi

Just out of interest, why not use a ContextListener instead of a Custom Servlet? something like this:

@WebListener
public class MyContextListener implements ServletContextListener
{
    @Override
    public void contextInitialized(ServletContextEvent event)
    {
            VaadinService.getCurrent().addSessionDestroyListener(new SessionDestroyListener() {
            ... do your stuff ...
            });
    }
}

Would this be too early (before the VaadinService is initialized)?