@Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {

    HttpServletRequest httpReq = (HttpServletRequest) request;
    HttpServletResponse httpResp = (HttpServletResponse) response;

    // Early out if this isn't the right kind of request. We might see a RequestWrapper instance
    // during a forward or include request.
    if (alreadyWrapped(httpReq)) {
      LOG.debug("Handling already-wrapped request");
      chain.doFilter(request, response);
      return;
    }

    // Create wrappers for the request and response objects.
    // Using these, you can extend the capabilities of the
    // request and response, for example, allow setting parameters
    // on the request before sending the request to the rest of the filter chain,
    // or keep track of the cookies that are set on the response.
    //
    // Caveat: some servers do not handle wrappers very well for forward or
    // include requests.

    ResponseWrapper wrappedResponse = new ResponseWrapper(httpResp);
    final RequestWrapper wrappedRequest =
        new RequestWrapper(manager, httpReq, wrappedResponse, filterConfig.getServletContext());

    Throwable problem = null;

    try {
      chain.doFilter(wrappedRequest, wrappedResponse);
    } catch (Throwable t) {
      // If an exception is thrown somewhere down the filter chain,
      // we still want to execute our after processing, and then
      // rethrow the problem after that.
      problem = t;
      LOG.error("Exception processing filter chain", t);
    }

    GemfireHttpSession session = (GemfireHttpSession) wrappedRequest.getSession(false);

    // If there was a problem, we want to rethrow it if it is
    // a known type, otherwise log it.
    if (problem != null) {
      if (problem instanceof ServletException) {
        throw (ServletException) problem;
      }
      if (problem instanceof IOException) {
        throw (IOException) problem;
      }
      sendProcessingError(problem, response);
    }

    // Commit any updates. What actually happens at that point is dependent on the type of
    // attributes defined for use by the sessions.
    if (session != null) {
      session.commit();
    }
  }
@param request The servlet request we are processing
@param response The servlet response we are creating
@param chain The filter chain we are processing
@throws IOException if an input/output error occurs
@throws ServletException if a servlet error occurs
extensions/geode-modules-session/src/main/java/org/apache/geode/modules/session/filter/SessionCachingFilter.java