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]