The implementation of the counter of active sessions, some issues

I welcome!

I’m trying to implement a counter of active sessions, approximately as shown below.

Listener -


...
public class SessionCounter implements ServletContextListener, 
		HttpSessionListener {
	private ServletContext servletContext;//
	private int counter;//
	
	@Override
	public void sessionCreated(HttpSessionEvent se) {
		incrementUserCounter();
	}
	@Override
	public void sessionDestroyed(HttpSessionEvent se) {
		decrementUserCounter();
	}
	@Override
	public void contextInitialized(ServletContextEvent sce) {
		servletContext = sce.getServletContext();
		servletContext.setAttribute(("userCounter"), Integer.toString(this.counter));		
	}
	
	@Override	
	public void contextDestroyed(ServletContextEvent sce) {
	}
	/**
	 * 
	 */
	synchronized void incrementUserCounter() {
		this.counter = Integer.parseInt((String)servletContext.getAttribute("userCounter"));
		this.counter++;
		servletContext.setAttribute(("userCounter"), Integer.toString(this.counter));
	}
	/**
	 * 
	 */
	synchronized void decrementUserCounter() {
		int counter = Integer.parseInt((String)servletContext.getAttribute("userCounter"));
		counter--;
		servletContext.setAttribute(("userCounter"), Integer.toString(counter));
	}
}
...

my web.xml contains -


...
	<listener>
		<listener-class>
			com.intellex.introgis.data.SessionCounter
		</listener-class>
	</listener>

...

In the main application class, in method
loadProtectedResources()
I get
webApplicationContext
-


...
                                          private WebApplicationContext webApplicationContext;
...

		ApplicationContext applicationContext = getContext();
		webApplicationContext = (WebApplicationContext) applicationContext;
...

And then pass to listeners -


...
public class UsersButtonClickListener implements ClickListener {
	public static final Logger LOG = Logger.getLogger(UsersButtonClickListener.class); //
	private Window window; //
	private TextField caption; //
	private TextField description; //
	private WebApplicationContext webApplicationContext;
	/**
	 * @param window
	 */
	public UsersButtonClickListener(Window window, WebApplicationContext webApplicationContext) {		
		this.window = window; 		
		this.webApplicationContext = webApplicationContext;
	    
		caption = new TextField("Caption", "Число пользователей системы на момент");        
	    caption.setWidth("200px");        
	    
	    description = new TextField("Description", 
	    		"<b> Всего пользователей: ");
	    description.setWidth("300px");
	}
	@Override
	public void buttonClick(ClickEvent event) {
		int userCounter = 0;
		ServletContext servletContext = webApplicationContext.getHttpSession().getServletContext();				
		if(servletContext != null && servletContext.getAttribute("userCounter") != null)
			userCounter = Integer.parseInt((String)servletContext.getAttribute("userCounter"));

		window.showNotification((String) caption.getValue(),                                
								(String) description.getValue()+userCounter+"</b>",                                
								 Notification.TYPE_TRAY_NOTIFICATION);
	}
}

...

The counter works fine on increment, but when the session is no decrement, ie user closes the application (or browser window as a whole), and the number of active sessions remains the same.

With what may be the reason?

That listener session ends -


...
public class LogoutButtonClickListener implements Button.ClickListener {
	private Window window; //
	private BlockerWindow blockerWindow;//
	/**
	 * @param window
	 */
	public LogoutButtonClickListener(Window window) {
		this.window = window;
	}
	
	@Override
	public void buttonClick(ClickEvent event) {
		Thread workThread = new Thread() {
			@Override
			public void run() {
				// TODO Auto-generated method stub
				window.removeWindow(blockerWindow);
				window.getApplication().close();
			}
		};
		workThread.start();
		blockerWindow = new BlockerWindow(workThread, "Завершение сеанса, ждите..", "Завершение сеанса может занять некоторое время");
		window.addWindow(blockerWindow);				
	}
}
...

I think sessionDestroyed is called when the servlet actually free the memory associated with the session.
As it works like a garbage collector, you can be sure it will be called at some point, but you don’t know when exactly.

Also I don’t know if sessionDestroyed is called during serialization of the session. And if Application.close() actually destroy the session (which can be bad if vaadin is embedded in a webpage) or just destroy all vaadin related data inside the session but leave the session alive.

Why don’t you hook Application.init() and Application.close() ? It should be more accurate.
(Also you should synchronize your counter to prevent weird things to happen)

I welcome you, Mathias Clerc!

Yes, indeed, if the increment counter in Application.init() ( …loadProtectedResources() ) and decrement in Application.close(), using a synchronized methods of SessionCounter, the problem is solved.

Thank you very much! :smiley: