Detecting a session timeout

I’m currently working with Vaadin 6.x and building some web apps that run in Tomcat containers. I am not using SessionGuard and I don’t particularly care if a session times out - but I do need to be able to detect the fact that it [b]
[i]

[/i]has
[/b] timed out. This is an area I’m not familiar with - how can I tell that a session is gone so I can do the necessary cleanup tasks on the server?

thanks,

nbc

That’s done with standard Java servlet coding based on javax.servlet.http.HttpSessionListener. Here’s an example:

@WebListener
public class SessionListener
    implements javax.servlet.http.HttpSessionListener
{
    
	public SessionListener()
	{
	}
    
    // For HttpSessionListener interface
	public void sessionCreated(HttpSessionEvent se)
	{
        Application.getInstance().getSessionTracker().addSession(se.getSession());
	}
	
    // For HttpSessionListener interface
	public void sessionDestroyed(HttpSessionEvent se)
	{
        Application.getInstance().getSessionTracker().removeSession(se.getSession());
	}
}

That makes sense - I can implement the listener, but can you tell me where I hook it into the Vaadin application? I can create the class (and I added the listener info in my web.xml file) but I’m not sure how to set it up so it actually gets invoked…

Thanks,

nbc

Let me expand on my question a bit. I have created a class that implements the HTTPSessionListener interface and added it to the web.xml file. Now when I enter the URL of my application, it looks like it invokes the sessionCreated method. For my purposes, this is happening before I’m ready for it - I need to know who logs in, not just the fact that they have connected to the URL. And at the moment, I don’t seem to be seeing any calls to the sessionDeleted routine at all - not even if I close my browser, and certainly not when I log off the application and return to the login screen.

So I could use a bit more help - I obviously don’t know enough about the underlying structure of the web app - time to do some digging there. But if someone could point me in the right direction, I’d be grateful.

My application is set up like this:

My application class initializes a few things and then calls my Login page. The user enters a username and password, and if it is valid, they go on to the main part of the app. At that point (user validation) I want to record the fact that they are logged in (and may be logged in from different system with the same username). I can handle this without the session handler.

When they log out explicitly, I can remove the user from my internal tables. The program then returns to the login page. I’m guessing that may not actually delete the original session - is that correct? Do I need to invalidate the session explicitly? If I do, what causes a new session to be created - just returning to the login page?

And the problem I was originally trying to solve is the one where the user logs in and then walks away from the terminal. Eventually their tomcat session times out - but I need to know which user was involved in the timeout. If someone has an example of something like that, I’d like to see it.

Thanks,

nbc

  1. Yes, closing theApplication does not destroy the session. Vaddin can support more than one Application per session (e.g. for different URLs)

  2. If your Application#close method deals with tidying up the internal tables, what you want to do ensure that the application is closed when the session is destroyed. I’m doing a bit of tinkering in this area of our system at the moment - and here’s an HttpSessionListener that ensures that the Application(s) associated with the destroyed session are closed.

HTH,

Cheers,

Charles.


import com.vaadin.Application;
import com.vaadin.terminal.gwt.server.WebApplicationContext;
// Etc

public class ApplicationClosingListener implements HttpSessionListener {
  @Override
  public void sessionCreated(HttpSessionEvent httpSessionEvent) {
    // Deliberate no-op
  }

  @Override
  public void sessionDestroyed(HttpSessionEvent event) {
    HttpSession session = event.getSession();
    if (session == null) {
      return;
    }

    WebApplicationContext context = WebApplicationContext.getApplicationContext(session);
    if (context == null) {
      return;
    }
    Collection<Application> applications = context.getApplications();

    for (Application application : applications) {
      application.close();
    }

  }
}

I suspect I’m not doing this correctly with Vaadin. At the moment, I’m not actually calling the Application.close() method at all - perhaps I should be…

What happens in my setup is that I have a ‘Quit’ button on the page, and when the user selects that, I erase all the internal info for that user, and transfer back to the Login page. I don’t close the application at that time. So it would seem to me that my sessions will only be deleted after a timeout (based on the Tomcat setup parameters, I assume) or when I physically stop and restart the Tomcat process. The rest of the time, there will be one session open for any user who connects to the URL where my application is located…

nbc

What we do in our logoff handler is cleanup and then we call close() on the Application. I don’t know how many people have multiple applications in a session, but that’s an interesting thing to note if you do.

What we have found is that you go back to a login URL that is a vaadin app, a new session would then start up. In our case, the login page is a regular JSP and so landing on the login page doesn’t cause a session to be restarted.

We also redirect to a logoff page, which ends the session after it renders the final page saying they have logged off, and then redirects back to the login page.

I’m sure there are all sorts of ways, but you do want to close the application and end the session on logoff to start over clean, otherwise you’ll have sessions lingering until they expire within the servlet container.

It sounds like I should be closing the application when the user hits the quit button - would it be possible for you to show me a code snippet that does that correctly? In other words, something I could invoke from the button listener when the user hits the Quit button - what exactly would I need to do to:

a) properly terminate the session
b) transfer to my login page - which is not the original application URL - just a page inside the application

Or is that even possible? This is where I get confused - the actual code flow - do I need to go back to the original URL and invoke the application.init() routine again to start a new session? That routine does transfer to my login page when it finishes, so I could do that - but I’m not sure how to get there from the quit button…

Thanks in advance,

nbc

Well, this is just how we do it, not necessarily the best way to do it, and we’re on the 6.x branch of Vaadin, not the new 7 where things no doubt change.

We have a subclassed Application that we use. It creates a MainWindow that creates a Button for logoff.

    	logoffButton.addListener( new Button.ClickListener() {
			@Override
			public void buttonClick(ClickEvent event) {
                EsfVaadinApplication vaadinApp = EsfVaadinApplication.getInstance();
				vaadinApp.logoffUser();
			}
		}); 

Then in our application subclass, our logoffUser does the following (use the Application.setLogoutURL() to set the URL for our logoff page (which in our case displays a message and ends the HttpSession and redirects to the login page after 5 seconds):

	public void logoffUser() {
		User user = getUser(); // retrieve User object stored in HttpSession
		
		if ( user != null ) {
			user.logoff(); // user cleanup, logging, etc.
		}
		
		close(); // shutdown the Application session
	}

You can override close() in your Application subclass if you want to do something there (like when the session times out, this gets called I believe). We just log some stuff in ours:

	@Override
	public void close() {
		_logger.debug("close()");
		User user = getUser();
		if ( user != null ) {
			user.logLoginLogoff("EsfVaadinApplication closed on session expiration for " + user.getFullDisplayName());
		}
		super.close();
		requestSession = null;
	}

Hope that helps some… As I said, we did note that the login page was in the Vaadin app, a new session will get started to display the login page (which is why we chose our login page to be a JSP outside of Vaadin). Also, if the login page then sits for a while, the new session will timeout, so when the user returns to login later may get that session expired exception. There may be a better way to handle that, but our choice was just to move the login/logoff pages outside of Vaadin.

I’m using V6.x at the moment as well - so this should help. I will take a look at it and see if I can replicate the behavior in my system - from a quick look, I think it should not be difficult. I’ll let you know what happens on Monday. Thanks very much for the help!

nbc