How do I execute an authenticated AJAX request without resetting the tomcat's session timeout? How do I execute an authenticated AJAX request without resetting the tomcat's session timeout? ajax ajax

How do I execute an authenticated AJAX request without resetting the tomcat's session timeout?


I'd go with a Grails filter that does something similar to what The-MeLLeR is proposing without the unnecessary loop through all sessions:

class AjaxTimeoutFilters {   int sessionTimeout = 30 * 60 * 1000   private static final String TIMEOUT_KEY = 'TIMEOUT_KEY'   def filters = {      all(controller:'*', action:'*') {         before = {            if (request.xhr) {               Long lastAccess = session[TIMEOUT_KEY]               if (lastAccess == null) {                  // TODO                  return false               }               if (System.currentTimeMillis() - lastAccess > sessionTimeout) {                  session.invalidate()                  // TODO - render response to trigger client redirect                  return false               }            }            else {               session[TIMEOUT_KEY] = System.currentTimeMillis()            }            true         }      }   }}

The session timeout should be dependency-injected or otherwise kept in sync with the value in web.xml.

There are two remaining issues. One is the case where there's an Ajax request but no previous non-Ajax request (lastAccess == null). The other is how to redirect the browser to a login page or wherever you need to go when there's an Ajax request after 30 minutes of no non-Ajax activity. You'd have to render JSON or some other response that the client would check to know that it's been timed out and do a client-side redirect.


Nope not possible...

One option is the following:

1) create a javax.servlet.Filter and store the timestamp of the last (non-ajax) pageview on the session.

2) create a javax.servlet.http.HttpSessionListener to store all the active sessions.

3) use a background thread to invalidate all expired sessions.


Sample Code:

import javax.servlet.*;import javax.servlet.http.*;import java.io.IOException;import java.util.ArrayList;import java.util.List;public class LastAccessFilter implements Filter, HttpSessionListener {    private static final Object SYNC_OBJECT = new Object();    private static final String LAST_ACCESSED = "lastAccessed";    private boolean backgroundThreadEnabled;    public void destroy() {        synchronized (SYNC_OBJECT){            backgroundThreadEnabled = false;            SYNC_OBJECT.notifyAll();        }    }    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {        if (req instanceof HttpServletRequest) {            HttpServletRequest httpServletRequest = (HttpServletRequest) req;            if(!isAjax(httpServletRequest)){                httpServletRequest.getSession().setAttribute(LAST_ACCESSED, System.currentTimeMillis());            }        }        chain.doFilter(req, resp);    }    public static boolean isAjax(request) {       return "XMLHttpRequest".equals(request.getHeader("X-Requested-With"));    }       public void init(FilterConfig config) throws ServletException {        Thread t = new Thread(new Runnable() {            @Override            public void run() {                while (LastAccessFilter.this.backgroundThreadEnabled) {                    synchronized (SYNC_OBJECT) {                        try {                            SYNC_OBJECT.wait(3000);                        } catch (InterruptedException e) {                            e.printStackTrace();                        }                        if (LastAccessFilter.this.backgroundThreadEnabled) {                            HttpSession[] sessions;                            synchronized (activeSessions){                                sessions = activeSessions.toArray(new HttpSession[activeSessions.size()]);                            }                            cleanupInactiveSessions(sessions);                        }                    }                }            }            private void cleanupInactiveSessions(HttpSession[] sessions) {                for (HttpSession session : sessions) {                    Object lastAccessedObject = session.getAttribute(LAST_ACCESSED);                    if(lastAccessedObject == null) continue;                    long lastAccessed = (Long)lastAccessedObject;                    if(System.currentTimeMillis() > (lastAccessed + 1800000)){//30 Minutes                        session.invalidate();                    }                }            }        });        t.setDaemon(true);        this.backgroundThreadEnabled = true;        t.start();    }    private final List<HttpSession> activeSessions = new ArrayList<HttpSession>();    @Override    public void sessionCreated(HttpSessionEvent httpSessionEvent) {        synchronized (activeSessions) {            this.activeSessions.add(httpSessionEvent.getSession());        }    }    @Override    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {        synchronized (activeSessions) {            this.activeSessions.remove(httpSessionEvent.getSession());        }    }}