I solved this problem using a combination of a filter and a SessionListener... I forgot it at work unfortunately, but it will be added to Java Web Parts tomorrow. It allows you to limit the number of sessions to any specific number, and deals with the issue you mention with regard to the different between a session not allowed to be created and a session being destroyed.

I actually intended to post the code, but like I said, forgot it at work :)

Frank

Rick Reumann wrote:
David G. Friedman wrote the following on 7/27/2005 12:35 AM:

When a session is created, have the SessionListener update a session count. If the count is 2 or more then call SessionEvent.getSession().invalidate() to cancel the session. Then the session listener's Session destroy method
can decrement the counter appropriately.   And once the main session is
removed (via logout or timeout) it would set the session count back to zero
so someone new could login to the webapp.  But it sounds like Rick found
some issues with that kind of approach where it doesn't match that simple
kind of logic.


I tried something like the above but there was a problem. The problem was that the Session destroy method that decrements the counter gets called whenever session.invalidate() is called, so say the first person logs in... the static counter goes to "1." Now another person tries to login and the session listener sees that it's "1" so it calls invalidate. Now you just set it back to 0 so another follow up session will think it's ok to login when it isn't.

I used your suggestion though David and did something similar but in a HttpSessionBindingListener (code will be shown below).

It still does also require a SessionListener and in sessionCreated(HttpSessionEvent event)

event.getSession().setAttribute("SessionIdWrapper", new SessionIdWrapper() );


Then the important class is the HttpSessionBindingListener:

public class SessionIdWrapper implements HttpSessionBindingListener {
    private static final int MAX_SESSIONS = 1;
    private static int mainSessionCount;
    private boolean activeSession;
    private Logger log = Logger.getLogger(this.getClass() );

    public SessionIdWrapper() { }
    synchronized void init(HttpSessionBindingEvent event) {
        if ( mainSessionCount < MAX_SESSIONS ) {
            mainSessionCount++;
            activeSession = true;
event.getSession().getServletContext().setAttribute( Constants.APPLICATION_IN_USE,"User" );
        } else {
            event.getSession().invalidate();
        }
    }
    synchronized void decrement(HttpSessionBindingEvent event) {
        mainSessionCount--;
        if ( mainSessionCount == 0 ) {
log.debug("Nobody is using the application, so remove APPLICATION_IN_USE");

event.getSession().getServletContext().removeAttribute(Constants.APPLICATION_IN_USE);
        }
    }


    public void valueBound(HttpSessionBindingEvent event) {
        init(event);
    }

    public void valueUnbound(HttpSessionBindingEvent event) {
        if ( activeSession ) {
            decrement(event);
        }
    }
}


Finally some work also done in the main Filter filtering all requests. If you don't have this, the user will just think his session expired or some other odd behavior. Relevant code is in the doFilter:

if ( path.indexOf("/appinuse.jsp") == -1 && path.indexOf("/logout.jsp") == -1 ) { if (session == null && context.getAttribute(Constants.APPLICATION_IN_USE) != null ) {
                log.debug("The application is in use");
                response.sendRedirect(contextPath+"/appinuse.jsp");
                return;
             }
        }


In the above you'll notice "context" to get this create class context var and in your init method: (thanks to Daniel S. for pointing this out to me)

public void init(FilterConfig filterConfig) throws ServletException {
        this.context = filterConfig.getServletContext();
    }

)

All and all, the above is a bit of work, but not too bad. Although looking over my code, I realize that the filter stuff is only going to work ok if you only allow one user to use the application (which happens to be my criteria). If it is allowed to use say 4 sessions, the above filter stuff will be a problem. My head hurts too much to figure out how to fix it. Someone email me at [EMAIL PROTECTED] so they can fix it up and make the code more robust:)


--
Frank W. Zammetti
Founder and Chief Software Architect
Omnytex Technologies
http://www.omnytex.com


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to