If your looking for something to run WHEN a session expires, the better choice is probably a SessionListener. I'm not clear on if that's what you really want though. Assuming it is, here's an example from one of my apps... this basically updates a list of active users in a static member of a class that stores application statics, as well as some other statistical updates...
package com.mycompany.myapp.listeners; import com.mycompany.myapp.stats.AppStats; import java.math.BigDecimal; import java.util.HashMap; import java.util.Iterator; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; public class SessionListener implements HttpSessionListener { public synchronized void sessionCreated(HttpSessionEvent se) { cleanupActiveUsersList(); HashMap appStats = (HashMap)AppStats.getStats(); HashMap activeUsers = (HashMap)appStats.get("activeUsers"); synchronized (activeUsers) { activeUsers.put(se.getSession().getId(), new HashMap()); int currentCount = activeUsers.size(); BigDecimal maxSimultaneousUsers = (BigDecimal)appStats.get("maxSimultaneousUsers"); BigDecimal maxSimultaneousUsersRunning = (BigDecimal)appStats.get("maxSimultaneousUsersRunning"); if (currentCount > maxSimultaneousUsers.intValue()) { appStats.put("maxSimultaneousUsers", new BigDecimal(currentCount)); } if (currentCount > maxSimultaneousUsersRunning.intValue()) { appStats.put("maxSimultaneousUsersRunning", new BigDecimal(currentCount)); } appStats.put("activeUsers", activeUsers); } AppStats.setStats(appStats); } // End sessionCreated() public synchronized void sessionDestroyed(HttpSessionEvent se) { String sessionID = se.getSession().getId(); cleanupActiveUsersList(); HashMap appStats = (HashMap)AppStats.getStats(); HashMap activeUsers = (HashMap)appStats.get("activeUsers"); synchronized (activeUsers) { activeUsers.remove(se.getSession().getId()); appStats.put("activeUsers", activeUsers); } AppStats.setStats(appStats); } // End sessionDestroyed public synchronized static void cleanupActiveUsersList() { HashMap appStats = (HashMap)AppStats.getStats(); HashMap activeUsers = (HashMap)appStats.get("activeUsers"); synchronized (activeUsers) { for (Iterator it = activeUsers.keySet().iterator(); it.hasNext();) { String uiKey = (String)it.next(); HashMap hm = (HashMap)activeUsers.get(uiKey); String userID = (String)hm.get("userID"); if (userID == null) { activeUsers.remove(uiKey); } } appStats.put("activeUsers", activeUsers); } AppStats.setStats(appStats); } // End cleanupActiveUsersList() } // End class -- Frank W. Zammetti Founder and Chief Software Architect Omnytex Technologies http://www.omnytex.com On Thu, January 20, 2005 2:08 pm, Dakota Jack said: > That's right. And, that is what I provided. There is an error in the > ServletExpireFilter I provided, however. You have to change > filterConfig = filterConfig to this.filterConfig = filterConfig in two > places. Then it works like a charm. > > Jack > > > On Thu, 20 Jan 2005 10:05:51 -0800, Wiebe de Jong <[EMAIL PROTECTED]> wrote: >> This will detect that a session has already expired, but I think that is >> not >> what he wants. >> >> I think Jack is looking for something to run WHEN the session expires, >> similar to the destroy() method in a plugin that runs when the >> application >> stops. >> >> Wiebe de Jong >> >> -----Original Message----- >> From: Amleto Di Salle [mailto:[EMAIL PROTECTED] >> Sent: Thursday, January 20, 2005 9:41 AM >> To: 'Struts Users Mailing List'; 'Dakota Jack' >> Subject: R: R: Session Strategy (here's a filter) >> >> Hello Jack, >> you detect a session expiration using the getSession( false ) method. If >> you use false, the session is not created if there is no current >> session. >> In fact, in a previous e-mail that I sent, there was my Filter which >> used the getSession method. >> All it works if the session expires, and you have to set in some way the >> web container in order to delete the session object. >> >> So, I don't understand what do you mean "I am not looking to create a >> timeout but to detect a session expiration, so that the user can be >> redirected to a page". >> >> BR >> /Amleto >> >> > -----Messaggio originale----- >> > Da: Dakota Jack [mailto:[EMAIL PROTECTED] >> > Inviato: gioved? 20 gennaio 2005 18.03 >> > A: Amleto Di Salle >> > Cc: Struts Users Mailing List >> > Oggetto: Re: R: Session Strategy (here's a filter) >> > >> > >> > Hello, Amleto, >> > >> > I am not looking to create a timeout but to detect a session >> > expiration, so that the user can be redirected to a page. I >> > am not, that is, looking to get rid of people but looking to >> > help people that have their session expired. >> > >> > Jack >> > >> > >> > On Thu, 20 Jan 2005 17:42:55 +0100, Amleto Di Salle >> > <[EMAIL PROTECTED]> wrote: >> > > You can do this using request.getSession( false ) (false doesn't >> > > create the session) and use the following in the tag in the web.xml. >> > > >> > > <session-config> >> > > <session-timeout>30</session-timeout> >> > > </session-config> >> > > 30 are minutes >> > > >> > > You can set the session-timeout also in the web container >> > (see tomcat >> > > documentation). >> > > >> > > BR >> > > /Amleto >> > > >> > > > -----Messaggio originale----- >> > > > Da: Dakota Jack [mailto:[EMAIL PROTECTED] >> > > > Inviato: gioved? 20 gennaio 2005 17.08 >> > > > A: Struts Users Mailing List >> > > > Oggetto: Re: Session Strategy (here's a filter) >> > > > >> > > > >> > > > I was looking for a filter that detected sessions that >> > had expired >> > > > and rerouted the request to a login or other appropriate page. >> > > > >> > > > Jack >> > > > >> > > > >> > > > On Thu, 20 Jan 2005 10:53:09 -0500, [EMAIL PROTECTED] >> > > > <[EMAIL PROTECTED]> wrote: >> > > > > Here's the filter I use. It contains some logging that you >> > > > can choose >> > > > > to ignore and I also set some session attributes that I use for >> > > > > navigation AFTER the re-login, to get the user back to the >> > > > page they >> > > > > were on or as near as possible, given only their first/last >> > > > name and >> > > > > password. I also included the configuration I added to >> > my web.xml >> > > > > file to activate the filter for all actions beginning with >> > > > "/secure/" >> > > > > Then, I added "/secure/" to all actions that should use the >> > > > filter. I >> > > > > did this for all actions except the following, for which it >> > > > would have >> > > > > introduced a pretty obvious logic error: login, >> > register, and an >> > > > > action I use to direct the user back to the page they were >> > > > on before >> > > > > the timeout. >> > > > > >> > > > > Here's the filter >> > > > > >> > > > >> > ******************************************************************** >> > > > ** >> > > > > ********************************* >> > > > > >> > > > > >> > > > >> > /******************************************************************* >> > > > ** >> > > > > ******* >> > > > > * >> > > > > * This class provides a servlet filter ensure that each >> > > > request is coming >> > > > > from >> > > > > * an authenticated user. It also logs each servlet invocation. >> > > > > * >> > > > > >> > > > > >> > > > >> > ******************************************************************** >> > > > ** >> > > > > ******/ >> > > > > package schs82; >> > > > > >> > > > > import java.util.*; >> > > > > import javax.servlet.*; >> > > > > import javax.servlet.http.*; >> > > > > import org.apache.struts.action.*; >> > > > > import org.apache.commons.logging.Log; >> > > > > import org.apache.commons.logging.LogFactory; >> > > > > import java.text.DateFormat; >> > > > > import schs82.*; >> > > > > >> > > > > public final class AuthenticationFilter implements Filter { >> > > > > >> > > > > private Log logger; >> > > > > >> > > > > public void init(javax.servlet.FilterConfig filterConfig) >> > > > > throws javax.servlet.ServletException { >> > > > > >> > > > > logger = LogFactory.getLog("SCHS82"); >> > > > > } >> > > > > >> > > > > public void doFilter(javax.servlet.ServletRequest request, >> > > > > javax.servlet.ServletResponse response, >> > > > > javax.servlet.FilterChain filterChain) >> > > > > throws java.io.IOException, >> > > > > javax.servlet.ServletException { >> > > > > >> > > > > HttpServletRequest req = (HttpServletRequest)request; >> > > > > HttpServletResponse resp > > >> (HttpServletResponse)response; >> > > > > >> > > > > HttpSession session = req.getSession(); >> > > > > String firstName > > > > >> (String)session.getAttribute("firstName"); >> > > > > String lastName > > >> (String)session.getAttribute("lastName"); >> > > > > String password > > >> (String)session.getAttribute("password"); >> > > > > String currentAction = req.getRequestURI(); >> > > > > session.setAttribute("currentAction", currentAction); >> > > > > session.setAttribute("currentActionDisposition", ""); >> > > > > session.setAttribute("currentActionMessage", ""); >> > > > > >> > > > > if (logger.isInfoEnabled()) { >> > > > > // log each servlet invoked, date/time and user >> > > > who invoked >> > > > > GregorianCalendar calendar = new >> > GregorianCalendar(); >> > > > > java.util.Date dateTime = calendar.getTime(); >> > > > > DateFormat format > > > > > >> DateFormat.getDateTimeInstance(DateFormat.MEDIUM, >> > DateFormat.LONG); >> > > > > String now = format.format(dateTime); >> > > > > >> > > > > logger.info(" " + now >> > > > > + " User: " + firstName >> > > > > + " " + lastName >> > > > > + ", Servlet: " + currentAction); >> > > > > } >> > > > > >> > > > > if (session.isNew()) { >> > > > > // session timed-out >> > > > > session.setAttribute("currentActionDisposition", >> > > > > "sessionTimeout"); >> > > > > >> > session.setAttribute("currentActionMessage", "You were >> > > > > inactive" + >> > > > > " too long, so you must >> > > > login again! >> > > > > Please" + >> > > > > " click on the button >> > > > below to go to >> > > > > the" >> > > > > + >> > > > > " login page."); >> > > > > >> > > > > >> > > > resp.sendRedirect("/schs82/BuildActionResultViewAction.do"); >> > > > > } >> > > > > else if (firstName == null || lastName == null || >> > > > password => > > > > null) { >> > > > > if (logger.isInfoEnabled()) { >> > > > > logger.info("NON-AUTHENTICATED USER >> > ATTEMPTED TO >> > > > > ACCESS SCHS82 " >> > > > > + "APPLICATION! (Session >> > > > attributes = Null)"); >> > > > > } >> > > > > session.setAttribute("currentActionDisposition", >> > > > > "systemError"); >> > > > > >> > session.setAttribute("currentActionMessage", "You have >> > > > > accessed" + >> > > > > " SCHS82.com in a >> > > > non-authorized way. >> > > > > Please" + >> > > > > " click on the button >> > > > below to go to >> > > > > the" >> > > > > + >> > > > > " login page."); >> > > > > >> > > > > >> > > > resp.sendRedirect("/schs82/BuildActionResultViewAction.do"); >> > > > > } >> > > > > else { >> > > > > //authenticate user >> > > > > User user = new User(); >> > > > > user.setFirstName(firstName); >> > > > > user.setLastName(lastName); >> > > > > user.setPassword(password); >> > > > > if (user.checkAuthorization()) { >> > > > > //user is authentic >> > > > > filterChain.doFilter(request, response); >> > > > > } >> > > > > else { >> > > > > //user is NOT authentic >> > > > > if (logger.isInfoEnabled()) { >> > > > > logger.info("NON-AUTHENTICATED USER >> > > > ATTEMPTED TO >> > > > > ACCESS " >> > > > > + "SCHS82 APPLICATION! >> > (Invalid name >> > > > > or password)"); >> > > > > } >> > > > > session.setAttribute("currentActionDisposition", >> > > > > "systemError"); >> > > > > >> > > > session.setAttribute("currentActionMessage", "You have >> > > > > accessed" + >> > > > > " SCHS82.com in a >> > > > non-authorized >> > > > > way. Please" + >> > > > > " click on the button >> > > > below to go >> > > > > to the" + >> > > > > " login page."); >> > > > > >> > > > > resp.sendRedirect("/schs82/BuildActionResultViewAction.do"); >> > > > > } >> > > > > } >> > > > > } >> > > > > >> > > > > public void destroy() {} >> > > > > } >> > > > > >> > > > > And this must be added to web.xml >> > > > > >> > > > >> > ******************************************************************** >> > > > ** >> > > > > ********************************* >> > > > > >> > > > > <filter> >> > > > > <filter-name>AuthenticationFilter</filter-name> >> > > > > <filter-class>schs82.AuthenticationFilter</filter-class> >> > > > > </filter> >> > > > > >> > > > > <filter-mapping> >> > > > > <filter-name>AuthenticationFilter</filter-name> >> > > > > <url-pattern>/secure/*</url-pattern> >> > > > > </filter-mapping> >> > > > > >> > > > > Dakota Jack <[EMAIL PROTECTED]> >> > > > > 01/20/2005 09:53 AM >> > > > > Please respond to "Struts Users Mailing List" >> > > > > >> > > > > To: Struts Users Mailing List >> > <user@struts.apache.org>, >> > > > > [EMAIL PROTECTED] >> > > > > cc: >> > > > > Subject: Re: Session Strategy >> > > > > >> > > > > I am also too lazy to make a filter! LOL ;-) Anyone >> > have one of >> > > > > these in their toolbox they would like to share? >> > > > > >> > > > > Jack >> > > > > >> > > > > On Thu, 20 Jan 2005 12:49:41 +0800, Andrew Hill >> > > > > <[EMAIL PROTECTED]> wrote: >> > > > > > Id support the filter suggestion, though for myself I >> > > > generally do >> > > > > > the check in the RequestProcessor, as Ive usually >> > > > overrideen it to >> > > > > > perform other evil anyhow, and Im lazy to make a filter. >> > > > > > >> > > > > > If you dont keep your JSP under WEB-INF (IMHO thats >> > where they >> > > > > > belong because they are 'code & config' , just like your >> > > > > > classes,jars, and struts-config.xml and tlds) then you should >> > > > > > declare some sort of security constraint so they can only >> > > > be reached >> > > > > > by a server side forward from their respective preperation >> > > > > > action. >> > > > > > >> > > > > > >> > > > > > Frank W. Zammetti wrote: >> > > > > > >> > > > > > > If the user clicks a button, you are either going to (a) go >> > > > > > > directly >> > > > > to >> > > > > > > a JSP, which is generally not a good idea in a Struts-based >> > > > > application >> > > > > > > anyway (or any servlet-based application for that >> > > > matter) or (b) >> > > > > > > go to an Action, as you probably should be doing. In >> > > > either case, >> > > > > > > choice 1 >> > > > > is >> > > > > > > what I would do personally. Putting things under >> > > > WEB-INF as David >> > > > > > > suggests works great, but it just feels kind of wrong to me. >> > > > > > > >> > > > > > > You'll also want to call some common code from all your >> > > > > > > Actions that does the same basic check and forwards >> > > > > > > immediately to your "logon >> > > > > again" >> > > > > > > page. I do this by means of an ActionHelpers class >> > that has >> > > > > > > two >> > > > > static >> > > > > > > methods, start() and finish() that are called, as >> > I'm sure you >> > > > > > > could guess, at the start and end of all my Actions. >> > > > They do some >> > > > > > > common tasks, including this check. >> > > > > > > >> > > > > > > If you want a real solution though, externalize >> > your security >> > > > > > > using something like Netegrity Siteminder. It will >> > > > deal with this >> > > > > > > situation for you, in a theoretically more secure >> > > > fashion than you >> > > > > > > could >> > > > > probably >> > > > > > > do on your own. >> > > > > > > >> > > > > > > Yet another idea is a filter that will check if a >> > > > session is alive >> > > > > > > and redirect as appropriate. This I believe can work no >> > > > > > > matter what your request is to (Action or JSP directly), or >> > > > > > > any other resource, >> > > > > assuming >> > > > > > > the app server serves everything. >> > > > > > > >> > > > > > >> > > > > > >> > > > >> > -------------------------------------------------------------------- >> > > > > > - >> > > > > > To unsubscribe, e-mail: [EMAIL PROTECTED] >> > > > > > For additional commands, e-mail: [EMAIL PROTECTED] >> > > > > > >> > > > > > >> > > > > >> > > > > -- >> > > > > ------------------------------ >> > > > > >> > > > > "You can lead a horse to water but you cannot make it >> > float on its >> > > > > back." >> > > > > >> > > > > ~Dakota Jack~ >> > > > > >> > > > > "You can't wake a person who is pretending to be asleep." >> > > > > >> > > > > ~Native Proverb~ >> > > > > >> > > > > "Each man is good in His sight. It is not necessary for >> > > > eagles to be >> > > > > crows." >> > > > > >> > > > > ~Hunkesni (Sitting Bull), Hunkpapa Sioux~ >> > > > > >> > > > > ----------------------------------------------- >> > > > > >> > > > > "This message may contain confidential and/or privileged >> > > > information. >> > > > > If you are not the addressee or authorized to receive >> > this for the >> > > > > addressee, you must not use, copy, disclose, or take any >> > > > action based >> > > > > on this message or any information herein. If you have >> > > > received this >> > > > > message in error, please advise the sender immediately by >> > > > reply e-mail >> > > > > and delete this message. Thank you for your cooperation." >> > > > > >> > > > > >> > > > >> > -------------------------------------------------------------------- >> > > > - >> > > > > To unsubscribe, e-mail: [EMAIL PROTECTED] >> > > > > For additional commands, e-mail: [EMAIL PROTECTED] >> > > > > >> > > > > >> > > > >> > > > >> > > > -- >> > > > ------------------------------ >> > > > >> > > > "You can lead a horse to water but you cannot make it >> > float on its >> > > > back." >> > > > >> > > > ~Dakota Jack~ >> > > > >> > > > "You can't wake a person who is pretending to be asleep." >> > > > >> > > > ~Native Proverb~ >> > > > >> > > > "Each man is good in His sight. It is not necessary for >> > eagles to be >> > > > crows." >> > > > >> > > > ~Hunkesni (Sitting Bull), Hunkpapa Sioux~ >> > > > >> > > > ----------------------------------------------- >> > > > >> > > > "This message may contain confidential and/or privileged >> > > > information. If you are not the addressee or authorized >> > to receive >> > > > this for the addressee, you must not use, copy, disclose, or take >> > > > any action based on this message or any information >> > herein. If you >> > > > have received this message in error, please advise the sender >> > > > immediately by reply e-mail and delete this message. >> > Thank you for >> > > > your cooperation." >> > > > >> > > > >> > -------------------------------------------------------------------- >> > > > - >> > > > To unsubscribe, e-mail: [EMAIL PROTECTED] >> > > > For additional commands, e-mail: [EMAIL PROTECTED] >> > > > >> > > > -- >> > > > No virus found in this incoming message. >> > > > Checked by AVG Anti-Virus. >> > > > Version: 7.0.300 / Virus Database: 265.7.0 - Release Date: >> > > > 17/01/2005 >> > > > >> > > > >> > > >> > > -- >> > > No virus found in this outgoing message. >> > > Checked by AVG Anti-Virus. >> > > Version: 7.0.300 / Virus Database: 265.7.0 - Release Date: >> > 17/01/2005 >> > > >> > > >> > >> > >> > -- >> > ------------------------------ >> > >> > "You can lead a horse to water but you cannot make it float >> > on its back." >> > >> > ~Dakota Jack~ >> > >> > "You can't wake a person who is pretending to be asleep." >> > >> > ~Native Proverb~ >> > >> > "Each man is good in His sight. It is not necessary for >> > eagles to be crows." >> > >> > ~Hunkesni (Sitting Bull), Hunkpapa Sioux~ >> > >> > ----------------------------------------------- >> > >> > "This message may contain confidential and/or privileged >> > information. If you are not the addressee or authorized to >> > receive this for the addressee, you must not use, copy, >> > disclose, or take any action based on this message or any >> > information herein. If you have received this message in >> > error, please advise the sender immediately by reply e-mail >> > and delete this message. Thank you for your cooperation." >> > >> > --------------------------------------------------------------------- >> > To unsubscribe, e-mail: [EMAIL PROTECTED] >> > For additional commands, e-mail: [EMAIL PROTECTED] >> > >> > >> > -- >> > No virus found in this incoming message. >> > Checked by AVG Anti-Virus. >> > Version: 7.0.300 / Virus Database: 265.7.0 - Release Date: 17/01/2005 >> > >> > >> >> -- >> No virus found in this outgoing message. >> Checked by AVG Anti-Virus. >> Version: 7.0.300 / Virus Database: 265.7.0 - Release Date: 17/01/2005 >> >> >> --------------------------------------------------------------------- >> To unsubscribe, e-mail: [EMAIL PROTECTED] >> For additional commands, e-mail: [EMAIL PROTECTED] >> >> >> --------------------------------------------------------------------- >> To unsubscribe, e-mail: [EMAIL PROTECTED] >> For additional commands, e-mail: [EMAIL PROTECTED] >> >> > > > -- > ------------------------------ > > "You can lead a horse to water but you cannot make it float on its back." > > ~Dakota Jack~ > > "You can't wake a person who is pretending to be asleep." > > ~Native Proverb~ > > "Each man is good in His sight. It is not necessary for eagles to be > crows." > > ~Hunkesni (Sitting Bull), Hunkpapa Sioux~ > > ----------------------------------------------- > > "This message may contain confidential and/or privileged information. > If you are not the addressee or authorized to receive this for the > addressee, you must not use, copy, disclose, or take any action based > on this message or any information herein. If you have received this > message in error, please advise the sender immediately by reply e-mail > and delete this message. Thank you for your cooperation." > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] > >
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]