You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by up...@apache.org on 2017/08/28 17:45:16 UTC

[2/2] geode git commit: GEODE-3513: Removing the use of native sessions session caching

GEODE-3513: Removing the use of native sessions session caching

In the session module for generic app servers, we were asking the
application server for a 'native' session and then wrapping it on our
own GemfireHttpSession. However, we were not cleaning up that native
session, which means that in PROXY mode we were leaving these sessions
on the client with them being useful.

The GemfireHttpSession now no longer wraps a native session. We are
still temporarily creating a native session because it is the only way
for us to get the session timeout value that was configured in web.xml,
but the native session is immediately invalidated.

Adding and extending cargo session tests to test how sessions are being
cleaned up from the clients and the server.

This closes #740


Project: http://git-wip-us.apache.org/repos/asf/geode/repo
Commit: http://git-wip-us.apache.org/repos/asf/geode/commit/c5b12117
Tree: http://git-wip-us.apache.org/repos/asf/geode/tree/c5b12117
Diff: http://git-wip-us.apache.org/repos/asf/geode/diff/c5b12117

Branch: refs/heads/develop
Commit: c5b1211758ece1346a4f69bf72f31b8d4b2a8441
Parents: 755f636
Author: Dan Smith <up...@apache.org>
Authored: Mon Aug 28 10:36:53 2017 -0700
Committer: Dan Smith <up...@apache.org>
Committed: Mon Aug 28 10:36:53 2017 -0700

----------------------------------------------------------------------
 .../internal/common/AbstractSessionCache.java   |   4 +
 .../common/ClientServerSessionCache.java        |   9 +-
 .../internal/filter/DummySessionManager.java    |  18 +-
 .../internal/filter/GemfireHttpSession.java     |  84 ++-------
 .../internal/filter/GemfireSessionManager.java  |  82 +-------
 .../session/internal/filter/SessionManager.java |  21 +--
 .../AbstractDeltaSessionAttributes.java         |   6 -
 .../attributes/AbstractSessionAttributes.java   |  24 +++
 .../internal/filter/attributes/DeltaEvent.java  |   6 +-
 .../filter/attributes/SessionAttributes.java    |  10 +
 .../filter/util/ThreadLocalSession.java         |  36 ----
 .../session/filter/SessionCachingFilter.java    |  77 ++------
 .../modules/session/filter/SessionListener.java |  14 +-
 .../modules/session/installer/Installer.java    |   6 -
 .../session/internal/filter/CommonTests.java    |  67 +------
 .../filter/HttpSessionListenerImpl.java         |  37 ----
 .../filter/HttpSessionListenerImpl2.java        |  39 ----
 .../SessionReplicationIntegrationJUnitTest.java | 188 -------------------
 .../InstallerJUnitTest.web.xml.expected         |   3 -
 .../geode/modules/session/CommandServlet.java   |  74 +++++---
 .../session/ListenerStoredInSessionContext.java |  31 +++
 .../geode/modules/session/QueryCommand.java     |   4 +-
 .../session/SessionCountingListener.java        |  43 +++++
 .../functions/GetMaxInactiveInterval.java       |  29 +++
 .../session/functions/GetSessionCount.java      |  30 +++
 .../functions/GetSessionCreatedCount.java       |  30 +++
 .../functions/GetSessionDestroyedCount.java     |  30 +++
 .../src/main/webapp/WEB-INF/web.xml             |   8 +
 .../geode/session/tests/CargoTestBase.java      |  67 ++++++-
 .../org/apache/geode/session/tests/Client.java  |  18 ++
 .../geode/session/tests/ContainerInstall.java   |  22 ++-
 .../tests/GenericAppServerClientServerTest.java |  74 +++++++-
 .../tests/GenericAppServerContainer.java        |   3 +-
 .../tests/Jetty9CachingClientServerTest.java    |  83 ++++++++
 .../geode/session/tests/ServerContainer.java    |   8 +-
 .../weblogic_setting_up_the_module.html.md.erb  |   5 +-
 36 files changed, 617 insertions(+), 673 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/geode/blob/c5b12117/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/common/AbstractSessionCache.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/common/AbstractSessionCache.java b/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/common/AbstractSessionCache.java
index 8a7f6f8..a553b72 100644
--- a/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/common/AbstractSessionCache.java
+++ b/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/common/AbstractSessionCache.java
@@ -19,6 +19,7 @@ import org.apache.geode.cache.Region;
 import org.apache.geode.modules.session.catalina.internal.DeltaSessionStatistics;
 import org.apache.geode.modules.session.internal.filter.util.TypeAwareMap;
 import org.apache.geode.modules.util.RegionConfiguration;
+import org.apache.geode.modules.util.SessionCustomExpiry;
 
 import java.util.Map;
 import javax.servlet.http.HttpSession;
@@ -91,6 +92,9 @@ public abstract class AbstractSessionCache implements SessionCache {
         (Boolean) properties.get(CacheProperty.ENABLE_GATEWAY_REPLICATION));
     configuration
         .setEnableDebugListener((Boolean) properties.get(CacheProperty.ENABLE_DEBUG_LISTENER));
+    // Need to set max inactive interval to tell the server to use our custom expiry
+    configuration.setMaxInactiveInterval(0);
+    configuration.setCustomExpiry(new SessionCustomExpiry());
 
     return configuration;
   }

http://git-wip-us.apache.org/repos/asf/geode/blob/c5b12117/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/common/ClientServerSessionCache.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/common/ClientServerSessionCache.java b/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/common/ClientServerSessionCache.java
index 51a2a6e..8350cad 100644
--- a/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/common/ClientServerSessionCache.java
+++ b/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/common/ClientServerSessionCache.java
@@ -28,6 +28,7 @@ import org.apache.geode.modules.util.BootstrappingFunction;
 import org.apache.geode.modules.util.CreateRegionFunction;
 import org.apache.geode.modules.util.RegionConfiguration;
 import org.apache.geode.modules.util.RegionStatus;
+import org.apache.geode.modules.util.SessionCustomExpiry;
 
 import java.util.List;
 import java.util.Map;
@@ -156,12 +157,14 @@ public class ClientServerSessionCache extends AbstractSessionCache {
     String regionName = (String) properties.get(CacheProperty.REGION_NAME);
     if (enableLocalCache) {
       // Create the region factory with caching and heap LRU enabled
-      factory = ((ClientCache) this.cache)
-          .createClientRegionFactory(ClientRegionShortcut.CACHING_PROXY_HEAP_LRU);
+      factory = this.cache
+          .<String, HttpSession>createClientRegionFactory(
+              ClientRegionShortcut.CACHING_PROXY_HEAP_LRU)
+          .setCustomEntryIdleTimeout(new SessionCustomExpiry());
       LOG.info("Created new local client session region: {}", regionName);
     } else {
       // Create the region factory without caching enabled
-      factory = ((ClientCache) this.cache).createClientRegionFactory(ClientRegionShortcut.PROXY);
+      factory = this.cache.createClientRegionFactory(ClientRegionShortcut.PROXY);
       LOG.info("Created new local client (uncached) session region: {} without any session expiry",
           regionName);
     }

http://git-wip-us.apache.org/repos/asf/geode/blob/c5b12117/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/DummySessionManager.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/DummySessionManager.java b/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/DummySessionManager.java
index b33c8d4..70d60ca 100644
--- a/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/DummySessionManager.java
+++ b/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/DummySessionManager.java
@@ -20,6 +20,8 @@ import org.apache.geode.modules.session.internal.filter.attributes.AbstractSessi
 import java.util.HashMap;
 import java.util.Map;
 import java.util.UUID;
+
+import javax.servlet.ServletContext;
 import javax.servlet.http.HttpSession;
 
 /**
@@ -69,10 +71,10 @@ public class DummySessionManager implements SessionManager {
    * {@inheritDoc}
    */
   @Override
-  public HttpSession wrapSession(HttpSession nativeSession) {
+  public HttpSession wrapSession(ServletContext context, int maxInactiveInterval) {
     String id = generateId();
     AbstractSessionAttributes attributes = new Attributes();
-    GemfireHttpSession session = new GemfireHttpSession(id, nativeSession);
+    GemfireHttpSession session = new GemfireHttpSession(id, context);
     session.setManager(this);
     session.setAttributes(attributes);
     sessions.put(id, session);
@@ -80,13 +82,6 @@ public class DummySessionManager implements SessionManager {
     return session;
   }
 
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public HttpSession getWrappingSession(String nativeId) {
-    return sessions.get(nativeId);
-  }
 
   /**
    * {@inheritDoc}
@@ -105,11 +100,6 @@ public class DummySessionManager implements SessionManager {
     sessions.remove(id);
   }
 
-  @Override
-  public String destroyNativeSession(String id) {
-    return null;
-  }
-
   public String getSessionCookieName() {
     return "JSESSIONID";
   }

http://git-wip-us.apache.org/repos/asf/geode/blob/c5b12117/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/GemfireHttpSession.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/GemfireHttpSession.java b/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/GemfireHttpSession.java
index 88b20d6..44c3ec3 100644
--- a/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/GemfireHttpSession.java
+++ b/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/GemfireHttpSession.java
@@ -67,7 +67,7 @@ public class GemfireHttpSession implements HttpSession, DataSerializable, Delta
 
   private transient SessionManager manager;
 
-  private HttpSession nativeSession = null;
+  private ServletContext context;
 
   /**
    * A session becomes invalid if it is explicitly invalidated or if it expires.
@@ -108,13 +108,10 @@ public class GemfireHttpSession implements HttpSession, DataSerializable, Delta
   /**
    * Constructor
    */
-  public GemfireHttpSession(String id, HttpSession nativeSession) {
+  public GemfireHttpSession(String id, ServletContext context) {
     this();
     this.id = id;
-    this.nativeSession = nativeSession;
-    if (nativeSession != null) {
-      attributes.setMaxInactiveInterval(nativeSession.getMaxInactiveInterval());
-    }
+    this.context = context;
   }
 
   /**
@@ -163,9 +160,7 @@ public class GemfireHttpSession implements HttpSession, DataSerializable, Delta
    */
   @Override
   public Enumeration getAttributeNames() {
-    if (!isValid) {
-      throw new IllegalStateException("Session is already invalidated");
-    }
+    checkValid();
     return Collections.enumeration(attributes.getAttributeNames());
   }
 
@@ -174,11 +169,8 @@ public class GemfireHttpSession implements HttpSession, DataSerializable, Delta
    */
   @Override
   public long getCreationTime() {
-    if (nativeSession != null) {
-      return nativeSession.getCreationTime();
-    } else {
-      return 0;
-    }
+    checkValid();
+    return attributes.getCreationTime();
   }
 
   /**
@@ -200,16 +192,16 @@ public class GemfireHttpSession implements HttpSession, DataSerializable, Delta
     return attributes.getLastAccessedTime();
   }
 
+  public void setServletContext(ServletContext context) {
+    this.context = context;
+  }
+
   /**
    * {@inheritDoc}
    */
   @Override
   public ServletContext getServletContext() {
-    if (nativeSession != null) {
-      return nativeSession.getServletContext();
-    } else {
-      return null;
-    }
+    return context;
   }
 
   /**
@@ -241,7 +233,6 @@ public class GemfireHttpSession implements HttpSession, DataSerializable, Delta
    */
   @Override
   public void invalidate() {
-    nativeSession.invalidate();
     manager.destroySession(id);
     isValid = false;
   }
@@ -266,9 +257,6 @@ public class GemfireHttpSession implements HttpSession, DataSerializable, Delta
    */
   @Override
   public void setMaxInactiveInterval(int interval) {
-    if (nativeSession != null) {
-      nativeSession.setMaxInactiveInterval(interval);
-    }
     attributes.setMaxInactiveInterval(interval);
     isDirty = true;
   }
@@ -278,11 +266,7 @@ public class GemfireHttpSession implements HttpSession, DataSerializable, Delta
    */
   @Override
   public int getMaxInactiveInterval() {
-    if (nativeSession != null) {
-      return nativeSession.getMaxInactiveInterval();
-    } else {
-      return attributes.getMaxIntactiveInterval();
-    }
+    return attributes.getMaxIntactiveInterval();
   }
 
   /**
@@ -298,8 +282,8 @@ public class GemfireHttpSession implements HttpSession, DataSerializable, Delta
    */
   @Override
   public void removeAttribute(final String name) {
+    checkValid();
     LOG.debug("Session {} removing attribute {}", getId(), name);
-    nativeSession.removeAttribute(name);
     attributes.removeAttribute(name);
   }
 
@@ -316,13 +300,13 @@ public class GemfireHttpSession implements HttpSession, DataSerializable, Delta
    */
   @Override
   public void setAttribute(final String name, final Object value) {
+    checkValid();
 
     if (LOG.isDebugEnabled()) {
       LOG.debug("Session {} setting attribute {} = '{}'", new Object[] {id, name, value});
     }
 
     isDirty = true;
-    nativeSession.setAttribute(name, value);
     if (value == null) {
       removeAttribute(name);
     } else {
@@ -330,6 +314,12 @@ public class GemfireHttpSession implements HttpSession, DataSerializable, Delta
     }
   }
 
+  private void checkValid() {
+    if (!isValid()) {
+      throw new IllegalStateException("Session is invalid");
+    }
+  }
+
   /**
    * Gemfire serialization {@inheritDoc}
    */
@@ -346,12 +336,6 @@ public class GemfireHttpSession implements HttpSession, DataSerializable, Delta
   public void fromData(DataInput in) throws IOException, ClassNotFoundException {
     id = DataSerializer.readString(in);
     attributes = DataSerializer.readObject(in);
-    if (getNativeSession() != null) {
-      for (String s : attributes.getAttributeNames()) {
-        getNativeSession().setAttribute(s, attributes.getAttribute(s));
-      }
-    }
-
     // Explicit sets
     serialized.set(true);
     attributes.setSession(this);
@@ -436,34 +420,6 @@ public class GemfireHttpSession implements HttpSession, DataSerializable, Delta
     this.manager = manager;
   }
 
-  /**
-   * For testing allow retrieval of the wrapped, native session.
-   */
-  public HttpSession getNativeSession() {
-    return nativeSession;
-  }
-
-
-  public void setNativeSession(HttpSession session) {
-    this.nativeSession = session;
-  }
-
-  /**
-   * Handle the process of failing over the session to a new native session object.
-   *
-   * @param session
-   */
-  public void failoverSession(HttpSession session) {
-    LOG.debug("Failing over session {} to {}", getId(), session.getId());
-    setNativeSession(session);
-    for (String name : attributes.getAttributeNames()) {
-      LOG.debug("Copying '{}' => {}", name, attributes.getAttribute(name));
-      session.setAttribute(name, attributes.getAttribute(name));
-    }
-    session.setMaxInactiveInterval(attributes.getMaxIntactiveInterval());
-    manager.putSession(this);
-  }
-
 
   /**
    * Update the last accessed time

http://git-wip-us.apache.org/repos/asf/geode/blob/c5b12117/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/GemfireSessionManager.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/GemfireSessionManager.java b/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/GemfireSessionManager.java
index c7466d6..f26df07 100644
--- a/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/GemfireSessionManager.java
+++ b/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/GemfireSessionManager.java
@@ -42,6 +42,7 @@ import javax.management.MBeanServer;
 import javax.management.ObjectName;
 import javax.naming.InitialContext;
 import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
 import javax.servlet.http.HttpSession;
 import java.util.Enumeration;
 import java.util.HashMap;
@@ -92,11 +93,6 @@ public class GemfireSessionManager implements SessionManager {
   private boolean isolated = false;
 
   /**
-   * Map of wrapping GemFire session id to native session id
-   */
-  private Map<String, String> nativeSessionMap = new HashMap<String, String>();
-
-  /**
    * MBean for statistics
    */
   private SessionStatistics mbean;
@@ -211,9 +207,9 @@ public class GemfireSessionManager implements SessionManager {
    * {@inheritDoc}
    */
   @Override
-  public HttpSession wrapSession(HttpSession nativeSession) {
+  public HttpSession wrapSession(ServletContext context, int maxInactiveInterval) {
     String id = generateId();
-    GemfireHttpSession session = new GemfireHttpSession(id, nativeSession);
+    GemfireHttpSession session = new GemfireHttpSession(id, context);
 
     /**
      * Set up the attribute container depending on how things are configured
@@ -233,6 +229,8 @@ public class GemfireSessionManager implements SessionManager {
 
     attributes.setSession(session);
     attributes.setJvmOwnerId(jvmId);
+    attributes.setMaxInactiveInterval(maxInactiveInterval);
+    attributes.setCreationTime(System.currentTimeMillis());
 
     session.setManager(this);
     session.setAttributes(attributes);
@@ -248,19 +246,6 @@ public class GemfireSessionManager implements SessionManager {
   /**
    * {@inheritDoc}
    */
-  public HttpSession getWrappingSession(String nativeId) {
-    HttpSession session = null;
-    String gemfireId = getGemfireSessionIdFromNativeId(nativeId);
-
-    if (gemfireId != null) {
-      session = getSession(gemfireId);
-    }
-    return session;
-  }
-
-  /**
-   * {@inheritDoc}
-   */
   @Override
   public void destroySession(String id) {
     if (!isStopping) {
@@ -283,18 +268,8 @@ public class GemfireSessionManager implements SessionManager {
         } catch (CacheClosedException ccex) {
           // Ignored
         }
-      } else {
-        GemfireHttpSession session = (GemfireHttpSession) sessionCache.getOperatingRegion().get(id);
-        if (session != null) {
-          session.setNativeSession(null);
-        }
       }
     }
-
-    synchronized (nativeSessionMap) {
-      String nativeId = nativeSessionMap.remove(id);
-      LOG.debug("destroySession called for {} wrapping {}", id, nativeId);
-    }
   }
 
   /**
@@ -304,46 +279,12 @@ public class GemfireSessionManager implements SessionManager {
   public void putSession(HttpSession session) {
     sessionCache.getOperatingRegion().put(session.getId(), session);
     mbean.incRegionUpdates();
-    nativeSessionMap.put(session.getId(),
-        ((GemfireHttpSession) session).getNativeSession().getId());
-  }
-
-  @Override
-  public String destroyNativeSession(String nativeId) {
-    String gemfireSessionId = getGemfireSessionIdFromNativeId(nativeId);
-    if (gemfireSessionId != null) {
-      destroySession(gemfireSessionId);
-    }
-    return gemfireSessionId;
   }
 
   public ClassLoader getReferenceClassLoader() {
     return referenceClassLoader;
   }
 
-  /**
-   * This method is called when a native session gets destroyed. It will check if the GemFire
-   * session is actually still valid/not expired and will then attach a new, native session.
-   *
-   * @param nativeId the id of the native session
-   * @return the id of the newly attached native session or null if the GemFire session was already
-   *         invalid
-   */
-  public String refreshSession(String nativeId) {
-    String gemfireId = getGemfireSessionIdFromNativeId(nativeId);
-    if (gemfireId == null) {
-      return null;
-    }
-
-    GemfireHttpSession session =
-        (GemfireHttpSession) sessionCache.getOperatingRegion().get(gemfireId);
-    if (session.isValid()) {
-
-    }
-
-    return null;
-  }
-
   public String getSessionCookieName() {
     return sessionCookieName;
   }
@@ -356,19 +297,6 @@ public class GemfireSessionManager implements SessionManager {
   ///////////////////////////////////////////////////////////////////////
   // Private methods
 
-  private String getGemfireSessionIdFromNativeId(String nativeId) {
-    if (nativeId == null) {
-      return null;
-    }
-
-    for (Map.Entry<String, String> e : nativeSessionMap.entrySet()) {
-      if (nativeId.equals(e.getValue())) {
-        return e.getKey();
-      }
-    }
-    return null;
-  }
-
   /**
    * Start the underlying distributed system
    *

http://git-wip-us.apache.org/repos/asf/geode/blob/c5b12117/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/SessionManager.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/SessionManager.java b/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/SessionManager.java
index 642c287..2c476d5 100644
--- a/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/SessionManager.java
+++ b/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/SessionManager.java
@@ -15,6 +15,7 @@
 
 package org.apache.geode.modules.session.internal.filter;
 
+import javax.servlet.ServletContext;
 import javax.servlet.http.HttpSession;
 
 /**
@@ -56,19 +57,9 @@ public interface SessionManager {
   /**
    * Create a new session, wrapping a container session.
    *
-   * @param nativeSession
    * @return the HttpSession object
    */
-  public HttpSession wrapSession(HttpSession nativeSession);
-
-  /**
-   * Get the wrapped (GemFire) session from a native session id. This method would typically be used
-   * from within session/http event listeners which receive the original session id.
-   *
-   * @param nativeId
-   * @return the wrapped GemFire session which maps the native session
-   */
-  public HttpSession getWrappingSession(String nativeId);
+  public HttpSession wrapSession(ServletContext context, int maxInactiveInterval);
 
   /**
    * Destroy the session associated with the given id.
@@ -78,14 +69,6 @@ public interface SessionManager {
   public void destroySession(String id);
 
   /**
-   * Destroy the session associated with a given native session
-   *
-   * @param id the id of the native session
-   * @return the corresponding Gemfire session which wrapped the native session and was destroyed.
-   */
-  public String destroyNativeSession(String id);
-
-  /**
    * Returns the cookie name used to hold the session id. By default this is JSESSIONID.
    *
    * @return the name of the cookie which contains the session id

http://git-wip-us.apache.org/repos/asf/geode/blob/c5b12117/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/attributes/AbstractDeltaSessionAttributes.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/attributes/AbstractDeltaSessionAttributes.java b/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/attributes/AbstractDeltaSessionAttributes.java
index 4d1f108..42b5115 100644
--- a/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/attributes/AbstractDeltaSessionAttributes.java
+++ b/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/attributes/AbstractDeltaSessionAttributes.java
@@ -87,14 +87,8 @@ public abstract class AbstractDeltaSessionAttributes extends AbstractSessionAttr
     for (DeltaEvent e : localDeltas.values()) {
       if (e.isUpdate()) {
         attributes.put(e.getName(), e.getValue());
-        if (session.getNativeSession() != null) {
-          session.getNativeSession().setAttribute(e.getName(), e.getValue());
-        }
       } else {
         attributes.remove(e.getName());
-        if (session.getNativeSession() != null) {
-          session.getNativeSession().setAttribute(e.getName(), null);
-        }
       }
     }
     jvmOwnerId = in.readUTF();

http://git-wip-us.apache.org/repos/asf/geode/blob/c5b12117/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/attributes/AbstractSessionAttributes.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/attributes/AbstractSessionAttributes.java b/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/attributes/AbstractSessionAttributes.java
index 6e0cbc4..8a3cf8b 100644
--- a/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/attributes/AbstractSessionAttributes.java
+++ b/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/attributes/AbstractSessionAttributes.java
@@ -16,6 +16,8 @@
 package org.apache.geode.modules.session.internal.filter.attributes;
 
 import org.apache.geode.DataSerializer;
+import org.apache.geode.internal.InternalDataSerializer;
+import org.apache.geode.internal.Version;
 import org.apache.geode.internal.util.BlobHelper;
 import org.apache.geode.modules.session.internal.filter.GemfireHttpSession;
 
@@ -66,6 +68,8 @@ public abstract class AbstractSessionAttributes implements SessionAttributes {
    */
   protected String jvmOwnerId;
 
+  protected long creationTime;
+
   /**
    * {@inheritDoc}
    */
@@ -119,6 +123,16 @@ public abstract class AbstractSessionAttributes implements SessionAttributes {
   }
 
   @Override
+  public long getCreationTime() {
+    return creationTime;
+  }
+
+  @Override
+  public void setCreationTime(long creationTime) {
+    this.creationTime = creationTime;
+  }
+
+  @Override
   public void setLastAccessedTime(long time) {
     lastAccessedTime = time;
   }
@@ -143,6 +157,11 @@ public abstract class AbstractSessionAttributes implements SessionAttributes {
    */
   @Override
   public void toData(DataOutput out) throws IOException {
+    toDataPre_GEODE_1_3_0_0(out);
+    out.writeLong(creationTime);
+  }
+
+  public void toDataPre_GEODE_1_3_0_0(DataOutput out) throws IOException {
     out.writeInt(maxInactiveInterval);
     out.writeLong(lastAccessedTime);
 
@@ -159,6 +178,11 @@ public abstract class AbstractSessionAttributes implements SessionAttributes {
 
   @Override
   public void fromData(DataInput in) throws IOException, ClassNotFoundException {
+    fromDataPre_GEODE_1_3_0_0(in);
+    creationTime = in.readLong();
+  }
+
+  private void fromDataPre_GEODE_1_3_0_0(DataInput in) throws IOException, ClassNotFoundException {
     maxInactiveInterval = in.readInt();
     lastAccessedTime = in.readLong();
     int size = in.readInt();

http://git-wip-us.apache.org/repos/asf/geode/blob/c5b12117/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/attributes/DeltaEvent.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/attributes/DeltaEvent.java b/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/attributes/DeltaEvent.java
index 249595a..18643ad 100644
--- a/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/attributes/DeltaEvent.java
+++ b/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/attributes/DeltaEvent.java
@@ -69,6 +69,10 @@ public class DeltaEvent implements DataSerializable {
   }
 
   private void blobifyValue() {
+    if (value instanceof byte[]) {
+      // already blobified
+      return;
+    }
     try {
       value = BlobHelper.serializeToBlob(value);
     } catch (IOException iox) {
@@ -92,7 +96,7 @@ public class DeltaEvent implements DataSerializable {
   @Override
   public void toData(DataOutput out) throws IOException {
     if (session != null) {
-      value = session.getNativeSession().getAttribute(name);
+      value = session.getAttribute(name);
       blobifyValue();
     }
     out.writeBoolean(update);

http://git-wip-us.apache.org/repos/asf/geode/blob/c5b12117/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/attributes/SessionAttributes.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/attributes/SessionAttributes.java b/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/attributes/SessionAttributes.java
index 4f4a2f8..cefb611 100644
--- a/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/attributes/SessionAttributes.java
+++ b/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/attributes/SessionAttributes.java
@@ -112,4 +112,14 @@ public interface SessionAttributes extends DataSerializable {
    * @param jvmId
    */
   public void setJvmOwnerId(String jvmId);
+
+  /**
+   * Return the creation of time of this session in milliseconds
+   */
+  long getCreationTime();
+
+  /**
+   * Set the creation time for these attributes
+   */
+  void setCreationTime(long creationTime);
 }

http://git-wip-us.apache.org/repos/asf/geode/blob/c5b12117/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/util/ThreadLocalSession.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/util/ThreadLocalSession.java b/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/util/ThreadLocalSession.java
deleted file mode 100644
index 31dd134..0000000
--- a/extensions/geode-modules-session-internal/src/main/java/org/apache/geode/modules/session/internal/filter/util/ThreadLocalSession.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for additional information regarding
- * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License. You may obtain a
- * copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package org.apache.geode.modules.session.internal.filter.util;
-
-import javax.servlet.http.HttpSession;
-
-/**
- */
-public class ThreadLocalSession {
-  private static ThreadLocal<HttpSession> threadLocal = new ThreadLocal<HttpSession>();
-
-  public static HttpSession get() {
-    return threadLocal.get();
-  }
-
-  public static void set(HttpSession session) {
-    threadLocal.set(session);
-  }
-
-  public static void remove() {
-    threadLocal.remove();
-  }
-}

http://git-wip-us.apache.org/repos/asf/geode/blob/c5b12117/extensions/geode-modules-session/src/main/java/org/apache/geode/modules/session/filter/SessionCachingFilter.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-session/src/main/java/org/apache/geode/modules/session/filter/SessionCachingFilter.java b/extensions/geode-modules-session/src/main/java/org/apache/geode/modules/session/filter/SessionCachingFilter.java
index bf58e22..3494ff1 100644
--- a/extensions/geode-modules-session/src/main/java/org/apache/geode/modules/session/filter/SessionCachingFilter.java
+++ b/extensions/geode-modules-session/src/main/java/org/apache/geode/modules/session/filter/SessionCachingFilter.java
@@ -26,6 +26,7 @@ import java.util.concurrent.atomic.AtomicInteger;
 import javax.servlet.Filter;
 import javax.servlet.FilterChain;
 import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletRequestWrapper;
@@ -46,7 +47,6 @@ import org.apache.geode.modules.session.internal.filter.GemfireSessionManager;
 import org.apache.geode.modules.session.internal.filter.SessionManager;
 import org.apache.geode.modules.session.internal.filter.attributes.DeltaQueuedSessionAttributes;
 import org.apache.geode.modules.session.internal.filter.attributes.DeltaSessionAttributes;
-import org.apache.geode.modules.session.internal.filter.util.ThreadLocalSession;
 
 /**
  * Primary class which orchestrates everything. This is the class which gets configured in the
@@ -110,18 +110,21 @@ public class SessionCachingFilter implements Filter {
 
     private HttpServletRequest outerRequest = null;
 
+    private final ServletContext context;
+
     /**
      * Need to save this in case we need the original {@code RequestDispatcher}
      */
     private HttpServletRequest originalRequest;
 
     public RequestWrapper(SessionManager manager, HttpServletRequest request,
-        ResponseWrapper response) {
+        ResponseWrapper response, ServletContext context) {
 
       super(request);
       this.response = response;
       this.manager = manager;
       this.originalRequest = request;
+      this.context = context;
 
       final Cookie[] cookies = request.getCookies();
       if (cookies != null) {
@@ -160,7 +163,6 @@ public class SessionCachingFilter implements Filter {
      */
     @Override
     public HttpSession getSession(boolean create) {
-      super.getSession(false);
       if (session != null && session.isValid()) {
         session.setIsNew(false);
         session.updateAccessTime();
@@ -172,34 +174,22 @@ public class SessionCachingFilter implements Filter {
         if (session != null) {
           session.setIsNew(false);
           // This means we've failed over to another node
-          if (session.getNativeSession() == null) {
-            try {
-              ThreadLocalSession.set(session);
-              HttpSession nativeSession = super.getSession();
-              session.failoverSession(nativeSession);
-              session.putInRegion();
-            } finally {
-              ThreadLocalSession.remove();
-            }
+          if (session.getServletContext() == null) {
+            session.setServletContext(context);
           }
         }
       }
 
       if (session == null || !session.isValid()) {
         if (create) {
+          HttpSession nativeSession = super.getSession();
           try {
-            session = (GemfireHttpSession) manager.wrapSession(null);
-            ThreadLocalSession.set(session);
-            HttpSession nativeSession = super.getSession();
-            if (session.getNativeSession() == null) {
-              session.setNativeSession(nativeSession);
-            } else {
-              assert (session.getNativeSession() == nativeSession);
-            }
+            session = (GemfireHttpSession) manager.wrapSession(context,
+                nativeSession.getMaxInactiveInterval());
             session.setIsNew(true);
             manager.putSession(session);
           } finally {
-            ThreadLocalSession.remove();
+            nativeSession.invalidate();
           }
         } else {
           // create is false, and session is either null or not valid.
@@ -222,33 +212,11 @@ public class SessionCachingFilter implements Filter {
         return;
       }
 
-      // Get the existing cookies
-      Cookie[] cookies = getCookies();
-
       Cookie cookie = new Cookie(manager.getSessionCookieName(), session.getId());
       cookie.setPath("".equals(getContextPath()) ? "/" : getContextPath());
       response.addCookie(cookie);
     }
 
-    private String getCookieString(Cookie c) {
-      StringBuilder cookie = new StringBuilder();
-      cookie.append(c.getName()).append("=").append(c.getValue());
-
-      if (c.getPath() != null) {
-        cookie.append("; ").append("Path=").append(c.getPath());
-      }
-      if (c.getDomain() != null) {
-        cookie.append("; ").append("Domain=").append(c.getDomain());
-      }
-      if (c.getSecure()) {
-        cookie.append("; ").append("Secure");
-      }
-
-      cookie.append("; HttpOnly");
-
-      return cookie.toString();
-    }
-
     /**
      * {@inheritDoc}
      */
@@ -415,7 +383,8 @@ public class SessionCachingFilter implements Filter {
     // include requests.
 
     ResponseWrapper wrappedResponse = new ResponseWrapper(httpResp);
-    final RequestWrapper wrappedRequest = new RequestWrapper(manager, httpReq, wrappedResponse);
+    final RequestWrapper wrappedRequest =
+        new RequestWrapper(manager, httpReq, wrappedResponse, filterConfig.getServletContext());
 
     Throwable problem = null;
 
@@ -616,24 +585,4 @@ public class SessionCachingFilter implements Filter {
   public static SessionManager getSessionManager() {
     return manager;
   }
-
-  /**
-   * Return the GemFire session which wraps a native session
-   *
-   * @param nativeSession the native session for which the corresponding GemFire session should be
-   *        returned.
-   * @return the GemFire session or null if no session maps to the native session
-   */
-  public static HttpSession getWrappingSession(HttpSession nativeSession) {
-    /*
-     * This is a special case where the GemFire session has been set as a ThreadLocal during session
-     * creation.
-     */
-    GemfireHttpSession gemfireSession = (GemfireHttpSession) ThreadLocalSession.get();
-    if (gemfireSession != null) {
-      gemfireSession.setNativeSession(nativeSession);
-      return gemfireSession;
-    }
-    return getSessionManager().getWrappingSession(nativeSession.getId());
-  }
 }

http://git-wip-us.apache.org/repos/asf/geode/blob/c5b12117/extensions/geode-modules-session/src/main/java/org/apache/geode/modules/session/filter/SessionListener.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-session/src/main/java/org/apache/geode/modules/session/filter/SessionListener.java b/extensions/geode-modules-session/src/main/java/org/apache/geode/modules/session/filter/SessionListener.java
index 157566d..3e0847d 100644
--- a/extensions/geode-modules-session/src/main/java/org/apache/geode/modules/session/filter/SessionListener.java
+++ b/extensions/geode-modules-session/src/main/java/org/apache/geode/modules/session/filter/SessionListener.java
@@ -22,6 +22,11 @@ import org.slf4j.LoggerFactory;
 import javax.servlet.http.HttpSessionEvent;
 import javax.servlet.http.HttpSessionListener;
 
+/**
+ * Listener to destroy gemfire sessions when native sessions are destroyed.
+ *
+ * @deprecated No longer does anything, native sessions are no longer kept around
+ */
 public class SessionListener implements HttpSessionListener {
 
   private static final Logger LOG = LoggerFactory.getLogger(SessionListener.class.getName());
@@ -32,13 +37,6 @@ public class SessionListener implements HttpSessionListener {
    * This will receive events from the container using the native sessions.
    */
   public void sessionDestroyed(HttpSessionEvent event) {
-    String nativeId = event.getSession().getId();
-    try {
-      String sessionId = SessionCachingFilter.getSessionManager().destroyNativeSession(nativeId);
-      LOG.debug("Received sessionDestroyed event for native session {} (wrapped by {})", nativeId,
-          sessionId);
-    } catch (DistributedSystemDisconnectedException dex) {
-      LOG.debug("Cache disconnected - unable to destroy native session {0}", nativeId);
-    }
+    // No op
   }
 }

http://git-wip-us.apache.org/repos/asf/geode/blob/c5b12117/extensions/geode-modules-session/src/main/java/org/apache/geode/modules/session/installer/Installer.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-session/src/main/java/org/apache/geode/modules/session/installer/Installer.java b/extensions/geode-modules-session/src/main/java/org/apache/geode/modules/session/installer/Installer.java
index 151ebb3..44ca043 100644
--- a/extensions/geode-modules-session/src/main/java/org/apache/geode/modules/session/installer/Installer.java
+++ b/extensions/geode-modules-session/src/main/java/org/apache/geode/modules/session/installer/Installer.java
@@ -48,9 +48,6 @@ public class Installer {
   private static final String GEMFIRE_FILTER_CLASS =
       "org.apache.geode.modules.session.filter.SessionCachingFilter";
 
-  private static final String GEMFIRE_LISTENER_CLASS =
-      "org.apache.geode.modules.session.filter.SessionListener";
-
   private ArgumentValues argValues;
 
   private static final Argument ARG_HELP =
@@ -220,10 +217,7 @@ public class Installer {
     final Element filterMapping = doc.createElement("filter-mapping");
     append(doc, filterMapping, "filter-name", "gemfire-session-filter");
     append(doc, filterMapping, "url-pattern", "/*");
-    final Element contextListener = doc.createElement("listener");
-    append(doc, contextListener, "listener-class", GEMFIRE_LISTENER_CLASS);
     docElement.insertBefore(filterMapping, after(docElement, "filter"));
-    docElement.insertBefore(contextListener, after(docElement, "filter-mapping"));
     return doc;
   }
 

http://git-wip-us.apache.org/repos/asf/geode/blob/c5b12117/extensions/geode-modules-session/src/test/java/org/apache/geode/modules/session/internal/filter/CommonTests.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-session/src/test/java/org/apache/geode/modules/session/internal/filter/CommonTests.java b/extensions/geode-modules-session/src/test/java/org/apache/geode/modules/session/internal/filter/CommonTests.java
index c31afc6..8c57260 100644
--- a/extensions/geode-modules-session/src/test/java/org/apache/geode/modules/session/internal/filter/CommonTests.java
+++ b/extensions/geode-modules-session/src/test/java/org/apache/geode/modules/session/internal/filter/CommonTests.java
@@ -14,10 +14,17 @@
  */
 package org.apache.geode.modules.session.internal.filter;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import java.io.IOException;
 import java.util.concurrent.TimeUnit;
+
 import javax.servlet.Filter;
 import javax.servlet.FilterChain;
 import javax.servlet.FilterConfig;
@@ -29,16 +36,15 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletRequestWrapper;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
-import javax.servlet.http.HttpSessionAttributeListener;
 
-import org.apache.geode.modules.session.filter.SessionCachingFilter;
 import com.mockrunner.mock.web.MockHttpServletRequest;
 import com.mockrunner.mock.web.MockHttpServletResponse;
-import com.mockrunner.mock.web.MockHttpSession;
 import com.mockrunner.servlet.BasicServletTestCaseAdapter;
 import org.junit.Ignore;
 import org.junit.Test;
 
+import org.apache.geode.modules.session.filter.SessionCachingFilter;
+
 /**
  * This servlet tests the effects of the downstream SessionCachingFilter filter. When these tests
  * are performed, the filter would already have taken effect.
@@ -323,59 +329,6 @@ public abstract class CommonTests extends BasicServletTestCaseAdapter {
     }
   }
 
-  /**
-   * Test that Session Attribute events get triggered
-   */
-  @Test
-  public void testSessionAttributeListener1() throws Exception {
-    AbstractListener listener = new HttpSessionAttributeListenerImpl();
-    RendezvousManager.registerListener(listener);
-    listener.setLatch(3);
-
-    doFilter();
-
-    // Ugh
-    MockHttpSession session =
-        (MockHttpSession) ((GemfireHttpSession) ((HttpServletRequest) getFilteredRequest())
-            .getSession()).getNativeSession();
-    session.addAttributeListener((HttpSessionAttributeListener) listener);
-    session.setAttribute("foo", "bar");
-    session.setAttribute("foo", "baz");
-    session.setAttribute("foo", null);
-
-    assertTrue("Event timeout", listener.await(1, TimeUnit.SECONDS));
-    assertEquals(ListenerEventType.SESSION_ATTRIBUTE_ADDED, listener.getEvents().get(0));
-    assertEquals(ListenerEventType.SESSION_ATTRIBUTE_REPLACED, listener.getEvents().get(1));
-    assertEquals(ListenerEventType.SESSION_ATTRIBUTE_REMOVED, listener.getEvents().get(2));
-  }
-
-  /**
-   * Test that both replace and remove events get triggered
-   */
-  @Test
-  public void testHttpSessionBindingListener1() throws Exception {
-    doFilter();
-
-    HttpSession session = ((HttpServletRequest) getFilteredRequest()).getSession();
-
-    HttpSessionBindingListenerImpl listener1 = new HttpSessionBindingListenerImpl(2);
-    HttpSessionBindingListenerImpl listener2 = new HttpSessionBindingListenerImpl(2);
-
-    session.setAttribute("foo", listener1);
-    session.setAttribute("foo", listener2);
-    session.setAttribute("foo", null);
-
-    assertTrue("Event timeout", listener1.await(1, TimeUnit.SECONDS));
-    assertTrue("Event timeout", listener2.await(1, TimeUnit.SECONDS));
-
-    assertEquals("Event list size incorrect", 2, listener1.getEvents().size());
-    assertEquals("Event list size incorrect", 2, listener2.getEvents().size());
-    assertEquals(ListenerEventType.SESSION_VALUE_BOUND, listener1.getEvents().get(0));
-    assertEquals(ListenerEventType.SESSION_VALUE_UNBOUND, listener1.getEvents().get(1));
-    assertEquals(ListenerEventType.SESSION_VALUE_BOUND, listener2.getEvents().get(0));
-    assertEquals(ListenerEventType.SESSION_VALUE_UNBOUND, listener2.getEvents().get(1));
-  }
-
   @Test
   public void testGetId1() throws Exception {
     doFilter();

http://git-wip-us.apache.org/repos/asf/geode/blob/c5b12117/extensions/geode-modules-session/src/test/java/org/apache/geode/modules/session/internal/filter/HttpSessionListenerImpl.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-session/src/test/java/org/apache/geode/modules/session/internal/filter/HttpSessionListenerImpl.java b/extensions/geode-modules-session/src/test/java/org/apache/geode/modules/session/internal/filter/HttpSessionListenerImpl.java
deleted file mode 100644
index fbf0d13..0000000
--- a/extensions/geode-modules-session/src/test/java/org/apache/geode/modules/session/internal/filter/HttpSessionListenerImpl.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for additional information regarding
- * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License. You may obtain a
- * copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package org.apache.geode.modules.session.internal.filter;
-
-import org.apache.geode.modules.session.filter.SessionCachingFilter;
-
-import javax.servlet.http.HttpSession;
-import javax.servlet.http.HttpSessionEvent;
-import javax.servlet.http.HttpSessionListener;
-
-public class HttpSessionListenerImpl extends AbstractListener implements HttpSessionListener {
-
-  public synchronized void sessionCreated(HttpSessionEvent se) {
-    HttpSession gfeSession = SessionCachingFilter.getWrappingSession(se.getSession());
-    gfeSession.setAttribute("gemfire-session-id", gfeSession.getId());
-    events.add(ListenerEventType.SESSION_CREATED);
-    latch.countDown();
-  }
-
-  public synchronized void sessionDestroyed(HttpSessionEvent se) {
-    events.add(ListenerEventType.SESSION_DESTROYED);
-    latch.countDown();
-  }
-}

http://git-wip-us.apache.org/repos/asf/geode/blob/c5b12117/extensions/geode-modules-session/src/test/java/org/apache/geode/modules/session/internal/filter/HttpSessionListenerImpl2.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-session/src/test/java/org/apache/geode/modules/session/internal/filter/HttpSessionListenerImpl2.java b/extensions/geode-modules-session/src/test/java/org/apache/geode/modules/session/internal/filter/HttpSessionListenerImpl2.java
deleted file mode 100644
index 5fd2c27..0000000
--- a/extensions/geode-modules-session/src/test/java/org/apache/geode/modules/session/internal/filter/HttpSessionListenerImpl2.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for additional information regarding
- * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License. You may obtain a
- * copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package org.apache.geode.modules.session.internal.filter;
-
-import org.apache.geode.modules.session.filter.SessionCachingFilter;
-
-import javax.servlet.http.HttpSession;
-import javax.servlet.http.HttpSessionEvent;
-import javax.servlet.http.HttpSessionListener;
-
-public class HttpSessionListenerImpl2 extends AbstractListener implements HttpSessionListener {
-
-  @Override
-  public void sessionCreated(HttpSessionEvent se) {
-    events.add(ListenerEventType.SESSION_CREATED);
-    latch.countDown();
-  }
-
-  @Override
-  public void sessionDestroyed(HttpSessionEvent se) {
-    HttpSession gfeSession = SessionCachingFilter.getWrappingSession(se.getSession());
-    assert (gfeSession != null);
-    events.add(ListenerEventType.SESSION_DESTROYED);
-    latch.countDown();
-  }
-}

http://git-wip-us.apache.org/repos/asf/geode/blob/c5b12117/extensions/geode-modules-session/src/test/java/org/apache/geode/modules/session/internal/filter/SessionReplicationIntegrationJUnitTest.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-session/src/test/java/org/apache/geode/modules/session/internal/filter/SessionReplicationIntegrationJUnitTest.java b/extensions/geode-modules-session/src/test/java/org/apache/geode/modules/session/internal/filter/SessionReplicationIntegrationJUnitTest.java
index 2679ecc..0577dd4 100644
--- a/extensions/geode-modules-session/src/test/java/org/apache/geode/modules/session/internal/filter/SessionReplicationIntegrationJUnitTest.java
+++ b/extensions/geode-modules-session/src/test/java/org/apache/geode/modules/session/internal/filter/SessionReplicationIntegrationJUnitTest.java
@@ -1155,48 +1155,6 @@ public class SessionReplicationIntegrationJUnitTest {
   }
 
   /**
-   * Test that the underlying native session remains the same across requests
-   */
-  @Test
-  public void testNativeSessionRemainsUnchanged() throws Exception {
-    Callback c = new Callback() {
-      @Override
-      public void call(HttpServletRequest request, HttpServletResponse response)
-          throws IOException {
-        GemfireHttpSession session = (GemfireHttpSession) request.getSession();
-        PrintWriter out = response.getWriter();
-        out.write(session.getNativeSession().getId());
-      }
-    };
-
-    tester.setAttribute("callback_1", c);
-    tester.start();
-    // ContextManager.getInstance().putContext(
-    // servletHolder.getServlet().getServletConfig().getServletContext());
-
-    request.setMethod("GET");
-    request.setURI("/test/hello");
-    request.setHeader("Host", "tester");
-    request.setVersion("HTTP/1.0");
-
-    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
-    String nativeSessionId = response.getContent();
-
-    List<Cookie> cookies = getCookies(response);
-    String sessionId = cookies.get(0).getValue();
-    Region r = getRegion();
-
-    assertEquals("Cached native session id does not match servlet returned native session id",
-        nativeSessionId, ((GemfireHttpSession) r.get(sessionId)).getNativeSession().getId());
-
-    request.setHeader("Cookie", "JSESSIONID=" + cookies.get(0).getValue());
-    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
-
-    assertEquals("Underlying native sessions must remain the same across requests", nativeSessionId,
-        ((GemfireHttpSession) r.get(sessionId)).getNativeSession().getId());
-  }
-
-  /**
    * Test session id embedded in the URL
    */
   @Test
@@ -1338,152 +1296,6 @@ public class SessionReplicationIntegrationJUnitTest {
     // sh.getServlet().getServletConfig().getServletContext());
   }
 
-
-  /**
-   * Test to try and simulate a failover scenario
-   */
-  @Test
-  public void testFailover1() throws Exception {
-    Callback c_1 = new Callback() {
-      @Override
-      public void call(HttpServletRequest request, HttpServletResponse response)
-          throws IOException, ServletException {
-        HttpSession s = request.getSession();
-        s.setAttribute("foo", "bar");
-
-        PrintWriter out = response.getWriter();
-        out.write(request.getSession().getId());
-      }
-    };
-
-    Callback c_2 = new Callback() {
-      @Override
-      public void call(HttpServletRequest request, HttpServletResponse response)
-          throws IOException, ServletException {
-        HttpSession s = request.getSession();
-
-        PrintWriter out = response.getWriter();
-        out.write((String) s.getAttribute("foo"));
-      }
-    };
-
-    tester.setAttribute("callback_1", c_1);
-    tester.setAttribute("callback_2", c_2);
-
-    ServletHolder sh = tester.addServlet(BasicServlet.class, "/request2");
-    sh.setInitParameter("test.callback", "callback_2");
-
-    tester.start();
-    // ContextManager.getInstance().putContext(
-    // sh.getServlet().getServletConfig().getServletContext());
-
-    request.setMethod("GET");
-    request.setURI("/test/hello");
-    request.setHeader("Host", "tester");
-    request.setVersion("HTTP/1.0");
-
-    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
-    String id = response.getContent();
-
-    // Now we simulate the failover by removing the native session from
-    // the stored session
-    Region r = getRegion();
-    GemfireHttpSession sessObj = (GemfireHttpSession) r.get(id);
-    sessObj.setNativeSession(null);
-
-    r.put(id, sessObj);
-
-    request.setHeader("Cookie", "JSESSIONID=" + id);
-    request.setURI("/test/request2");
-    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
-
-    assertEquals("bar", response.getContent());
-  }
-
-  @Test
-  public void testHttpSessionListener1() throws Exception {
-    HttpSessionListenerImpl listener = new HttpSessionListenerImpl();
-    tester.getContext().getSessionHandler().addEventListener(listener);
-
-    Callback c = new Callback() {
-      @Override
-      public void call(HttpServletRequest request, HttpServletResponse response)
-          throws IOException {
-        HttpSession s = request.getSession();
-        // This is set in HttpSessionListenerImpl
-        String result = (String) s.getAttribute("gemfire-session-id");
-        response.getWriter().write(result);
-      }
-    };
-
-    tester.setAttribute("callback_1", c);
-    tester.start();
-    // ContextManager.getInstance().putContext(
-    // servletHolder.getServlet().getServletConfig().getServletContext());
-
-    request.setMethod("GET");
-    request.setURI("/test/hello");
-    request.setHeader("Host", "tester");
-    request.setVersion("HTTP/1.0");
-
-    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
-
-    assertEquals(200, response.getStatus());
-
-    List<Cookie> cookies = getCookies(response);
-
-    // AbstractListener listener = RendezvousManager.getListener();
-    tester.stop();
-
-    assertTrue("Timeout waiting for events", listener.await(1, TimeUnit.SECONDS));
-    assertEquals(ListenerEventType.SESSION_CREATED, listener.events.get(0));
-    assertEquals(ListenerEventType.SESSION_DESTROYED, listener.events.get(1));
-    assertEquals(cookies.get(0).getValue(), response.getContent());
-  }
-
-  @Test
-  public void testHttpSessionListener2() throws Exception {
-    HttpSessionListenerImpl2 listener = new HttpSessionListenerImpl2();
-    tester.getContext().getSessionHandler().addEventListener(listener);
-
-    Callback c = new Callback() {
-      @Override
-      public void call(HttpServletRequest request, HttpServletResponse response)
-          throws IOException {
-        HttpSession s = request.getSession();
-        s.setAttribute("test01", "test01");
-        s = request.getSession(false);
-        s.invalidate();
-        response.getWriter().write(s.getId());
-      }
-    };
-
-    tester.setAttribute("callback_1", c);
-    tester.start();
-    // ContextManager.getInstance().putContext(
-    // servletHolder.getServlet().getServletConfig().getServletContext());
-
-    request.setMethod("GET");
-    request.setURI("/test/hello");
-    request.setHeader("Host", "tester");
-    request.setVersion("HTTP/1.0");
-
-    response = HttpTester.parseResponse(tester.getResponses(request.generate()));
-
-    assertEquals(200, response.getStatus());
-
-    List<Cookie> cookies = getCookies(response);
-
-    tester.stop();
-
-    assertTrue("Timeout waiting for events", listener.await(1, TimeUnit.SECONDS));
-    assertEquals(ListenerEventType.SESSION_CREATED, listener.events.get(0));
-    assertEquals(ListenerEventType.SESSION_DESTROYED, listener.events.get(1));
-    assertEquals(cookies.get(0).getValue(), response.getContent());
-  }
-
-
-
   // @Test
   public void testJsp() throws Exception {
     tester.setResourceBase("target/test-classes");

http://git-wip-us.apache.org/repos/asf/geode/blob/c5b12117/extensions/geode-modules-session/src/test/resources/org/apache/geode/modules/session/installer/InstallerJUnitTest.web.xml.expected
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-session/src/test/resources/org/apache/geode/modules/session/installer/InstallerJUnitTest.web.xml.expected b/extensions/geode-modules-session/src/test/resources/org/apache/geode/modules/session/installer/InstallerJUnitTest.web.xml.expected
index 1b23f2f..e4fcf6b 100644
--- a/extensions/geode-modules-session/src/test/resources/org/apache/geode/modules/session/installer/InstallerJUnitTest.web.xml.expected
+++ b/extensions/geode-modules-session/src/test/resources/org/apache/geode/modules/session/installer/InstallerJUnitTest.web.xml.expected
@@ -36,9 +36,6 @@ limitations under the License.
     <filter-name>existingFilter</filter-name>
     <url-pattern>/*</url-pattern>
   </filter-mapping>
-    <listener>
-        <listener-class>org.apache.geode.modules.session.filter.SessionListener</listener-class>
-    </listener>
 
   <servlet>
     <servlet-name>existingServlet</servlet-name>

http://git-wip-us.apache.org/repos/asf/geode/blob/c5b12117/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/CommandServlet.java
----------------------------------------------------------------------
diff --git a/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/CommandServlet.java b/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/CommandServlet.java
index dabd45b..cd44490 100644
--- a/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/CommandServlet.java
+++ b/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/CommandServlet.java
@@ -17,6 +17,7 @@ package org.apache.geode.modules.session;
 
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.util.function.Function;
 import javax.servlet.ServletConfig;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
@@ -48,37 +49,52 @@ public class CommandServlet extends HttpServlet {
     String value = request.getParameter("value");
     PrintWriter out = response.getWriter();
 
-    String cmdStr = request.getParameter("cmd");
-    if (cmdStr != null) {
-      cmd = QueryCommand.valueOf(cmdStr);
-    }
+    try {
+      String cmdStr = request.getParameter("cmd");
+      if (cmdStr != null) {
+        cmd = QueryCommand.valueOf(cmdStr);
+      }
 
-    HttpSession session;
+      HttpSession session;
 
-    switch (cmd) {
-      case SET:
-        session = request.getSession();
-        session.setAttribute(param, value);
-        break;
-      case SET_MAX_INACTIVE:
-        session = request.getSession();
-        session.setMaxInactiveInterval(Integer.valueOf(value));
-        break;
-      case GET:
-        session = request.getSession();
-        String val = (String) session.getAttribute(param);
-        if (val != null) {
-          out.write(val);
-        }
-        break;
-      case REMOVE:
-        session = request.getSession();
-        session.removeAttribute(param);
-        break;
-      case INVALIDATE:
-        session = request.getSession();
-        session.invalidate();
-        break;
+      switch (cmd) {
+        case SET:
+          session = request.getSession();
+          session.setAttribute(param, value);
+          break;
+        case SET_MAX_INACTIVE:
+          session = request.getSession();
+          session.setMaxInactiveInterval(Integer.valueOf(value));
+          break;
+        case GET:
+          session = request.getSession();
+          String val = (String) session.getAttribute(param);
+          if (val != null) {
+            out.write(val);
+          }
+          break;
+        case REMOVE:
+          session = request.getSession();
+          session.removeAttribute(param);
+          break;
+        case INVALIDATE:
+          session = request.getSession();
+          session.invalidate();
+          break;
+        case FUNCTION:
+          String functionClass = request.getParameter("function");
+          Class<? extends Function> clazz = (Class<? extends Function>) Thread.currentThread()
+              .getContextClassLoader().loadClass(functionClass);
+          Function<HttpServletRequest, String> function = clazz.newInstance();
+          String result = function.apply(request);
+          if (result != null) {
+            out.write(result);
+          }
+          break;
+      }
+    } catch (Exception e) {
+      out.write("Error in servlet: " + e.toString());
+      e.printStackTrace(out);
     }
   }
 

http://git-wip-us.apache.org/repos/asf/geode/blob/c5b12117/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/ListenerStoredInSessionContext.java
----------------------------------------------------------------------
diff --git a/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/ListenerStoredInSessionContext.java b/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/ListenerStoredInSessionContext.java
new file mode 100644
index 0000000..d0c4b63
--- /dev/null
+++ b/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/ListenerStoredInSessionContext.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package org.apache.geode.modules.session;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+public class ListenerStoredInSessionContext implements ServletContextListener {
+  @Override
+  public void contextInitialized(final ServletContextEvent sce) {
+    sce.getServletContext().setAttribute(getClass().getName(), this);
+  }
+
+  @Override
+  public void contextDestroyed(final ServletContextEvent sce) {
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c5b12117/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/QueryCommand.java
----------------------------------------------------------------------
diff --git a/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/QueryCommand.java b/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/QueryCommand.java
index a3a63c3..b22787c 100644
--- a/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/QueryCommand.java
+++ b/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/QueryCommand.java
@@ -29,6 +29,8 @@ public enum QueryCommand {
 
   INVALIDATE,
 
-  UNKNOWN;
+  UNKNOWN,
+
+  FUNCTION;
 
 }

http://git-wip-us.apache.org/repos/asf/geode/blob/c5b12117/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/SessionCountingListener.java
----------------------------------------------------------------------
diff --git a/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/SessionCountingListener.java b/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/SessionCountingListener.java
new file mode 100644
index 0000000..829789f
--- /dev/null
+++ b/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/SessionCountingListener.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode.modules.session;
+
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.servlet.http.HttpSessionEvent;
+import javax.servlet.http.HttpSessionListener;
+
+public class SessionCountingListener extends ListenerStoredInSessionContext
+    implements HttpSessionListener {
+  private final AtomicInteger sessionCreates = new AtomicInteger();
+  private final AtomicInteger sessionDestroys = new AtomicInteger();
+
+  @Override
+  public void sessionCreated(final HttpSessionEvent se) {
+    sessionCreates.incrementAndGet();
+  }
+
+  @Override
+  public void sessionDestroyed(final HttpSessionEvent se) {
+    sessionDestroys.incrementAndGet();
+  }
+
+  public int getSessionCreates() {
+    return sessionCreates.get();
+  }
+
+  public int getSessionDestroys() {
+    return sessionDestroys.get();
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c5b12117/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/functions/GetMaxInactiveInterval.java
----------------------------------------------------------------------
diff --git a/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/functions/GetMaxInactiveInterval.java b/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/functions/GetMaxInactiveInterval.java
new file mode 100644
index 0000000..b37fee7
--- /dev/null
+++ b/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/functions/GetMaxInactiveInterval.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package org.apache.geode.modules.session.functions;
+
+import java.util.function.Function;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.geode.modules.session.SessionCountingListener;
+
+public class GetMaxInactiveInterval implements Function<HttpServletRequest, String> {
+  @Override
+  public String apply(final HttpServletRequest request) {
+    return Integer.toString(request.getSession().getMaxInactiveInterval());
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c5b12117/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/functions/GetSessionCount.java
----------------------------------------------------------------------
diff --git a/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/functions/GetSessionCount.java b/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/functions/GetSessionCount.java
new file mode 100644
index 0000000..ef6e958
--- /dev/null
+++ b/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/functions/GetSessionCount.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package org.apache.geode.modules.session.functions;
+
+import org.apache.geode.modules.session.SessionCountingListener;
+
+import java.util.function.Function;
+import javax.servlet.http.HttpServletRequest;
+
+public class GetSessionCount implements Function<HttpServletRequest, String> {
+  @Override
+  public String apply(final HttpServletRequest request) {
+    SessionCountingListener listener = (SessionCountingListener) request.getSession()
+        .getServletContext().getAttribute(SessionCountingListener.class.getName());
+    return String.valueOf(listener.getSessionCreates() - listener.getSessionDestroys());
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c5b12117/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/functions/GetSessionCreatedCount.java
----------------------------------------------------------------------
diff --git a/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/functions/GetSessionCreatedCount.java b/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/functions/GetSessionCreatedCount.java
new file mode 100644
index 0000000..bb5a62a
--- /dev/null
+++ b/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/functions/GetSessionCreatedCount.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package org.apache.geode.modules.session.functions;
+
+import org.apache.geode.modules.session.SessionCountingListener;
+
+import java.util.function.Function;
+import javax.servlet.http.HttpServletRequest;
+
+public class GetSessionCreatedCount implements Function<HttpServletRequest, String> {
+  @Override
+  public String apply(final HttpServletRequest request) {
+    SessionCountingListener listener = (SessionCountingListener) request.getSession()
+        .getServletContext().getAttribute(SessionCountingListener.class.getName());
+    return String.valueOf(listener.getSessionCreates());
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c5b12117/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/functions/GetSessionDestroyedCount.java
----------------------------------------------------------------------
diff --git a/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/functions/GetSessionDestroyedCount.java b/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/functions/GetSessionDestroyedCount.java
new file mode 100644
index 0000000..f8d3e66
--- /dev/null
+++ b/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/functions/GetSessionDestroyedCount.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package org.apache.geode.modules.session.functions;
+
+import org.apache.geode.modules.session.SessionCountingListener;
+
+import java.util.function.Function;
+import javax.servlet.http.HttpServletRequest;
+
+public class GetSessionDestroyedCount implements Function<HttpServletRequest, String> {
+  @Override
+  public String apply(final HttpServletRequest request) {
+    SessionCountingListener listener = (SessionCountingListener) request.getSession()
+        .getServletContext().getAttribute(SessionCountingListener.class.getName());
+    return String.valueOf(listener.getSessionDestroys());
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/c5b12117/extensions/session-testing-war/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/extensions/session-testing-war/src/main/webapp/WEB-INF/web.xml b/extensions/session-testing-war/src/main/webapp/WEB-INF/web.xml
index 1ed33cd..3746c08 100644
--- a/extensions/session-testing-war/src/main/webapp/WEB-INF/web.xml
+++ b/extensions/session-testing-war/src/main/webapp/WEB-INF/web.xml
@@ -40,4 +40,12 @@ limitations under the License.
     <url-pattern>/*</url-pattern>
   </servlet-mapping>
 
+  <session-config>
+    <session-timeout>59</session-timeout>
+  </session-config>
+
+  <listener>
+    <listener-class>org.apache.geode.modules.session.SessionCountingListener</listener-class>
+  </listener>
+
 </web-app>

http://git-wip-us.apache.org/repos/asf/geode/blob/c5b12117/geode-assembly/src/test/java/org/apache/geode/session/tests/CargoTestBase.java
----------------------------------------------------------------------
diff --git a/geode-assembly/src/test/java/org/apache/geode/session/tests/CargoTestBase.java b/geode-assembly/src/test/java/org/apache/geode/session/tests/CargoTestBase.java
index 92f3490..5dcdd6a 100644
--- a/geode-assembly/src/test/java/org/apache/geode/session/tests/CargoTestBase.java
+++ b/geode-assembly/src/test/java/org/apache/geode/session/tests/CargoTestBase.java
@@ -19,6 +19,8 @@ import static org.junit.Assert.assertEquals;
 import java.io.IOException;
 import java.net.URISyntaxException;
 
+import org.apache.geode.modules.session.functions.GetMaxInactiveInterval;
+import org.apache.geode.modules.session.functions.GetSessionCount;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
@@ -160,6 +162,10 @@ public abstract class CargoTestBase extends JUnit4CacheTestCase {
 
     client.invalidate();
 
+    verifySessionIsRemoved(key);
+  }
+
+  protected void verifySessionIsRemoved(String key) throws IOException, URISyntaxException {
     getKeyValueDataOnAllClients(key, "", null);
   }
 
@@ -178,12 +184,52 @@ public abstract class CargoTestBase extends JUnit4CacheTestCase {
     client.setPort(Integer.parseInt(manager.getContainerPort(0)));
     Client.Response resp = client.set(key, value);
 
-    getKeyValueDataOnAllClients(key, value, resp.getSessionCookie());
+    if (!localCacheEnabled()) {
+      getKeyValueDataOnAllClients(key, value, resp.getSessionCookie());
+    }
 
     client.setMaxInactive(1);
     Thread.sleep(5000);
 
-    getKeyValueDataOnAllClients(key, "", null);
+    verifySessionIsRemoved(key);
+  }
+
+  private boolean localCacheEnabled() {
+    return getInstall().getConnectionType().enableLocalCache();
+  }
+
+  /**
+   * Test that if a session is not used within the expiration time, it is expired and removed from
+   * all containers
+   */
+  @Test
+  public void sessionPicksUpSessionTimeoutConfiguredInWebXml()
+      throws IOException, URISyntaxException, InterruptedException {
+    manager.startAllInactiveContainers();
+
+    String key = "value_testSessionExpiration";
+    String value = "Foo";
+
+    client.setPort(Integer.parseInt(manager.getContainerPort(0)));
+    Client.Response resp = client.set(key, value);
+
+    // 59 minutes is the value configured in web.xml
+    verifyMaxInactiveInterval(59 * 60);
+
+    if (!localCacheEnabled()) {
+      client.setMaxInactive(63);
+
+      verifyMaxInactiveInterval(63);
+    }
+
+  }
+
+  protected void verifyMaxInactiveInterval(int expected) throws IOException, URISyntaxException {
+    for (int i = 0; i < manager.numContainers(); i++) {
+      client.setPort(Integer.parseInt(manager.getContainerPort(i)));
+      assertEquals(Integer.toString(expected),
+          client.executionFunction(GetMaxInactiveInterval.class).getResponse());
+    }
   }
 
 
@@ -196,22 +242,28 @@ public abstract class CargoTestBase extends JUnit4CacheTestCase {
       throws URISyntaxException, IOException, InterruptedException {
     manager.startAllInactiveContainers();
 
-    int timeToExp = 5;
+    int timeToExp = 30;
     String key = "value_testSessionExpiration";
     String value = "Foo";
 
     client.setPort(Integer.parseInt(manager.getContainerPort(0)));
     Client.Response resp = client.set(key, value);
+    String cookie = resp.getSessionCookie();
 
-    client.setMaxInactive(timeToExp);
+    resp = client.setMaxInactive(timeToExp);
+    assertEquals(cookie, resp.getSessionCookie());
 
     long startTime = System.currentTimeMillis();
     long curTime = System.currentTimeMillis();
     // Run for 2 times the set expiration time
     while (curTime - startTime < timeToExp * 2000) {
-      client.get(key);
+      resp = client.get(key);
       Thread.sleep(500);
       curTime = System.currentTimeMillis();
+
+      assertEquals("Sessions are not replicating properly", cookie, resp.getSessionCookie());
+      assertEquals("Containers are not replicating session expiration reset", value,
+          resp.getResponse());
     }
 
     getKeyValueDataOnAllClients(key, value, resp.getSessionCookie());
@@ -230,7 +282,10 @@ public abstract class CargoTestBase extends JUnit4CacheTestCase {
     client.setPort(Integer.parseInt(manager.getContainerPort(0)));
     Client.Response resp = client.set(key, value);
 
-    getKeyValueDataOnAllClients(key, value, resp.getSessionCookie());
+
+    if (!localCacheEnabled()) {
+      getKeyValueDataOnAllClients(key, value, resp.getSessionCookie());
+    }
 
     client.setPort(Integer.parseInt(manager.getContainerPort(0)));
     client.remove(key);

http://git-wip-us.apache.org/repos/asf/geode/blob/c5b12117/geode-assembly/src/test/java/org/apache/geode/session/tests/Client.java
----------------------------------------------------------------------
diff --git a/geode-assembly/src/test/java/org/apache/geode/session/tests/Client.java b/geode-assembly/src/test/java/org/apache/geode/session/tests/Client.java
index 52968d4..7237b93 100644
--- a/geode-assembly/src/test/java/org/apache/geode/session/tests/Client.java
+++ b/geode-assembly/src/test/java/org/apache/geode/session/tests/Client.java
@@ -33,6 +33,10 @@ import org.apache.http.util.EntityUtils;
 
 import org.apache.geode.modules.session.CommandServlet;
 import org.apache.geode.modules.session.QueryCommand;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.function.Function;
+import javax.servlet.http.HttpServletRequest;
 
 /**
  * A simple http client that talks to a server running the session-testing-war.
@@ -113,6 +117,20 @@ public class Client {
   }
 
   /**
+   * Instantiate and execute a function in the server. Note that this function must be present in
+   * the sesssion testing war.
+   */
+  public Response executionFunction(
+      Class<? extends Function<HttpServletRequest, String>> functionClass)
+      throws IOException, URISyntaxException {
+    resetURI();
+    reqURIBuild.setParameter("cmd", QueryCommand.FUNCTION.name());
+    reqURIBuild.setParameter("function", functionClass.getName());
+
+    return doRequest(new HttpGet(reqURIBuild.build()), true);
+  }
+
+  /**
    * Remove the session attribute on the server
    * 
    * @param key - the session attribute to remove

http://git-wip-us.apache.org/repos/asf/geode/blob/c5b12117/geode-assembly/src/test/java/org/apache/geode/session/tests/ContainerInstall.java
----------------------------------------------------------------------
diff --git a/geode-assembly/src/test/java/org/apache/geode/session/tests/ContainerInstall.java b/geode-assembly/src/test/java/org/apache/geode/session/tests/ContainerInstall.java
index ede100e..fafb8f6 100644
--- a/geode-assembly/src/test/java/org/apache/geode/session/tests/ContainerInstall.java
+++ b/geode-assembly/src/test/java/org/apache/geode/session/tests/ContainerInstall.java
@@ -75,15 +75,21 @@ public abstract class ContainerInstall {
    * identify XML files or connection types when setting up containers.
    */
   public enum ConnectionType {
-    PEER_TO_PEER("peer-to-peer", "cache-peer.xml"),
-    CLIENT_SERVER("client-server", "cache-client.xml");
+    PEER_TO_PEER("peer-to-peer", "cache-peer.xml", false, false),
+    CLIENT_SERVER("client-server", "cache-client.xml", false, true),
+    CACHING_CLIENT_SERVER("client-server", "cache-client.xml", true, true);
 
     private final String name;
     private final String cacheXMLFileName;
+    private final boolean enableLocalCache;
+    private final boolean isClientServer;
 
-    ConnectionType(String name, String cacheXMLFileName) {
+    ConnectionType(String name, String cacheXMLFileName, boolean enableLocalCache,
+        boolean isClientServer) {
       this.name = name;
       this.cacheXMLFileName = cacheXMLFileName;
+      this.enableLocalCache = enableLocalCache;
+      this.isClientServer = isClientServer;
     }
 
     public String getName() {
@@ -93,6 +99,14 @@ public abstract class ContainerInstall {
     public String getCacheXMLFileName() {
       return cacheXMLFileName;
     }
+
+    public boolean enableLocalCache() {
+      return enableLocalCache;
+    }
+
+    public boolean isClientServer() {
+      return isClientServer;
+    }
   }
 
   public ContainerInstall(String installDir, String downloadURL, ConnectionType connType,
@@ -176,7 +190,7 @@ public abstract class ContainerInstall {
    * which checks for a peer to peer installation (just check if not client server).
    */
   public boolean isClientServer() {
-    return connType == ConnectionType.CLIENT_SERVER;
+    return connType.isClientServer();
   }
 
   /**