Are orphaned sessions harvested?

I’ve created a simple vaadin application with a table on a page that is dynamically updated using the ICEpush addon from a thread I create in the attach() method of the panel. Each time it updates the page, it logs a message.

If I use ?restartApplication or restart my browser to get a fresh session then I start to see double the amount of log messages. The thread attached to the orphaned session continues to updated the table even though no client is connected.

Is there a way to harvest these orphan sessions? Is there a way to detect if the client is no longer connected and kill the thread I have created and Application instance?

Thanks, Tom

I am not familiar with ICEpush addon, but You can implement manualy
HTTP session listener
, attach it to Your application and stops the thread using appropriate way for ICEpush by implementing sessionDestroyed method.

Hi Radek,

In essence my application is like this:

public class MyApp extends Application {

ICEPush icepush = new ICEPush();
Table myTable = new Table()

publc void init() {

 mainWindow.add(icepush)
 mainWindow.add( myTable );

 new BackgroundThread().start();

}

public class BackgroundThread extends Thread {

    @Override
    public void run() {
        log.info("Started background thread to update table");

        while (true) {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {

            }

            updateTable(myTable)

        }

    }
}

}

I need the background thread to stop when the user has closed their browser/session has expired.
Can Http session listener help with this? if so - can you show me an example?

Or is there some way to do while (!getApplication.isExpired() ?

Thanks, Tom

3 things that comes to my mind are the corrections to Your code:

  1. Instead of extending Thread, try to implement Runnable interface like this:
public class BackgroundThread implements Runnable {
  public void run() {
    ...
  }
}

And start the thread like this:

new Thread( new BackgroundThread() ).start();
  1. According to
    Thread’s Java API
    You shouldn’t directly call stop() and - what is connected to this - using endless loop like “while( true )”. Instead of this, there should be some e.g. boolean field which works as “switch” which says to running thread it should stop ASAP. This switch should be checked once a time e,g,:
public class BackgroundThread implements Runnable {
  boolean switch = true;

  public void run() {
    while( switch ) {
      ...
    }
  }

  public void stopWorking() {
    this.switch = false;
  }
}

And when You want this thread to stop working - You just invoke method “stopWorking()” on instance of this thread.

  1. From the code snippet I see that You want to update table from another thread so user will have table updated periodically. I guess it will not work as You expect because of Vaadin nature as a framework. UI (in You case - table) will be refreshed when User make some interaction to the server (e.g. click something). This is harder to achieve. Please read
    this thread
    and read about
    Refresher addon
    .

About implementing session listener I have to go to home and I’ll give You detailed info.

Application’s init() method implementation could be like this:

public class MyApp extends Application {
  BackgroundThread thread;

  publc void init() {
    mainWindow.add(icepush)
    mainWindow.add( myTable );

    this.thread = new BackgroundThread();
    new Thread( this.thread ).start();

  }

  public BackgroundThread getThread() {
    return this.thread;
  }
}

Session listener implementation could be like this (draft):

public class ThreadCleanerListener implements HttpSessionListener {

  public void sessionCreated( HttpSessionEvent sessionEvent ) {
    ...
  }

  public void sessionDestroyed( HttpSessionEvent sessionEvent ) {
    final WebApplicationContext waContext = WebApplicationContext.getApplicationContext( sessionEvent.getSession() );
    final Iterator< Application > appIt = waContext.getApplications().iterator();
    if ( appIt.hasNext() ) {
      final Application app = appIt.next();
      app.getThread().stopWorking();
    } else {
      ...no application exists for this session.
    }
  }
}

Additionaly in BackgroundThread run method there could be passed instance of application which created this thread and in thread could be checking if application is running: while( switch && this.app.isRunning() )

Thank you for your thorough answer. I will try and implement this.
I have a couple of questions -

  1. At which point application lifecycle does isRunning() return false?
  2. At which point is session destroyed?

Thanks, Tom

I will answer in reverse order:

Session can be destroyed in 1 of 2 ways (generally):

  • You directly invalidate session by calling
    invalidate()
    on HttpSession object.
    In this case, session could be manualy invalidated when user logs out from the application - it depends on Your application use case/business logic.
  • session is timed out (then, container invalidates session). This happens when user closes the browser window without logging out. Timeout depends on Your application - is it 30 minutes (regular application) or 10 minutes (banking system).

Application is bind to session in Vaadin. isRunning can happen, when You somehow have reference to application instance, but this application is not bounded to any running session or application was already closed (somehow, e.g. by calling manually
close() method
).

Hi Radek,
Well I finally found some time to implement this and I did exactly how you suggested and it seems to work perfectly so thankyou!!!

You mention that I need to use the refresher plugin to update the page - I am actually using Icepush plugin to push changes to the page.

Thank you also for clarifying about session destruction and application lifecycle.

Cheers, Tom

Quick note: you want to declare that boolean field volatile or else there’s no guarantee that the running thread will see a change in its value. That’s the kind of error that won’t show up until months after your code is in production. :slight_smile:

Cheers,
Bobby