You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by ja...@apache.org on 2016/07/27 18:34:09 UTC

[1/2] incubator-geode git commit: GEODE-1675: Session Management modules need to be updated to work with Tomcat 8.5.4

Repository: incubator-geode
Updated Branches:
  refs/heads/develop 9389c6fec -> a6e9569f5


http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/a6e9569f/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/Tomcat6DeltaSessionManager.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/Tomcat6DeltaSessionManager.java b/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/Tomcat6DeltaSessionManager.java
index d5b5991..c89b990 100644
--- a/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/Tomcat6DeltaSessionManager.java
+++ b/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/Tomcat6DeltaSessionManager.java
@@ -17,10 +17,17 @@
 package com.gemstone.gemfire.modules.session.catalina;
 
 import org.apache.catalina.LifecycleException;
+import org.apache.catalina.LifecycleListener;
+import org.apache.catalina.util.LifecycleSupport;
 
 public class Tomcat6DeltaSessionManager extends DeltaSessionManager {
 
   /**
+   * The <code>LifecycleSupport</code> for this component.
+   */
+  protected LifecycleSupport lifecycle = new LifecycleSupport(this);
+
+  /**
    * Prepare for the beginning of active use of the public methods of this component.  This method should be called
    * after <code>configure()</code>, and before any of the public methods of the component are utilized.
    *
@@ -95,4 +102,33 @@ public class Tomcat6DeltaSessionManager extends DeltaSessionManager {
       unregisterCommitSessionValve();
     }
   }
+
+  /**
+   * Add a lifecycle event listener to this component.
+   *
+   * @param listener The listener to add
+   */
+  @Override
+  public void addLifecycleListener(LifecycleListener listener) {
+    this.lifecycle.addLifecycleListener(listener);
+  }
+
+  /**
+   * Get the lifecycle listeners associated with this lifecycle. If this Lifecycle has no listeners registered, a
+   * zero-length array is returned.
+   */
+  @Override
+  public LifecycleListener[] findLifecycleListeners() {
+    return this.lifecycle.findLifecycleListeners();
+  }
+
+  /**
+   * Remove a lifecycle event listener from this component.
+   *
+   * @param listener The listener to remove
+   */
+  @Override
+  public void removeLifecycleListener(LifecycleListener listener) {
+    this.lifecycle.removeLifecycleListener(listener);
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/a6e9569f/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/callback/SessionExpirationCacheListener.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/callback/SessionExpirationCacheListener.java b/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/callback/SessionExpirationCacheListener.java
index dff6d58..5893c95 100644
--- a/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/callback/SessionExpirationCacheListener.java
+++ b/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/callback/SessionExpirationCacheListener.java
@@ -27,6 +27,8 @@ import com.gemstone.gemfire.modules.util.ContextMapper;
 import javax.servlet.http.HttpSession;
 import java.util.Properties;
 
+import org.apache.catalina.session.ManagerBase;
+
 public class SessionExpirationCacheListener extends CacheListenerAdapter<String, HttpSession> implements Declarable {
 
   public void afterDestroy(EntryEvent<String, HttpSession> event) {
@@ -47,7 +49,7 @@ public class SessionExpirationCacheListener extends CacheListenerAdapter<String,
       Object callback = event.getCallbackArgument();
       if (callback != null && callback instanceof DeltaSession) {
         session = (DeltaSession) callback;
-        DeltaSessionManager m = ContextMapper.getContext(session.getContextName());
+        ManagerBase m = ContextMapper.getContext(session.getContextName());
         if (m != null) {
           session.setOwner(m);
         }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/a6e9569f/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionAttributeEvent.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionAttributeEvent.java b/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionAttributeEvent.java
index 90b6f28..c930d6f 100644
--- a/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionAttributeEvent.java
+++ b/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionAttributeEvent.java
@@ -18,8 +18,9 @@ package com.gemstone.gemfire.modules.session.catalina.internal;
 
 import com.gemstone.gemfire.DataSerializable;
 import com.gemstone.gemfire.modules.session.catalina.DeltaSession;
+import com.gemstone.gemfire.modules.session.catalina.DeltaSessionInterface;
 
 public interface DeltaSessionAttributeEvent extends DataSerializable {
 
-  public void apply(DeltaSession session);
+  public void apply(DeltaSessionInterface session);
 }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/a6e9569f/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionAttributeEventBatch.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionAttributeEventBatch.java b/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionAttributeEventBatch.java
index 47df071..8e4c0c3 100644
--- a/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionAttributeEventBatch.java
+++ b/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionAttributeEventBatch.java
@@ -21,6 +21,7 @@ import com.gemstone.gemfire.cache.Cache;
 import com.gemstone.gemfire.cache.Region;
 import com.gemstone.gemfire.modules.gatewaydelta.AbstractGatewayDeltaEvent;
 import com.gemstone.gemfire.modules.session.catalina.DeltaSession;
+import com.gemstone.gemfire.modules.session.catalina.DeltaSessionInterface;
 
 import java.io.DataInput;
 import java.io.DataOutput;
@@ -47,8 +48,8 @@ public class DeltaSessionAttributeEventBatch extends AbstractGatewayDeltaEvent {
   }
 
   public void apply(Cache cache) {
-    Region<String, DeltaSession> region = getRegion(cache);
-    DeltaSession session = region.get(this.key);
+    Region<String, DeltaSessionInterface> region = getRegion(cache);
+    DeltaSessionInterface session = region.get(this.key);
     if (session == null) {
       StringBuilder builder = new StringBuilder();
       builder.append("Session ").append(this.key).append(" was not found while attempting to apply ").append(this);

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/a6e9569f/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionDestroyAttributeEvent.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionDestroyAttributeEvent.java b/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionDestroyAttributeEvent.java
index 989474f..dd96f49 100644
--- a/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionDestroyAttributeEvent.java
+++ b/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionDestroyAttributeEvent.java
@@ -20,6 +20,7 @@ import com.gemstone.gemfire.DataSerializable;
 import com.gemstone.gemfire.DataSerializer;
 import com.gemstone.gemfire.Instantiator;
 import com.gemstone.gemfire.modules.session.catalina.DeltaSession;
+import com.gemstone.gemfire.modules.session.catalina.DeltaSessionInterface;
 
 import java.io.DataInput;
 import java.io.DataOutput;
@@ -42,7 +43,7 @@ public class DeltaSessionDestroyAttributeEvent implements DeltaSessionAttributeE
     return this.attributeName;
   }
 
-  public void apply(DeltaSession session) {
+  public void apply(DeltaSessionInterface session) {
     session.localDestroyAttribute(this.attributeName);
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/a6e9569f/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionUpdateAttributeEvent.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionUpdateAttributeEvent.java b/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionUpdateAttributeEvent.java
index 6678e55..7b47280 100644
--- a/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionUpdateAttributeEvent.java
+++ b/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionUpdateAttributeEvent.java
@@ -20,6 +20,7 @@ import com.gemstone.gemfire.DataSerializable;
 import com.gemstone.gemfire.DataSerializer;
 import com.gemstone.gemfire.Instantiator;
 import com.gemstone.gemfire.modules.session.catalina.DeltaSession;
+import com.gemstone.gemfire.modules.session.catalina.DeltaSessionInterface;
 
 import java.io.DataInput;
 import java.io.DataOutput;
@@ -48,7 +49,7 @@ public class DeltaSessionUpdateAttributeEvent implements DeltaSessionAttributeEv
     return this.attributeValue;
   }
 
-  public void apply(DeltaSession session) {
+  public void apply(DeltaSessionInterface session) {
     session.localUpdateAttribute(this.attributeName, this.attributeValue);
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/a6e9569f/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/util/ContextMapper.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/util/ContextMapper.java b/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/util/ContextMapper.java
index 3b7b2de..e539d89 100644
--- a/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/util/ContextMapper.java
+++ b/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/util/ContextMapper.java
@@ -21,6 +21,8 @@ import com.gemstone.gemfire.modules.session.catalina.DeltaSessionManager;
 import java.util.HashMap;
 import java.util.Map;
 
+import org.apache.catalina.session.ManagerBase;
+
 /**
  * This basic singleton class maps context paths to manager instances.
  * <p>
@@ -33,21 +35,21 @@ import java.util.Map;
 
 public class ContextMapper {
 
-  private static Map<String, DeltaSessionManager> managers = new HashMap<String, DeltaSessionManager>();
+  private static Map<String, ManagerBase> managers = new HashMap<String, ManagerBase>();
 
   private ContextMapper() {
     // This is a singleton
   }
 
-  public static void addContext(String path, DeltaSessionManager manager) {
+  public static void addContext(String path, ManagerBase manager) {
     managers.put(path, manager);
   }
 
-  public static DeltaSessionManager getContext(String path) {
+  public static ManagerBase getContext(String path) {
     return managers.get(path);
   }
 
-  public static DeltaSessionManager removeContext(String path) {
+  public static ManagerBase removeContext(String path) {
     return managers.remove(path);
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/a6e9569f/gradle/dependency-versions.properties
----------------------------------------------------------------------
diff --git a/gradle/dependency-versions.properties b/gradle/dependency-versions.properties
index aafacef..a19520c 100644
--- a/gradle/dependency-versions.properties
+++ b/gradle/dependency-versions.properties
@@ -105,3 +105,4 @@ system-rules.version = 1.16.0
 tempus-fugit.version = 1.1
 tomcat6.version = 6.0.37
 tomcat7.version = 7.0.30
+tomcat8.version = 8.5.4

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/a6e9569f/settings.gradle
----------------------------------------------------------------------
diff --git a/settings.gradle b/settings.gradle
index ca34692..95c15f2 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -30,6 +30,7 @@ include 'geode-wan'
 include 'geode-cq'
 include 'extensions/geode-modules'
 include 'extensions/geode-modules-tomcat7'
+include 'extensions/geode-modules-tomcat8'
 include 'extensions/geode-modules-hibernate'
 include 'extensions/geode-modules-session-internal'
 include 'extensions/geode-modules-session'


[2/2] incubator-geode git commit: GEODE-1675: Session Management modules need to be updated to work with Tomcat 8.5.4

Posted by ja...@apache.org.
GEODE-1675: Session Management modules need to be updated to work with Tomcat 8.5.4

* Extracted DeltaSessionInterface to allow shared code between classes for Tomcat 6,7,8
* Added new test classes


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

Branch: refs/heads/develop
Commit: a6e9569f510eb3bda736474e508b7832e63453ec
Parents: 9389c6f
Author: Jason Huynh <hu...@gmail.com>
Authored: Thu Jul 14 14:10:39 2016 -0700
Committer: Jason Huynh <hu...@gmail.com>
Committed: Wed Jul 27 11:06:10 2016 -0700

----------------------------------------------------------------------
 extensions/geode-modules-assembly/build.gradle  |   7 +-
 .../catalina/Tomcat7DeltaSessionManager.java    |  35 ++
 extensions/geode-modules-tomcat8/build.gradle   |  58 ++
 .../modules/session/catalina/DeltaSession8.java | 595 +++++++++++++++++++
 .../catalina/Tomcat8DeltaSessionManager.java    | 140 +++++
 .../modules/session/EmbeddedTomcat8.java        | 193 ++++++
 .../session/TestSessionsTomcat8Base.java        | 464 +++++++++++++++
 .../session/Tomcat8SessionsJUnitTest.java       |  32 +
 .../test/resources/tomcat/conf/tomcat-users.xml |   3 +
 .../src/test/resources/tomcat/logs/.gitkeep     |   0
 .../src/test/resources/tomcat/temp/.gitkeep     |   0
 .../gatewaydelta/GatewayDeltaDestroyEvent.java  |   4 +-
 .../session/catalina/CommitSessionValve.java    |  11 +-
 .../modules/session/catalina/DeltaSession.java  |  20 +-
 .../session/catalina/DeltaSessionFacade.java    |   4 +-
 .../session/catalina/DeltaSessionInterface.java |  52 ++
 .../session/catalina/DeltaSessionManager.java   | 127 ++--
 .../catalina/Tomcat6DeltaSessionManager.java    |  36 ++
 .../SessionExpirationCacheListener.java         |   4 +-
 .../internal/DeltaSessionAttributeEvent.java    |   3 +-
 .../DeltaSessionAttributeEventBatch.java        |   5 +-
 .../DeltaSessionDestroyAttributeEvent.java      |   3 +-
 .../DeltaSessionUpdateAttributeEvent.java       |   3 +-
 .../gemfire/modules/util/ContextMapper.java     |  10 +-
 gradle/dependency-versions.properties           |   1 +
 settings.gradle                                 |   1 +
 26 files changed, 1712 insertions(+), 99 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/a6e9569f/extensions/geode-modules-assembly/build.gradle
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-assembly/build.gradle b/extensions/geode-modules-assembly/build.gradle
index 0f7518f..f037aad 100644
--- a/extensions/geode-modules-assembly/build.gradle
+++ b/extensions/geode-modules-assembly/build.gradle
@@ -50,6 +50,7 @@ def configureTcServerAssembly = {
   into('geode-cs/lib') {
     from getJarArtifact(':extensions/geode-modules')
     from getJarArtifact(':extensions/geode-modules-tomcat7')
+    from getJarArtifact(':extensions/geode-modules-tomcat8')
     from configurations.slf4jDeps
   }
   into('geode-cs/bin') {
@@ -82,6 +83,7 @@ def configureTcServerAssembly = {
   into('geode-p2p/lib') {
     from getJarArtifact(':extensions/geode-modules')
     from getJarArtifact(':extensions/geode-modules-tomcat7')
+    from getJarArtifact(':extensions/geode-modules-tomcat8')
     from configurations.slf4jDeps
   }
   into('geode-p2p/bin') {
@@ -136,6 +138,7 @@ task distTomcat(type: Zip, dependsOn: ':extensions/geode-modules:assemble') {
   into('lib') {
     from getJarArtifact(':extensions/geode-modules')
     from getJarArtifact(':extensions/geode-modules-tomcat7')
+    from getJarArtifact(':extensions/geode-modules-tomcat8')
     from configurations.slf4jDeps
   }
   into('bin') {
@@ -189,11 +192,11 @@ task distAppServer(type: Zip, dependsOn: ':extensions/geode-modules-session:asse
   }
 }
 
-task distTcServer(type: Zip, dependsOn: [':extensions/geode-modules:assemble', ':extensions/geode-modules-tomcat7:assemble']) {
+task distTcServer(type: Zip, dependsOn: [':extensions/geode-modules:assemble', ':extensions/geode-modules-tomcat7:assemble', ':extensions/geode-modules-tomcat8:assemble'] ) {
   configure(configureTcServerAssembly)
 }
 
-task distTcServer30(type: Zip, dependsOn: [':extensions/geode-modules:assemble', ':extensions/geode-modules-tomcat7:assemble']) {
+task distTcServer30(type: Zip, dependsOn: [':extensions/geode-modules:assemble', ':extensions/geode-modules-tomcat7:assemble', ':extensions/geode-modules-tomcat8:assemble']) {
   configure(configureTcServerAssembly)
   configure(configureTcServer30Assembly)
 }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/a6e9569f/extensions/geode-modules-tomcat7/src/main/java/com/gemstone/gemfire/modules/session/catalina/Tomcat7DeltaSessionManager.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-tomcat7/src/main/java/com/gemstone/gemfire/modules/session/catalina/Tomcat7DeltaSessionManager.java b/extensions/geode-modules-tomcat7/src/main/java/com/gemstone/gemfire/modules/session/catalina/Tomcat7DeltaSessionManager.java
index d1f44bb..8776c16 100644
--- a/extensions/geode-modules-tomcat7/src/main/java/com/gemstone/gemfire/modules/session/catalina/Tomcat7DeltaSessionManager.java
+++ b/extensions/geode-modules-tomcat7/src/main/java/com/gemstone/gemfire/modules/session/catalina/Tomcat7DeltaSessionManager.java
@@ -17,13 +17,20 @@
 package com.gemstone.gemfire.modules.session.catalina;
 
 import org.apache.catalina.LifecycleException;
+import org.apache.catalina.LifecycleListener;
 import org.apache.catalina.LifecycleState;
+import org.apache.catalina.util.LifecycleSupport;
 
 import java.io.IOException;
 
 public class Tomcat7DeltaSessionManager extends DeltaSessionManager {
 
   /**
+   * The <code>LifecycleSupport</code> for this component.
+   */
+  protected LifecycleSupport lifecycle = new LifecycleSupport(this);
+
+  /**
    * Prepare for the beginning of active use of the public methods of this component.  This method should be called
    * after <code>configure()</code>, and before any of the public methods of the component are utilized.
    *
@@ -109,4 +116,32 @@ public class Tomcat7DeltaSessionManager extends DeltaSessionManager {
     this.setState(LifecycleState.STOPPING);
   }
 
+  /**
+   * Add a lifecycle event listener to this component.
+   *
+   * @param listener The listener to add
+   */
+  @Override
+  public void addLifecycleListener(LifecycleListener listener) {
+    this.lifecycle.addLifecycleListener(listener);
+  }
+
+  /**
+   * Get the lifecycle listeners associated with this lifecycle. If this Lifecycle has no listeners registered, a
+   * zero-length array is returned.
+   */
+  @Override
+  public LifecycleListener[] findLifecycleListeners() {
+    return this.lifecycle.findLifecycleListeners();
+  }
+
+  /**
+   * Remove a lifecycle event listener from this component.
+   *
+   * @param listener The listener to remove
+   */
+  @Override
+  public void removeLifecycleListener(LifecycleListener listener) {
+    this.lifecycle.removeLifecycleListener(listener);
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/a6e9569f/extensions/geode-modules-tomcat8/build.gradle
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-tomcat8/build.gradle b/extensions/geode-modules-tomcat8/build.gradle
new file mode 100644
index 0000000..dfa86cf
--- /dev/null
+++ b/extensions/geode-modules-tomcat8/build.gradle
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+test  {
+  doFirst {
+    copy {
+      from 'build/resources/test/tomcat'
+      into 'build/test/tomcat/'
+    }
+  }
+}
+
+dependencies {
+  compile(project(':extensions/geode-modules')) {
+    exclude group: 'org.apache.tomcat'
+  }
+
+  compile ('org.apache.tomcat:tomcat-catalina:' + project.'tomcat8.version') {
+    exclude module: 'tomcat-annotations-api'
+    exclude module: 'tomcat-servlet-api'
+  }
+  compile ('org.apache.tomcat:tomcat-coyote:' + project.'tomcat8.version') {
+    exclude module: 'tomcat-servlet-api'
+  }
+  compile 'org.apache.tomcat:tomcat-juli:' + project.'tomcat8.version'
+
+  testCompile 'org.httpunit:httpunit:' + project.'httpunit.version'
+
+  testRuntime 'javax.annotation:jsr250-api:' + project.'javax.jsr250-api.version'
+  testRuntime 'javax.ejb:ejb-api:' + project.'javax.ejb-api.version'
+  compile 'javax.servlet:javax.servlet-api:' + '3.1.0'
+  testRuntime 'org.eclipse.persistence:javax.persistence:' + project.'javax.persistence-api.version'
+  compile 'javax.security.auth.message:javax.security.auth.message-api:' + '1.1'
+
+  testCompile project(path: ':geode-junit')
+  testCompile files(project(':geode-core').sourceSets.test.output)
+  testCompile files(project(':extensions/geode-modules').sourceSets.test.output)
+
+  eclipse.classpath.file {
+    whenMerged { classpath ->
+      classpath.entries.removeAll { entry -> entry.path.contains('geode-modules/build')}
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/a6e9569f/extensions/geode-modules-tomcat8/src/main/java/com/gemstone/gemfire/modules/session/catalina/DeltaSession8.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-tomcat8/src/main/java/com/gemstone/gemfire/modules/session/catalina/DeltaSession8.java b/extensions/geode-modules-tomcat8/src/main/java/com/gemstone/gemfire/modules/session/catalina/DeltaSession8.java
new file mode 100644
index 0000000..aa07b5b
--- /dev/null
+++ b/extensions/geode-modules-tomcat8/src/main/java/com/gemstone/gemfire/modules/session/catalina/DeltaSession8.java
@@ -0,0 +1,595 @@
+/*
+* 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 com.gemstone.gemfire.modules.session.catalina;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.AccessController;
+import java.security.Principal;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import javax.servlet.http.HttpSession;
+
+import org.apache.catalina.Manager;
+import org.apache.catalina.realm.GenericPrincipal;
+import org.apache.catalina.security.SecurityUtil;
+import org.apache.catalina.session.StandardSession;
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+
+import com.gemstone.gemfire.DataSerializable;
+import com.gemstone.gemfire.DataSerializer;
+import com.gemstone.gemfire.Delta;
+import com.gemstone.gemfire.InvalidDeltaException;
+import com.gemstone.gemfire.cache.Region;
+import com.gemstone.gemfire.internal.cache.lru.Sizeable;
+import com.gemstone.gemfire.internal.util.BlobHelper;
+import com.gemstone.gemfire.modules.gatewaydelta.GatewayDelta;
+import com.gemstone.gemfire.modules.gatewaydelta.GatewayDeltaEvent;
+import com.gemstone.gemfire.modules.session.catalina.internal.DeltaSessionAttributeEvent;
+import com.gemstone.gemfire.modules.session.catalina.internal.DeltaSessionAttributeEventBatch;
+import com.gemstone.gemfire.modules.session.catalina.internal.DeltaSessionDestroyAttributeEvent;
+import com.gemstone.gemfire.modules.session.catalina.internal.DeltaSessionUpdateAttributeEvent;
+
+
+@SuppressWarnings("serial")
+public class DeltaSession8 extends StandardSession implements DataSerializable, Delta, GatewayDelta, Sizeable, DeltaSessionInterface {
+
+  private transient Region<String, HttpSession> operatingRegion;
+
+  private String sessionRegionName;
+
+  private String contextName;
+
+  private boolean hasDelta;
+
+  private boolean applyRemotely;
+
+  private boolean enableGatewayDeltaReplication;
+
+  private transient final Object changeLock = new Object();
+
+  private final List<DeltaSessionAttributeEvent> eventQueue = new ArrayList<DeltaSessionAttributeEvent>();
+
+  private transient GatewayDeltaEvent currentGatewayDeltaEvent;
+
+  private transient boolean expired = false;
+
+  private transient boolean preferDeserializedForm = true;
+
+  private byte[] serializedPrincipal;
+
+  private final Log LOG = LogFactory.getLog(DeltaSession.class.getName());
+  /**
+   * Construct a new <code>Session</code> associated with no <code>Manager</code>. The <code>Manager</code> will be
+   * assigned later using {@link #setOwner(Object)}.
+   */
+  public DeltaSession8() {
+    super(null);
+  }
+
+  /**
+   * Construct a new Session associated with the specified Manager.
+   *
+   * @param manager The manager with which this Session is associated
+   */
+  public DeltaSession8(Manager manager) {
+    super(manager);
+    setOwner(manager);
+  }
+
+  /**
+   * Return the <code>HttpSession</code> for which this object is the facade.
+   */
+  @SuppressWarnings("unchecked")
+  public HttpSession getSession() {
+    if (facade == null) {
+      if (SecurityUtil.isPackageProtectionEnabled()) {
+        final DeltaSession8 fsession = this;
+        facade = (DeltaSessionFacade) AccessController.doPrivileged(new PrivilegedAction() {
+          public Object run() {
+            return new DeltaSessionFacade(fsession);
+          }
+        });
+      } else {
+        facade = new DeltaSessionFacade(this);
+      }
+    }
+    return (facade);
+  }
+
+  public Principal getPrincipal() {
+    if (this.principal == null && this.serializedPrincipal != null) {
+
+      Principal sp = null;
+      try {
+        sp = (Principal)BlobHelper.deserializeBlob(this.serializedPrincipal);
+      } catch (Exception e) {
+        StringBuilder builder = new StringBuilder();
+        builder.append(this)
+               .append(
+                 ": Serialized principal contains a byte[] that cannot be deserialized due to the following exception");
+        ((DeltaSessionManager) getManager()).getLogger().warn(builder.toString(), e);
+        return null;
+      }
+      this.principal = sp;
+      if (getManager() != null) {
+        DeltaSessionManager mgr = (DeltaSessionManager) getManager();
+        if (mgr.getLogger().isDebugEnabled()) {
+          mgr.getLogger().debug(this + ": Deserialized principal: " + this.principal);
+        }
+      }
+    }
+    return this.principal;
+  }
+
+  public void setPrincipal(Principal principal) {
+    super.setPrincipal(principal);
+
+    // Put the session into the region to serialize the principal
+    if (getManager() != null) {
+      getManager().add(this);
+      DeltaSessionManager mgr = (DeltaSessionManager) getManager();
+      if (mgr.getLogger().isDebugEnabled()) {
+        mgr.getLogger().debug(this + ": Cached principal: " + principal);
+      }
+    }
+  }
+
+  private byte[] getSerializedPrincipal() {
+    if (this.serializedPrincipal == null) {
+      if (this.principal != null && this.principal instanceof GenericPrincipal) {
+        GenericPrincipal gp = (GenericPrincipal) this.principal;
+        this.serializedPrincipal = serialize(gp);
+        if (manager != null) {
+          DeltaSessionManager mgr = (DeltaSessionManager) getManager();
+          if (mgr.getLogger().isDebugEnabled()) {
+            mgr.getLogger().debug(this + ": Serialized principal: " + gp);
+          }
+        }
+      }
+    }
+    return this.serializedPrincipal;
+  }
+
+  protected Region<String, HttpSession> getOperatingRegion() {
+    // This region shouldn't be null when it is needed.
+    // It should have been set by the setOwner method.
+    return this.operatingRegion;
+  }
+
+  public boolean isCommitEnabled() {
+    DeltaSessionManager mgr = (DeltaSessionManager) getManager();
+    return mgr.isCommitValveEnabled();
+  }
+
+  public GatewayDeltaEvent getCurrentGatewayDeltaEvent() {
+    return this.currentGatewayDeltaEvent;
+  }
+
+  public void setCurrentGatewayDeltaEvent(GatewayDeltaEvent currentGatewayDeltaEvent) {
+    this.currentGatewayDeltaEvent = currentGatewayDeltaEvent;
+  }
+
+  @SuppressWarnings("unchecked")
+  public void setOwner(Object manager) {
+    if (manager instanceof DeltaSessionManager) {
+      DeltaSessionManager sessionManager = (DeltaSessionManager) manager;
+      this.manager = sessionManager;
+      initializeRegion(sessionManager);
+      this.hasDelta = false;
+      this.applyRemotely = false;
+      this.enableGatewayDeltaReplication = sessionManager.getEnableGatewayDeltaReplication();
+      this.preferDeserializedForm = sessionManager.getPreferDeserializedForm();
+
+      // Initialize transient variables
+      if (this.listeners == null) {
+        this.listeners = new ArrayList();
+      }
+
+      if (this.notes == null) {
+        this.notes = new Hashtable();
+      }
+
+      contextName = ((DeltaSessionManager) manager).getContextName();
+    } else {
+      throw new IllegalArgumentException(this + ": The Manager must be an AbstractManager");
+    }
+  }
+
+  private void checkBackingCacheAvailable() {
+    if (!((SessionManager) getManager()).isBackingCacheAvailable()) {
+      throw new IllegalStateException("No backing cache server is available.");
+    }
+  }
+
+  public void setAttribute(String name, Object value, boolean notify) {
+    checkBackingCacheAvailable();
+    synchronized (this.changeLock) {
+      // Serialize the value
+      byte[] serializedValue = serialize(value);
+
+      // Store the attribute locally
+      if (this.preferDeserializedForm) {
+        super.setAttribute(name, value, true);
+      } else {
+        super.setAttribute(name, serializedValue, true);
+      }
+
+      if (serializedValue == null) {
+        return;
+      }
+
+      // Create the update attribute message
+      DeltaSessionAttributeEvent event = new DeltaSessionUpdateAttributeEvent(name, serializedValue);
+      queueAttributeEvent(event, true);
+
+      // Distribute the update
+      if (!isCommitEnabled()) {
+        putInRegion(getOperatingRegion(), true, null);
+      }
+    }
+  }
+
+  public void removeAttribute(String name, boolean notify) {
+    checkBackingCacheAvailable();
+    synchronized (this.changeLock) {
+      // Remove the attribute locally
+      super.removeAttribute(name, true);
+
+      // Create the destroy attribute message
+      DeltaSessionAttributeEvent event = new DeltaSessionDestroyAttributeEvent(name);
+      queueAttributeEvent(event, true);
+
+      // Distribute the update
+      if (!isCommitEnabled()) {
+        putInRegion(getOperatingRegion(), true, null);
+      }
+    }
+  }
+
+  public Object getAttribute(String name) {
+    checkBackingCacheAvailable();
+    Object value = super.getAttribute(name);
+
+    // If the attribute is a byte[] (meaning it came from the server),
+    // deserialize it and add it to attributes map before returning it.
+    if (value instanceof byte[]) {
+      try {
+        value = BlobHelper.deserializeBlob((byte[]) value);
+      } catch (Exception e) {
+        StringBuilder builder = new StringBuilder();
+        builder.append(this)
+               .append(": Attribute named ")
+               .append(name)
+               .append(" contains a byte[] that cannot be deserialized due to the following exception");
+        ((DeltaSessionManager) getManager()).getLogger().warn(builder.toString(), e);
+      }
+      if (this.preferDeserializedForm) {
+        localUpdateAttribute(name, value);
+      }
+    }
+
+    // Touch the session region if necessary. This is an asynchronous operation
+    // that prevents the session region from prematurely expiring a session that
+    // is only getting attributes.
+    ((DeltaSessionManager) getManager()).addSessionToTouch(getId());
+
+    return value;
+  }
+
+  public void invalidate() {
+    super.invalidate();
+    //getOperatingRegion().destroy(this.id, true); // already done in super (remove)
+    ((DeltaSessionManager) getManager()).getStatistics().incSessionsInvalidated();
+  }
+
+  public void processExpired() {
+    if (((DeltaSessionManager) getManager()).getLogger().isDebugEnabled()) {
+      ((DeltaSessionManager) getManager()).getLogger().debug(this + ": Expired");
+    }
+    // Set expired (so region.destroy is not called again)
+    setExpired(true);
+
+    // Do expire processing
+    expire();
+
+    // Update statistics
+    DeltaSessionManager manager = (DeltaSessionManager) getManager();
+    if (manager != null) {
+      manager.getStatistics().incSessionsExpired();
+    }
+  }
+
+  public void setMaxInactiveInterval(int interval) {
+    super.setMaxInactiveInterval(interval);
+  }
+
+  public void localUpdateAttribute(String name, Object value) {
+    super.setAttribute(name, value, false); // don't do notification since this is a replication
+  }
+
+  public void localDestroyAttribute(String name) {
+    super.removeAttribute(name, false); // don't do notification since this is a replication
+  }
+
+  public void applyAttributeEvents(Region<String, DeltaSessionInterface> region, List<DeltaSessionAttributeEvent> events) {
+    for (DeltaSessionAttributeEvent event : events) {
+      event.apply(this);
+      queueAttributeEvent(event, false);
+    }
+
+    putInRegion(region, false, true);
+  }
+
+  private void initializeRegion(DeltaSessionManager sessionManager) {
+    // Get the session region name
+    this.sessionRegionName = sessionManager.getRegionName();
+
+    // Get the operating region.
+    // If a P2P manager is used, then this will be a local region fronting the
+    // session region if local cache is enabled; otherwise, it will be the
+    // session region itself.
+    // If a CS manager is used, it will be the session proxy region.
+    this.operatingRegion = sessionManager.getSessionCache().getOperatingRegion();
+    if (sessionManager.getLogger().isDebugEnabled()) {
+      sessionManager.getLogger().debug(this + ": Set operating region: " + this.operatingRegion);
+    }
+  }
+
+  private void queueAttributeEvent(DeltaSessionAttributeEvent event, boolean checkAddToCurrentGatewayDelta) {
+    // Add to current gateway delta if necessary
+    if (checkAddToCurrentGatewayDelta) {
+      // If the manager has enabled gateway delta replication and is a P2P
+      // manager, the GatewayDeltaForwardCacheListener will be invoked in this
+      // VM. Add the event to the currentDelta.
+      DeltaSessionManager mgr = (DeltaSessionManager) this.manager;
+      if (this.enableGatewayDeltaReplication && mgr.isPeerToPeer()) {
+        // If commit is not enabled, add the event to the current batch; else,
+        // the current batch will be initialized to the events in the queue will
+        // be added at commit time.
+        if (!isCommitEnabled()) {
+          List<DeltaSessionAttributeEvent> events = new ArrayList<DeltaSessionAttributeEvent>();
+          events.add(event);
+          this.currentGatewayDeltaEvent = new DeltaSessionAttributeEventBatch(this.sessionRegionName, this.id, events);
+        }
+      }
+    }
+    this.eventQueue.add(event);
+  }
+
+  @SuppressWarnings("unchecked")
+  private void putInRegion(Region region, boolean applyRemotely, Object callbackArgument) {
+    this.hasDelta = true;
+    this.applyRemotely = applyRemotely;
+    region.put(this.id, this, callbackArgument);
+    this.eventQueue.clear();
+  }
+
+  public void commit() {
+    if (!isValidInternal()) throw new IllegalStateException("commit: Session " + getId() +
+                                                            " already invalidated");
+    //          (STRING_MANAGER.getString("deltaSession.commit.ise", getId()));
+
+    synchronized (this.changeLock) {
+      // Jens - there used to be a check to only perform this if the queue is
+      // empty, but we want this to always run so that the lastAccessedTime
+      // will be updated even when no attributes have been changed.
+      DeltaSessionManager mgr = (DeltaSessionManager) this.manager;
+      if (this.enableGatewayDeltaReplication && mgr.isPeerToPeer()) {
+        setCurrentGatewayDeltaEvent(
+          new DeltaSessionAttributeEventBatch(this.sessionRegionName, this.id, this.eventQueue));
+      }
+      this.hasDelta = true;
+      this.applyRemotely = true;
+      putInRegion(getOperatingRegion(), true, null);
+      this.eventQueue.clear();
+    }
+  }
+
+  public void abort() {
+    synchronized (this.changeLock) {
+      this.eventQueue.clear();
+    }
+  }
+
+  private void setExpired(boolean expired) {
+    this.expired = expired;
+  }
+
+  public boolean getExpired() {
+    return this.expired;
+  }
+
+  public String getContextName() {
+    return contextName;
+  }
+
+  public boolean hasDelta() {
+    return this.hasDelta;
+  }
+
+  public void toDelta(DataOutput out) throws IOException {
+    // Write whether to apply the changes to another DS if necessary
+    out.writeBoolean(this.applyRemotely);
+
+    // Write the events
+    DataSerializer.writeArrayList((ArrayList) this.eventQueue, out);
+
+    out.writeLong(this.lastAccessedTime);
+    out.writeInt(this.maxInactiveInterval);
+  }
+
+  public void fromDelta(DataInput in) throws IOException, InvalidDeltaException {
+    // Read whether to apply the changes to another DS if necessary
+    this.applyRemotely = in.readBoolean();
+
+    // Read the events
+    List<DeltaSessionAttributeEvent> events = null;
+    try {
+      events = DataSerializer.readArrayList(in);
+    } catch (ClassNotFoundException e) {
+      throw new InvalidDeltaException(e);
+    }
+
+    // This allows for backwards compatibility with 2.1 clients
+    if (((InputStream) in).available() > 0) {
+      this.lastAccessedTime = in.readLong();
+      this.maxInactiveInterval = in.readInt();
+    }
+
+    // Iterate and apply the events
+    for (DeltaSessionAttributeEvent event : events) {
+      event.apply(this);
+    }
+
+    // Add the events to the gateway delta region if necessary
+    if (this.enableGatewayDeltaReplication && this.applyRemotely) {
+      setCurrentGatewayDeltaEvent(new DeltaSessionAttributeEventBatch(this.sessionRegionName, this.id, events));
+    }
+
+    // Access it to set the last accessed time. End access it to set not new.
+    access();
+    endAccess();
+  }
+
+  @Override
+  public void toData(DataOutput out) throws IOException {
+    // Write the StandardSession state
+    DataSerializer.writeString(this.id, out);
+    out.writeLong(this.creationTime);
+    out.writeLong(this.lastAccessedTime);
+    out.writeLong(this.thisAccessedTime);
+    out.writeInt(this.maxInactiveInterval);
+    out.writeBoolean(this.isNew);
+    out.writeBoolean(this.isValid);
+    DataSerializer.writeObject(getSerializedAttributes(), out);
+    DataSerializer.writeByteArray(getSerializedPrincipal(), out);
+
+    // Write the DeltaSession state
+    out.writeBoolean(this.enableGatewayDeltaReplication);
+    DataSerializer.writeString(this.sessionRegionName, out);
+
+    DataSerializer.writeString(this.contextName, out);
+  }
+
+  @Override
+  @SuppressWarnings("unchecked")
+  public void fromData(DataInput in) throws IOException, ClassNotFoundException {
+    // Read the StandardSession state
+    this.id = DataSerializer.readString(in);
+    this.creationTime = in.readLong();
+    this.lastAccessedTime = in.readLong();
+    this.thisAccessedTime = in.readLong();
+    this.maxInactiveInterval = in.readInt();
+    this.isNew = in.readBoolean();
+    this.isValid = in.readBoolean();
+    this.attributes = readInAttributes(in);
+    this.serializedPrincipal = DataSerializer.readByteArray(in);
+
+    // Read the DeltaSession state
+    this.enableGatewayDeltaReplication = in.readBoolean();
+    this.sessionRegionName = DataSerializer.readString(in);
+
+    // This allows for backwards compatibility with 2.1 clients
+    if (((InputStream) in).available() > 0) {
+      this.contextName = DataSerializer.readString(in);
+    }
+
+    // Initialize the transients if necessary
+    if (this.listeners == null) {
+      this.listeners = new ArrayList();
+    }
+
+    if (this.notes == null) {
+      this.notes = new Hashtable();
+    }
+  }
+
+  @Override
+  public int getSizeInBytes() {
+    int size = 0;
+    for (Enumeration<String> e = getAttributeNames(); e.hasMoreElements(); ) {
+      // Don't use this.getAttribute() because we don't want to deserialize
+      // the value.
+      Object value = super.getAttribute(e.nextElement());
+      if (value instanceof byte[]) {
+        size += ((byte[]) value).length;
+      }
+    }
+
+    return size;
+  }
+
+  protected byte[] serialize(Object obj) {
+    byte[] serializedValue = null;
+    try {
+      serializedValue = BlobHelper.serializeToBlob(obj);
+    } catch (IOException e) {
+      StringBuilder builder = new StringBuilder();
+      builder.append(this)
+             .append(": Object ")
+             .append(obj)
+             .append(" cannot be serialized due to the following exception");
+      ((DeltaSessionManager) getManager()).getLogger().warn(builder.toString(), e);
+    }
+    return serializedValue;
+  }
+
+  @Override
+  public String toString() {
+    return new StringBuilder().append("DeltaSession[")
+                              .append("id=")
+                              .append(getId())
+                              .append("; context=")
+                              .append(this.contextName)
+                              .append("; sessionRegionName=")
+                              .append(this.sessionRegionName)
+                              .append("; operatingRegionName=")
+                              .append(getOperatingRegion() == null ? "unset" : getOperatingRegion().getFullPath())
+                              .append("]")
+                              .toString();
+  }
+
+  @SuppressWarnings({"unchecked", "rawtypes"})
+  protected ConcurrentMap<String, byte[]> getSerializedAttributes() {
+    // Iterate the values and serialize them if necessary before sending them to the server. This makes the application classes unnecessary on the server.
+    ConcurrentMap<String, byte[]> serializedAttributes = new ConcurrentHashMap<String, byte[]>();
+    for (Iterator i = this.attributes.entrySet().iterator(); i.hasNext(); ) {
+      Map.Entry<String, Object> entry = (Map.Entry<String, Object>) i.next();
+      Object value = entry.getValue();
+      byte[] serializedValue = value instanceof byte[] ? (byte[]) value : serialize(value);
+      serializedAttributes.put(entry.getKey(), serializedValue);
+    }
+    return serializedAttributes;
+  }
+
+  protected ConcurrentMap readInAttributes(final DataInput in) throws IOException, ClassNotFoundException {
+    return DataSerializer.readObject(in);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/a6e9569f/extensions/geode-modules-tomcat8/src/main/java/com/gemstone/gemfire/modules/session/catalina/Tomcat8DeltaSessionManager.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-tomcat8/src/main/java/com/gemstone/gemfire/modules/session/catalina/Tomcat8DeltaSessionManager.java b/extensions/geode-modules-tomcat8/src/main/java/com/gemstone/gemfire/modules/session/catalina/Tomcat8DeltaSessionManager.java
new file mode 100644
index 0000000..25bb847
--- /dev/null
+++ b/extensions/geode-modules-tomcat8/src/main/java/com/gemstone/gemfire/modules/session/catalina/Tomcat8DeltaSessionManager.java
@@ -0,0 +1,140 @@
+/*
+* 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 com.gemstone.gemfire.modules.session.catalina;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.LifecycleException;
+import org.apache.catalina.LifecycleState;
+import org.apache.catalina.Pipeline;
+import org.apache.catalina.session.StandardSession;
+
+import java.io.IOException;
+
+public class Tomcat8DeltaSessionManager extends DeltaSessionManager {
+
+  /**
+   * Prepare for the beginning of active use of the public methods of this component.  This method should be called
+   * after <code>configure()</code>, and before any of the public methods of the component are utilized.
+   *
+   * @throws LifecycleException if this component detects a fatal error that prevents this component from being used
+   */
+  @Override
+  public void startInternal() throws LifecycleException {
+    super.startInternal();
+    if (getLogger().isDebugEnabled()) {
+      getLogger().debug(this + ": Starting");
+    }
+    if (this.started.get()) {
+      return;
+    }
+
+    fireLifecycleEvent(START_EVENT, null);
+
+    // Register our various valves
+    registerJvmRouteBinderValve();
+
+    if (isCommitValveEnabled()) {
+      registerCommitSessionValve();
+    }
+
+    // Initialize the appropriate session cache interface
+    initializeSessionCache();
+
+    try {
+      load();
+    } catch (ClassNotFoundException e) {
+      throw new LifecycleException("Exception starting manager", e);
+    } catch (IOException e) {
+      throw new LifecycleException("Exception starting manager", e);
+    }
+
+    // Create the timer and schedule tasks
+    scheduleTimerTasks();
+
+    this.started.set(true);
+    this.setState(LifecycleState.STARTING);
+  }
+
+  /**
+   * Gracefully terminate the active use of the public methods of this component.  This method should be the last one
+   * called on a given instance of this component.
+   *
+   * @throws LifecycleException if this component detects a fatal error that needs to be reported
+   */
+  @Override
+  public void stopInternal() throws LifecycleException {
+    super.stopInternal();
+    if (getLogger().isDebugEnabled()) {
+      getLogger().debug(this + ": Stopping");
+    }
+
+    try {
+      unload();
+    } catch (IOException e) {
+      getLogger().error("Unable to unload sessions", e);
+    }
+
+    this.started.set(false);
+    fireLifecycleEvent(STOP_EVENT, null);
+
+    // StandardManager expires all Sessions here.
+    // All Sessions are not known by this Manager.
+
+    super.destroyInternal();
+
+    // Clear any sessions to be touched
+    getSessionsToTouch().clear();
+
+    // Cancel the timer
+    cancelTimer();
+
+    // Unregister the JVM route valve
+    unregisterJvmRouteBinderValve();
+
+    if (isCommitValveEnabled()) {
+      unregisterCommitSessionValve();
+    }
+
+    this.setState(LifecycleState.STOPPING);
+
+  }
+
+  @Override
+  public int getMaxInactiveInterval() {
+    return getContext().getSessionTimeout();
+  }
+
+  @Override
+  protected Pipeline getPipeline() {
+    return getTheContext().getPipeline();
+  }
+
+  @Override
+  public Context getTheContext() {
+    return getContext();
+  }
+
+  @Override
+  public void setMaxInactiveInterval(final int interval) {
+    getContext().setSessionTimeout(interval);
+  }
+
+  @Override
+  protected StandardSession getNewSession() {
+    return new DeltaSession8(this);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/a6e9569f/extensions/geode-modules-tomcat8/src/test/java/com/gemstone/gemfire/modules/session/EmbeddedTomcat8.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-tomcat8/src/test/java/com/gemstone/gemfire/modules/session/EmbeddedTomcat8.java b/extensions/geode-modules-tomcat8/src/test/java/com/gemstone/gemfire/modules/session/EmbeddedTomcat8.java
new file mode 100644
index 0000000..3b67c29
--- /dev/null
+++ b/extensions/geode-modules-tomcat8/src/test/java/com/gemstone/gemfire/modules/session/EmbeddedTomcat8.java
@@ -0,0 +1,193 @@
+/*
+* 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 com.gemstone.gemfire.modules.session;
+
+import java.io.File;
+import java.net.MalformedURLException;
+
+import javax.security.auth.message.config.AuthConfigFactory;
+import javax.servlet.ServletException;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.Engine;
+import org.apache.catalina.Host;
+import org.apache.catalina.LifecycleException;
+import org.apache.catalina.LifecycleListener;
+import org.apache.catalina.Valve;
+import org.apache.catalina.authenticator.jaspic.AuthConfigFactoryImpl;
+import org.apache.catalina.authenticator.jaspic.SimpleAuthConfigProvider;
+import org.apache.catalina.connector.Connector;
+import org.apache.catalina.core.StandardEngine;
+import org.apache.catalina.core.StandardHost;
+import org.apache.catalina.core.StandardService;
+import org.apache.catalina.core.StandardWrapper;
+import org.apache.catalina.loader.WebappLoader;
+import org.apache.catalina.startup.Tomcat;
+import org.apache.catalina.valves.ValveBase;
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+
+import com.gemstone.gemfire.modules.session.catalina.JvmRouteBinderValve;
+
+/**
+ *
+ */
+public class EmbeddedTomcat8 {
+
+  private String contextPath = null;
+  private Tomcat container = null;
+  private Log logger = LogFactory.getLog(getClass());
+
+  /**
+   * The directory to create the Tomcat server configuration under.
+   */
+  private String catalinaHome = "doh";
+
+  /**
+   * The port to run the Tomcat server on.
+   */
+  private int port = 8089;
+
+  /**
+   * The classes directory for the web application being run.
+   */
+  private String classesDir = "target/classes";
+
+  private Context rootContext = null;
+
+  private Engine engine;
+
+  /**
+   * The web resources directory for the web application being run.
+   */
+  private String webappDir = "";
+
+  public EmbeddedTomcat8(String contextPath, int port, String jvmRoute) throws MalformedURLException {
+    this.contextPath = contextPath;
+    this.port = port;
+
+    // create server
+    container = new Tomcat();
+    container.setBaseDir(System.getProperty("user.dir") + "/tomcat");
+
+    Host localHost = container.getHost();//("127.0.0.1", new File("").getAbsolutePath());
+    localHost.setDeployOnStartup(true);
+    localHost.getCreateDirs();
+
+    try {
+      new File(localHost.getAppBaseFile().getAbsolutePath()).mkdir();
+      rootContext = container.addContext("", localHost.getAppBaseFile().getAbsolutePath());
+    }
+    catch (Exception e) {
+      throw new Error(e);
+    }
+    // Otherwise we get NPE when instantiating servlets
+    rootContext.setIgnoreAnnotations(true);
+
+
+    AuthConfigFactory factory = new AuthConfigFactoryImpl();
+    new SimpleAuthConfigProvider(null, factory);
+    AuthConfigFactory.setFactory(factory);
+
+    // create engine
+    engine = container.getEngine();
+    engine.setName("localEngine");
+    engine.setJvmRoute(jvmRoute);
+
+    // create http connector
+    container.setPort(port);
+    Connector httpConnector = container.getConnector();//((InetAddress) null, port, false);
+
+    // Create the JVMRoute valve for session failover
+    ValveBase valve = new JvmRouteBinderValve();
+    ((StandardEngine) engine).addValve(valve);
+  }
+
+  /**
+   * Starts the embedded Tomcat server.
+   */
+  public void startContainer() throws LifecycleException {
+    // start server
+    container.start();
+
+    // add shutdown hook to stop server
+    Runtime.getRuntime().addShutdownHook(new Thread() {
+      @Override
+      public void run() {
+        stopContainer();
+      }
+    });
+  }
+
+  /**
+   * Stops the embedded Tomcat server.
+   */
+  public void stopContainer() {
+    try {
+      if (container != null) {
+        container.stop();
+        logger.info("Stopped container");
+      }
+    } catch (LifecycleException exception) {
+      logger.warn("Cannot Stop Tomcat" + exception.getMessage());
+    }
+  }
+
+  public StandardWrapper addServlet(String path, String name, String clazz) throws ServletException {
+    StandardWrapper servlet = (StandardWrapper) rootContext.createWrapper();
+    servlet.setName(name);
+    servlet.setServletClass(clazz);
+    servlet.setLoadOnStartup(1);
+
+    rootContext.addChild(servlet);
+    rootContext.addServletMapping(path, name);
+
+    servlet.setParent(rootContext);
+//        servlet.load();
+
+    return servlet;
+  }
+
+  public Tomcat getEmbedded() {
+    return container;
+  }
+
+  public void addLifecycleListener(LifecycleListener lifecycleListener) {
+    container.getServer().addLifecycleListener(lifecycleListener);
+  }
+
+  public Context getRootContext() {
+    return rootContext;
+  }
+
+  public String getPath() {
+    return contextPath;
+  }
+
+  public void setPath(String path) {
+    this.contextPath = path;
+  }
+
+  public int getPort() {
+    return port;
+  }
+
+  public void addValve(Valve valve) {
+    ((StandardEngine) engine).addValve(valve);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/a6e9569f/extensions/geode-modules-tomcat8/src/test/java/com/gemstone/gemfire/modules/session/TestSessionsTomcat8Base.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-tomcat8/src/test/java/com/gemstone/gemfire/modules/session/TestSessionsTomcat8Base.java b/extensions/geode-modules-tomcat8/src/test/java/com/gemstone/gemfire/modules/session/TestSessionsTomcat8Base.java
new file mode 100644
index 0000000..76b301d
--- /dev/null
+++ b/extensions/geode-modules-tomcat8/src/test/java/com/gemstone/gemfire/modules/session/TestSessionsTomcat8Base.java
@@ -0,0 +1,464 @@
+/*
+* 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 com.gemstone.gemfire.modules.session;
+
+import static com.gemstone.gemfire.distributed.ConfigurationProperties.*;
+import static org.junit.Assert.*;
+
+import java.beans.PropertyChangeEvent;
+import java.io.IOException;
+import java.io.PrintWriter;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import com.meterware.httpunit.GetMethodWebRequest;
+import com.meterware.httpunit.WebConversation;
+import com.meterware.httpunit.WebRequest;
+import com.meterware.httpunit.WebResponse;
+import org.apache.catalina.core.StandardWrapper;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.gemstone.gemfire.cache.Region;
+import com.gemstone.gemfire.internal.AvailablePortHelper;
+import com.gemstone.gemfire.modules.session.catalina.ClientServerCacheLifecycleListener;
+import com.gemstone.gemfire.modules.session.catalina.DeltaSessionManager;
+import com.gemstone.gemfire.modules.session.catalina.PeerToPeerCacheLifecycleListener;
+
+public abstract class TestSessionsTomcat8Base {
+
+  private static EmbeddedTomcat8 server;
+
+  private static Region<String, HttpSession> region;
+
+  private static StandardWrapper servlet;
+
+  private static DeltaSessionManager sessionManager;
+
+  private static int port;
+
+  // Set up the servers we need
+  public static void setupServer(DeltaSessionManager manager) throws Exception {
+    port = AvailablePortHelper.getRandomAvailableTCPPort();
+    server = new EmbeddedTomcat8("/test", port, "JVM-1");
+
+    PeerToPeerCacheLifecycleListener p2pListener = new PeerToPeerCacheLifecycleListener();
+    p2pListener.setProperty(MCAST_PORT, "0");
+    p2pListener.setProperty(LOG_LEVEL, "config");
+    server.addLifecycleListener(p2pListener);
+    sessionManager = manager;
+    sessionManager.setEnableCommitValve(true);
+    server.getRootContext().setManager(sessionManager);
+
+    servlet = server.addServlet("/test/*", "default", CommandServlet.class.getName());
+    server.startContainer();
+
+    /*
+     * Can only retrieve the region once the container has started up
+     * (and the cache has started too).
+     */
+    region = sessionManager.getSessionCache().getSessionRegion();
+  }
+
+  @AfterClass
+  public static void teardownClass() throws Exception {
+    server.stopContainer();
+  }
+
+  /**
+   * Reset some data
+   */
+  @Before
+  public void setup() throws Exception {
+    sessionManager.getTheContext().setSessionTimeout(30);
+    region.clear();
+  }
+
+  /**
+   * Check that the basics are working
+   */
+  @Test
+  public void testSanity() throws Exception {
+    WebConversation wc = new WebConversation();
+    WebRequest req = new GetMethodWebRequest(String.format("http://localhost:%d/test", port));
+    req.setParameter("cmd", QueryCommand.GET.name());
+    req.setParameter("param", "null");
+    WebResponse response = wc.getResponse(req);
+
+    assertEquals("JSESSIONID", response.getNewCookieNames()[0]);
+  }
+
+  /**
+   * Test callback functionality. This is here really just as an example. Callbacks are useful to implement per test
+   * actions which can be defined within the actual test method instead of in a separate servlet class.
+   */
+  @Test
+  public void testCallback() throws Exception {
+    final String helloWorld = "Hello World";
+    Callback c = new Callback() {
+
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response) throws IOException {
+        PrintWriter out = response.getWriter();
+        out.write(helloWorld);
+      }
+    };
+    servlet.getServletContext().setAttribute("callback", c);
+
+    WebConversation wc = new WebConversation();
+    WebRequest req = new GetMethodWebRequest(String.format("http://localhost:%d/test", port));
+
+    req.setParameter("cmd", QueryCommand.CALLBACK.name());
+    req.setParameter("param", "callback");
+    WebResponse response = wc.getResponse(req);
+
+    assertEquals(helloWorld, response.getText());
+  }
+
+  /**
+   * Test that calling session.isNew() works for the initial as well as subsequent requests.
+   */
+  @Test
+  public void testIsNew() throws Exception {
+    Callback c = new Callback() {
+
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response) throws IOException {
+        HttpSession session = request.getSession();
+        response.getWriter().write(Boolean.toString(session.isNew()));
+      }
+    };
+    servlet.getServletContext().setAttribute("callback", c);
+
+    WebConversation wc = new WebConversation();
+    WebRequest req = new GetMethodWebRequest(String.format("http://localhost:%d/test", port));
+
+    req.setParameter("cmd", QueryCommand.CALLBACK.name());
+    req.setParameter("param", "callback");
+    WebResponse response = wc.getResponse(req);
+
+    assertEquals("true", response.getText());
+    response = wc.getResponse(req);
+
+    assertEquals("false", response.getText());
+  }
+
+  /**
+   * Check that our session persists. The values we pass in as query params are used to set attributes on the session.
+   */
+  @Test
+  public void testSessionPersists1() throws Exception {
+    String key = "value_testSessionPersists1";
+    String value = "Foo";
+
+    WebConversation wc = new WebConversation();
+    WebRequest req = new GetMethodWebRequest(String.format("http://localhost:%d/test", port));
+    req.setParameter("cmd", QueryCommand.SET.name());
+    req.setParameter("param", key);
+    req.setParameter("value", value);
+    WebResponse response = wc.getResponse(req);
+    String sessionId = response.getNewCookieValue("JSESSIONID");
+
+    assertNotNull("No apparent session cookie", sessionId);
+
+    // The request retains the cookie from the prior response...
+    req.setParameter("cmd", QueryCommand.GET.name());
+    req.setParameter("param", key);
+    req.removeParameter("value");
+    response = wc.getResponse(req);
+
+    assertEquals(value, response.getText());
+  }
+
+  /**
+   * Test that invalidating a session makes it's attributes inaccessible.
+   */
+  @Test
+  public void testInvalidate() throws Exception {
+    String key = "value_testInvalidate";
+    String value = "Foo";
+
+    WebConversation wc = new WebConversation();
+    WebRequest req = new GetMethodWebRequest(String.format("http://localhost:%d/test", port));
+
+    // Set an attribute
+    req.setParameter("cmd", QueryCommand.SET.name());
+    req.setParameter("param", key);
+    req.setParameter("value", value);
+    WebResponse response = wc.getResponse(req);
+
+    // Invalidate the session
+    req.removeParameter("param");
+    req.removeParameter("value");
+    req.setParameter("cmd", QueryCommand.INVALIDATE.name());
+    wc.getResponse(req);
+
+    // The attribute should not be accessible now...
+    req.setParameter("cmd", QueryCommand.GET.name());
+    req.setParameter("param", key);
+    response = wc.getResponse(req);
+
+    assertEquals("", response.getText());
+  }
+
+  /**
+   * Test setting the session expiration
+   */
+  @Test
+  public void testSessionExpiration1() throws Exception {
+    // TestSessions only live for a second
+    sessionManager.setMaxInactiveInterval(1);
+
+    String key = "value_testSessionExpiration1";
+    String value = "Foo";
+
+    WebConversation wc = new WebConversation();
+    WebRequest req = new GetMethodWebRequest(String.format("http://localhost:%d/test", port));
+
+    // Set an attribute
+    req.setParameter("cmd", QueryCommand.SET.name());
+    req.setParameter("param", key);
+    req.setParameter("value", value);
+    WebResponse response = wc.getResponse(req);
+
+    // Sleep a while
+    Thread.sleep(65000);
+
+    // The attribute should not be accessible now...
+    req.setParameter("cmd", QueryCommand.GET.name());
+    req.setParameter("param", key);
+    response = wc.getResponse(req);
+
+    assertEquals("", response.getText());
+  }
+
+  /**
+   * Test setting the session expiration via a property change as would happen under normal deployment conditions.
+   */
+  @Test
+  public void testSessionExpiration2() throws Exception {
+    // TestSessions only live for a minute
+    sessionManager.propertyChange(
+      new PropertyChangeEvent(server.getRootContext(), "sessionTimeout", new Integer(30), new Integer(1)));
+
+    // Check that the value has been set to 60 seconds
+    assertEquals(60, sessionManager.getMaxInactiveInterval());
+  }
+
+  /**
+   * Test that removing a session attribute also removes it from the region
+   */
+  @Test
+  public void testRemoveAttribute() throws Exception {
+    String key = "value_testRemoveAttribute";
+    String value = "Foo";
+
+    WebConversation wc = new WebConversation();
+    WebRequest req = new GetMethodWebRequest(String.format("http://localhost:%d/test", port));
+
+    // Set an attribute
+    req.setParameter("cmd", QueryCommand.SET.name());
+    req.setParameter("param", key);
+    req.setParameter("value", value);
+    WebResponse response = wc.getResponse(req);
+    String sessionId = response.getNewCookieValue("JSESSIONID");
+
+    // Implicitly remove the attribute
+    req.removeParameter("value");
+    wc.getResponse(req);
+
+    // The attribute should not be accessible now...
+    req.setParameter("cmd", QueryCommand.GET.name());
+    req.setParameter("param", key);
+    response = wc.getResponse(req);
+
+    assertEquals("", response.getText());
+    assertNull(region.get(sessionId).getAttribute(key));
+  }
+
+  /**
+   * Test that a session attribute gets set into the region too.
+   */
+  @Test
+  public void testBasicRegion() throws Exception {
+    String key = "value_testBasicRegion";
+    String value = "Foo";
+
+    WebConversation wc = new WebConversation();
+    WebRequest req = new GetMethodWebRequest(String.format("http://localhost:%d/test", port));
+
+    // Set an attribute
+    req.setParameter("cmd", QueryCommand.SET.name());
+    req.setParameter("param", key);
+    req.setParameter("value", value);
+    WebResponse response = wc.getResponse(req);
+    String sessionId = response.getNewCookieValue("JSESSIONID");
+
+    assertEquals(value, region.get(sessionId).getAttribute(key));
+  }
+
+  /**
+   * Test that a session attribute gets removed from the region when the session is invalidated.
+   */
+  @Test
+  public void testRegionInvalidate() throws Exception {
+    String key = "value_testRegionInvalidate";
+    String value = "Foo";
+
+    WebConversation wc = new WebConversation();
+    WebRequest req = new GetMethodWebRequest(String.format("http://localhost:%d/test", port));
+
+    // Set an attribute
+    req.setParameter("cmd", QueryCommand.SET.name());
+    req.setParameter("param", key);
+    req.setParameter("value", value);
+    WebResponse response = wc.getResponse(req);
+    String sessionId = response.getNewCookieValue("JSESSIONID");
+
+    // Invalidate the session
+    req.removeParameter("param");
+    req.removeParameter("value");
+    req.setParameter("cmd", QueryCommand.INVALIDATE.name());
+    wc.getResponse(req);
+
+    assertNull("The region should not have an entry for this session", region.get(sessionId));
+  }
+
+  /**
+   * Test that multiple attribute updates, within the same request result in only the latest one being effective.
+   */
+  @Test
+  public void testMultipleAttributeUpdates() throws Exception {
+    final String key = "value_testMultipleAttributeUpdates";
+    Callback c = new Callback() {
+
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response) throws IOException {
+        HttpSession session = request.getSession();
+        for (int i = 0; i < 1000; i++) {
+          session.setAttribute(key, Integer.toString(i));
+        }
+      }
+    };
+    servlet.getServletContext().setAttribute("callback", c);
+
+    WebConversation wc = new WebConversation();
+    WebRequest req = new GetMethodWebRequest(String.format("http://localhost:%d/test", port));
+
+    // Execute the callback
+    req.setParameter("cmd", QueryCommand.CALLBACK.name());
+    req.setParameter("param", "callback");
+    WebResponse response = wc.getResponse(req);
+
+    String sessionId = response.getNewCookieValue("JSESSIONID");
+
+    assertEquals("999", region.get(sessionId).getAttribute(key));
+  }
+
+  /*
+   * Test for issue #38 CommitSessionValve throws exception on invalidated sessions
+   */
+  @Test
+  public void testCommitSessionValveInvalidSession() throws Exception {
+    Callback c = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response) throws IOException {
+        HttpSession session = request.getSession();
+        session.invalidate();
+        response.getWriter().write("done");
+      }
+    };
+    servlet.getServletContext().setAttribute("callback", c);
+
+    WebConversation wc = new WebConversation();
+    WebRequest req = new GetMethodWebRequest(String.format("http://localhost:%d/test", port));
+
+    // Execute the callback
+    req.setParameter("cmd", QueryCommand.CALLBACK.name());
+    req.setParameter("param", "callback");
+    WebResponse response = wc.getResponse(req);
+
+    assertEquals("done", response.getText());
+  }
+
+  /**
+   * Test for issue #45 Sessions are being created for every request
+   */
+  @Test
+  public void testExtraSessionsNotCreated() throws Exception {
+    Callback c = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response) throws IOException {
+        // Do nothing with sessions
+        response.getWriter().write("done");
+      }
+    };
+    servlet.getServletContext().setAttribute("callback", c);
+
+    WebConversation wc = new WebConversation();
+    WebRequest req = new GetMethodWebRequest(String.format("http://localhost:%d/test", port));
+
+    // Execute the callback
+    req.setParameter("cmd", QueryCommand.CALLBACK.name());
+    req.setParameter("param", "callback");
+    WebResponse response = wc.getResponse(req);
+
+    assertEquals("done", response.getText());
+    assertEquals("The region should be empty", 0, region.size());
+  }
+
+  /**
+   * Test for issue #46 lastAccessedTime is not updated at the start of the request, but only at the end.
+   */
+  @Test
+  public void testLastAccessedTime() throws Exception {
+    Callback c = new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response) throws IOException {
+        HttpSession session = request.getSession();
+        // Hack to expose the session to our test context
+        session.getServletContext().setAttribute("session", session);
+        session.setAttribute("lastAccessTime", session.getLastAccessedTime());
+        try {
+          Thread.sleep(100);
+        } catch (InterruptedException ex) {
+        }
+        session.setAttribute("somethingElse", 1);
+        request.getSession();
+        response.getWriter().write("done");
+      }
+    };
+    servlet.getServletContext().setAttribute("callback", c);
+
+    WebConversation wc = new WebConversation();
+    WebRequest req = new GetMethodWebRequest(String.format("http://localhost:%d/test", port));
+
+    // Execute the callback
+    req.setParameter("cmd", QueryCommand.CALLBACK.name());
+    req.setParameter("param", "callback");
+    WebResponse response = wc.getResponse(req);
+
+    HttpSession session = (HttpSession) servlet.getServletContext().getAttribute("session");
+    Long lastAccess = (Long) session.getAttribute("lastAccessTime");
+
+    assertTrue(
+      "Last access time not set correctly: " + lastAccess.longValue() + " not <= " + session.getLastAccessedTime(),
+      lastAccess.longValue() <= session.getLastAccessedTime());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/a6e9569f/extensions/geode-modules-tomcat8/src/test/java/com/gemstone/gemfire/modules/session/Tomcat8SessionsJUnitTest.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-tomcat8/src/test/java/com/gemstone/gemfire/modules/session/Tomcat8SessionsJUnitTest.java b/extensions/geode-modules-tomcat8/src/test/java/com/gemstone/gemfire/modules/session/Tomcat8SessionsJUnitTest.java
new file mode 100644
index 0000000..df65690
--- /dev/null
+++ b/extensions/geode-modules-tomcat8/src/test/java/com/gemstone/gemfire/modules/session/Tomcat8SessionsJUnitTest.java
@@ -0,0 +1,32 @@
+/*
+* 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 com.gemstone.gemfire.modules.session;
+
+import com.gemstone.gemfire.modules.session.catalina.Tomcat8DeltaSessionManager;
+import com.gemstone.gemfire.test.junit.categories.UnitTest;
+import org.junit.BeforeClass;
+import org.junit.experimental.categories.Category;
+
+@Category(UnitTest.class)
+public class Tomcat8SessionsJUnitTest extends TestSessionsTomcat8Base {
+
+  // Set up the session manager we need
+  @BeforeClass
+  public static void setupClass() throws Exception {
+    setupServer(new Tomcat8DeltaSessionManager());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/a6e9569f/extensions/geode-modules-tomcat8/src/test/resources/tomcat/conf/tomcat-users.xml
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-tomcat8/src/test/resources/tomcat/conf/tomcat-users.xml b/extensions/geode-modules-tomcat8/src/test/resources/tomcat/conf/tomcat-users.xml
new file mode 100644
index 0000000..6c9f217
--- /dev/null
+++ b/extensions/geode-modules-tomcat8/src/test/resources/tomcat/conf/tomcat-users.xml
@@ -0,0 +1,3 @@
+<?xml version='1.0' encoding='utf-8'?>
+<tomcat-users>
+</tomcat-users>

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/a6e9569f/extensions/geode-modules-tomcat8/src/test/resources/tomcat/logs/.gitkeep
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-tomcat8/src/test/resources/tomcat/logs/.gitkeep b/extensions/geode-modules-tomcat8/src/test/resources/tomcat/logs/.gitkeep
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/a6e9569f/extensions/geode-modules-tomcat8/src/test/resources/tomcat/temp/.gitkeep
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-tomcat8/src/test/resources/tomcat/temp/.gitkeep b/extensions/geode-modules-tomcat8/src/test/resources/tomcat/temp/.gitkeep
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/a6e9569f/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/gatewaydelta/GatewayDeltaDestroyEvent.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/gatewaydelta/GatewayDeltaDestroyEvent.java b/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/gatewaydelta/GatewayDeltaDestroyEvent.java
index 18bfe8b..54e7c0d 100644
--- a/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/gatewaydelta/GatewayDeltaDestroyEvent.java
+++ b/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/gatewaydelta/GatewayDeltaDestroyEvent.java
@@ -21,7 +21,7 @@ import com.gemstone.gemfire.Instantiator;
 import com.gemstone.gemfire.cache.Cache;
 import com.gemstone.gemfire.cache.EntryNotFoundException;
 import com.gemstone.gemfire.cache.Region;
-import com.gemstone.gemfire.modules.session.catalina.DeltaSession;
+import com.gemstone.gemfire.modules.session.catalina.DeltaSessionInterface;
 
 import java.io.DataInput;
 import java.io.DataOutput;
@@ -38,7 +38,7 @@ public class GatewayDeltaDestroyEvent extends AbstractGatewayDeltaEvent {
   }
 
   public void apply(Cache cache) {
-    Region<String, DeltaSession> region = getRegion(cache);
+    Region<String, DeltaSessionInterface> region = getRegion(cache);
     try {
       region.destroy(this.key);
       if (cache.getLogger().fineEnabled()) {

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/a6e9569f/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/CommitSessionValve.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/CommitSessionValve.java b/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/CommitSessionValve.java
index 0ae17f2..379fb18 100644
--- a/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/CommitSessionValve.java
+++ b/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/CommitSessionValve.java
@@ -49,16 +49,17 @@ public class CommitSessionValve extends ValveBase {
       // Commit and if the correct Manager was found
       if (manager instanceof DeltaSessionManager) {
         session = (DeltaSessionFacade) request.getSession(false);
+        DeltaSessionManager dsm = ((DeltaSessionManager) manager);
         if (session != null) {
           if (session.isValid()) {
-            ((DeltaSessionManager) manager).removeTouchedSession(session.getId());
+            dsm.removeTouchedSession(session.getId());
             session.commit();
-            if (manager.getContainer().getLogger().isDebugEnabled()) {
-              manager.getContainer().getLogger().debug(session + ": Committed.");
+            if (dsm.getTheContext().getLogger().isDebugEnabled()) {
+              dsm.getTheContext().getLogger().debug(session + ": Committed.");
             }
           } else {
-            if (manager.getContainer().getLogger().isDebugEnabled()) {
-              manager.getContainer().getLogger().debug(session + ": Not valid so not committing.");
+            if (dsm.getTheContext().getLogger().isDebugEnabled()) {
+              dsm.getTheContext().getLogger().debug(session + ": Not valid so not committing.");
             }
           }
         }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/a6e9569f/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/DeltaSession.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/DeltaSession.java b/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/DeltaSession.java
index c81a232..ff7133d 100644
--- a/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/DeltaSession.java
+++ b/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/DeltaSession.java
@@ -54,7 +54,7 @@ import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
 @SuppressWarnings("serial")
-public class DeltaSession extends StandardSession implements DataSerializable, Delta, GatewayDelta, Sizeable {
+public class DeltaSession extends StandardSession implements DataSerializable, Delta, GatewayDelta, Sizeable, DeltaSessionInterface {
 
   private transient Region<String, HttpSession> operatingRegion;
 
@@ -139,7 +139,7 @@ public class DeltaSession extends StandardSession implements DataSerializable, D
         ((DeltaSessionManager) getManager()).getLogger().warn(builder.toString(), e);
         return null;
       }
-      this.principal = sp.getPrincipal(this.manager.getContainer().getRealm());
+      this.principal = sp.getPrincipal(((DeltaSessionManager)this.manager).getTheContext().getRealm());
       if (getManager() != null) {
         DeltaSessionManager mgr = (DeltaSessionManager) getManager();
         if (mgr.getLogger().isDebugEnabled()) {
@@ -223,7 +223,7 @@ public class DeltaSession extends StandardSession implements DataSerializable, D
         this.notes = new Hashtable();
       }
 
-      contextName = ((DeltaSessionManager) manager).getContainer().getName();
+      contextName = ((DeltaSessionManager) manager).getContextName();
     } else {
       throw new IllegalArgumentException(this + ": The Manager must be an AbstractManager");
     }
@@ -345,7 +345,7 @@ public class DeltaSession extends StandardSession implements DataSerializable, D
     super.removeAttribute(name, false); // don't do notification since this is a replication
   }
 
-  public void applyAttributeEvents(Region<String, DeltaSession> region, List<DeltaSessionAttributeEvent> events) {
+  public void applyAttributeEvents(Region<String, DeltaSessionInterface> region, List<DeltaSessionAttributeEvent> events) {
     for (DeltaSessionAttributeEvent event : events) {
       event.apply(this);
       queueAttributeEvent(event, false);
@@ -429,7 +429,7 @@ public class DeltaSession extends StandardSession implements DataSerializable, D
     this.expired = expired;
   }
 
-  protected boolean getExpired() {
+  public boolean getExpired() {
     return this.expired;
   }
 
@@ -515,7 +515,7 @@ public class DeltaSession extends StandardSession implements DataSerializable, D
     this.maxInactiveInterval = in.readInt();
     this.isNew = in.readBoolean();
     this.isValid = in.readBoolean();
-    this.attributes = DataSerializer.readObject(in);
+    this.attributes = readInAttributes(in);
     this.serializedPrincipal = DataSerializer.readByteArray(in);
 
     // Read the DeltaSession state
@@ -537,6 +537,10 @@ public class DeltaSession extends StandardSession implements DataSerializable, D
     }
   }
 
+  protected Map readInAttributes(final DataInput in) throws IOException, ClassNotFoundException {
+    return DataSerializer.readObject(in);
+  }
+
   @Override
   public int getSizeInBytes() {
     int size = 0;
@@ -553,7 +557,7 @@ public class DeltaSession extends StandardSession implements DataSerializable, D
   }
 
   @SuppressWarnings({"unchecked", "rawtypes"})
-  private Map<String, byte[]> getSerializedAttributes() {
+  protected Map<String, byte[]> getSerializedAttributes() {
     // Iterate the values and serialize them if necessary before sending them to the server. This makes the application classes unnecessary on the server.
     Map<String, byte[]> serializedAttributes = new ConcurrentHashMap<String, byte[]>();
     for (Iterator i = this.attributes.entrySet().iterator(); i.hasNext(); ) {
@@ -565,7 +569,7 @@ public class DeltaSession extends StandardSession implements DataSerializable, D
     return serializedAttributes;
   }
 
-  private byte[] serialize(Object obj) {
+  protected byte[] serialize(Object obj) {
     byte[] serializedValue = null;
     try {
       serializedValue = BlobHelper.serializeToBlob(obj);

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/a6e9569f/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/DeltaSessionFacade.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/DeltaSessionFacade.java b/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/DeltaSessionFacade.java
index 1ac4da2..2259ffe 100644
--- a/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/DeltaSessionFacade.java
+++ b/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/DeltaSessionFacade.java
@@ -22,12 +22,12 @@ import javax.servlet.http.HttpSession;
 
 public class DeltaSessionFacade extends StandardSessionFacade {
 
-  private DeltaSession session;
+  private DeltaSessionInterface session;
 
   /**
    * Construct a new session facade.
    */
-  public DeltaSessionFacade(DeltaSession session) {
+  public DeltaSessionFacade(DeltaSessionInterface session) {
     super((HttpSession) session);
     // Store session locally since the super session is private and provides no accessor.
     this.session = session;

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/a6e9569f/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/DeltaSessionInterface.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/DeltaSessionInterface.java b/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/DeltaSessionInterface.java
new file mode 100644
index 0000000..1d3d1f7
--- /dev/null
+++ b/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/DeltaSessionInterface.java
@@ -0,0 +1,52 @@
+/*
+* 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 com.gemstone.gemfire.modules.session.catalina;
+
+import com.gemstone.gemfire.cache.Region;
+
+
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.catalina.Session;
+import org.apache.catalina.session.ManagerBase;
+
+import com.gemstone.gemfire.modules.session.catalina.internal.DeltaSessionAttributeEvent;
+
+public interface DeltaSessionInterface extends Session {
+
+  void commit();
+  void abort();
+  boolean isValid();
+  void localDestroyAttribute(String name);
+  void applyAttributeEvents(Region<String, DeltaSessionInterface> region, List<DeltaSessionAttributeEvent> events);
+
+  void localUpdateAttribute(String attributeName, Object attributeValue);
+
+  void toData(DataOutput os) throws IOException;
+  void fromData(DataInput is) throws IOException, ClassNotFoundException;
+
+  String getContextName();
+  boolean getExpired();
+
+  void setOwner(Object manager);
+  void activate();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/a6e9569f/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/DeltaSessionManager.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/DeltaSessionManager.java b/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/DeltaSessionManager.java
index 92d9ef6..d1b6011 100644
--- a/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/DeltaSessionManager.java
+++ b/extensions/geode-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/DeltaSessionManager.java
@@ -29,14 +29,13 @@ import com.gemstone.gemfire.modules.util.RegionHelper;
 import org.apache.catalina.Container;
 import org.apache.catalina.Context;
 import org.apache.catalina.Lifecycle;
-import org.apache.catalina.LifecycleListener;
 import org.apache.catalina.Loader;
+import org.apache.catalina.Pipeline;
 import org.apache.catalina.Session;
 import org.apache.catalina.Valve;
 import org.apache.catalina.session.ManagerBase;
 import org.apache.catalina.session.StandardSession;
 import org.apache.catalina.util.CustomObjectInputStream;
-import org.apache.catalina.util.LifecycleSupport;
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
 
@@ -65,11 +64,6 @@ import java.util.concurrent.atomic.AtomicInteger;
 abstract public class DeltaSessionManager extends ManagerBase implements Lifecycle, PropertyChangeListener, SessionManager {
 
   /**
-   * The <code>LifecycleSupport</code> for this component.
-   */
-  protected LifecycleSupport lifecycle = new LifecycleSupport(this);
-
-  /**
    * The number of rejected sessions.
    */
   private AtomicInteger rejectedSessions;
@@ -156,6 +150,11 @@ abstract public class DeltaSessionManager extends ManagerBase implements Lifecyc
   }
 
   @Override
+  public void setMaxInactiveInterval(final int interval) {
+    super.setMaxInactiveInterval(interval);
+  }
+
+  @Override
   public String getRegionAttributesId() {
     // This property will be null if it hasn't been set in the context.xml file.
     // Since its default is dependent on the session cache, get the default from
@@ -258,7 +257,7 @@ abstract public class DeltaSessionManager extends ManagerBase implements Lifecyc
 
   @Override
   public String getStatisticsName() {
-    return getContainer().getName().replace("/", "");
+    return getContextName().replace("/", "");
   }
 
   @Override
@@ -320,7 +319,7 @@ abstract public class DeltaSessionManager extends ManagerBase implements Lifecyc
     if (getLogger().isDebugEnabled()) {
       getLogger().debug(this + ": Finding session " + id + " in " + getSessionCache().getOperatingRegionName());
     }
-    DeltaSession session = (DeltaSession) getSessionCache().getSession(id);
+    DeltaSessionInterface session = (DeltaSessionInterface) getSessionCache().getSession(id);
     /*
      * Check that the context name for this session is the same as this manager's.
      * This comes into play when multiple versions of a webapp are deployed and
@@ -329,10 +328,10 @@ abstract public class DeltaSessionManager extends ManagerBase implements Lifecyc
      */
     if (session != null &&
         !session.getContextName().isEmpty() &&
-        !getContainer().getName().equals(session.getContextName())) {
+        !getContextName().equals(session.getContextName())) {
       getLogger().info(this + ": Session " + id +
           " rejected as container name and context do not match: " +
-          getContainer().getName() + " != " + session.getContextName());
+          getContextName() + " != " + session.getContextName());
       session = null;
     }
 
@@ -352,7 +351,7 @@ abstract public class DeltaSessionManager extends ManagerBase implements Lifecyc
       // If the manager is null, the session was replicated and this is a
       // failover situation. Reset the manager and activate the session.
       if (session.getManager() == null) {
-        DeltaSession ds = (DeltaSession) session;
+        DeltaSessionInterface ds = (DeltaSessionInterface) session;
         ds.setOwner(this);
         ds.activate();
       }
@@ -390,7 +389,7 @@ abstract public class DeltaSessionManager extends ManagerBase implements Lifecyc
     //super.remove(session);
     // Remove the session from the region if necessary.
     // It will have already been removed if it expired implicitly.
-    DeltaSession ds = (DeltaSession) session;
+    DeltaSessionInterface ds = (DeltaSessionInterface) session;
     if (ds.getExpired()) {
       if (getLogger().isDebugEnabled()) {
         getLogger().debug(
@@ -545,13 +544,13 @@ abstract public class DeltaSessionManager extends ManagerBase implements Lifecyc
   @Override
   public void load() throws ClassNotFoundException, IOException {
     doLoad();
-    ContextMapper.addContext(getContainer().getName(), this);
+    ContextMapper.addContext(getContextName(), this);
   }
 
   @Override
   public void unload() throws IOException {
     doUnload();
-    ContextMapper.removeContext(getContainer().getName());
+    ContextMapper.removeContext(getContextName());
   }
 
   protected void registerJvmRouteBinderValve() {
@@ -559,7 +558,11 @@ abstract public class DeltaSessionManager extends ManagerBase implements Lifecyc
       getLogger().debug(this + ": Registering JVM route binder valve");
     }
     jvmRouteBinderValve = new JvmRouteBinderValve();
-    getContainer().getPipeline().addValve(jvmRouteBinderValve);
+    getPipeline().addValve(jvmRouteBinderValve);
+  }
+
+  protected Pipeline getPipeline() {
+    return getContainer().getPipeline();
   }
 
   protected void unregisterJvmRouteBinderValve() {
@@ -567,7 +570,7 @@ abstract public class DeltaSessionManager extends ManagerBase implements Lifecyc
       getLogger().debug(this + ": Unregistering JVM route binder valve");
     }
     if (jvmRouteBinderValve != null) {
-      getContainer().getPipeline().removeValve(jvmRouteBinderValve);
+      getPipeline().removeValve(jvmRouteBinderValve);
     }
   }
 
@@ -576,7 +579,7 @@ abstract public class DeltaSessionManager extends ManagerBase implements Lifecyc
       getLogger().debug(this + ": Registering CommitSessionValve");
     }
     commitSessionValve = new CommitSessionValve();
-    getContainer().getPipeline().addValve(commitSessionValve);
+    getPipeline().addValve(commitSessionValve);
   }
 
   protected void unregisterCommitSessionValve() {
@@ -584,42 +587,13 @@ abstract public class DeltaSessionManager extends ManagerBase implements Lifecyc
       getLogger().debug(this + ": Unregistering CommitSessionValve");
     }
     if (commitSessionValve != null) {
-      getContainer().getPipeline().removeValve(commitSessionValve);
+      getPipeline().removeValve(commitSessionValve);
     }
   }
 
   // ------------------------------ Lifecycle Methods
 
   /**
-   * Add a lifecycle event listener to this component.
-   *
-   * @param listener The listener to add
-   */
-  @Override
-  public void addLifecycleListener(LifecycleListener listener) {
-    this.lifecycle.addLifecycleListener(listener);
-  }
-
-  /**
-   * Get the lifecycle listeners associated with this lifecycle. If this Lifecycle has no listeners registered, a
-   * zero-length array is returned.
-   */
-  @Override
-  public LifecycleListener[] findLifecycleListeners() {
-    return this.lifecycle.findLifecycleListeners();
-  }
-
-  /**
-   * Remove a lifecycle event listener from this component.
-   *
-   * @param listener The listener to remove
-   */
-  @Override
-  public void removeLifecycleListener(LifecycleListener listener) {
-    this.lifecycle.removeLifecycleListener(listener);
-  }
-
-  /**
    * Process property change events from our associated Context.
    * <p>
    * Part of this method implementation was taken from StandardManager. The sessionTimeout can be changed in the web.xml
@@ -674,12 +648,8 @@ abstract public class DeltaSessionManager extends ManagerBase implements Lifecyc
    */
   protected void doUnload() throws IOException {
     QueryService querySvc = sessionCache.getCache().getQueryService();
-    Context context;
-    if (getContainer() instanceof Context) {
-      context = (Context) getContainer();
-    } else {
-      getLogger().error("Unable to unload sessions - container is of type " +
-          getContainer().getClass().getName() + " instead of StandardContext");
+    Context context = getTheContext();
+    if (context == null) {
       return;
     }
     String regionName;
@@ -751,11 +721,11 @@ abstract public class DeltaSessionManager extends ManagerBase implements Lifecyc
       }
     }
 
-    ArrayList<StandardSession> list = new ArrayList<StandardSession>();
+    ArrayList<DeltaSessionInterface> list = new ArrayList<DeltaSessionInterface>();
     Iterator<String> elements = results.iterator();
     while (elements.hasNext()) {
       String id = elements.next();
-      DeltaSession session = (DeltaSession) findSession(id);
+      DeltaSessionInterface session = (DeltaSessionInterface) findSession(id);
       if (session != null) {
         list.add(session);
       }
@@ -765,9 +735,16 @@ abstract public class DeltaSessionManager extends ManagerBase implements Lifecyc
     if (getLogger().isDebugEnabled()) getLogger().debug("Unloading " + list.size() + " sessions");
     try {
       oos.writeObject(new Integer(list.size()));
-      for (StandardSession session : list) {
-        session.passivate();
-        session.writeObjectData(oos);
+      for (DeltaSessionInterface session : list) {
+        if (session instanceof StandardSession) {
+          StandardSession standardSession = (StandardSession) session;
+          standardSession.passivate();
+          standardSession.writeObjectData(oos);
+        }
+        else {
+          //All DeltaSessionInterfaces as of Geode 1.0 should be based on StandardSession
+          throw new IOException("Session should be of type StandardSession");
+        }
       }
     } catch (IOException e) {
       getLogger().error("Exception unloading sessions", e);
@@ -792,7 +769,7 @@ abstract public class DeltaSessionManager extends ManagerBase implements Lifecyc
 
     // Locally destroy the sessions we just wrote
     if (getSessionCache().isClientServer()) {
-      for (StandardSession session : list) {
+      for (DeltaSessionInterface session : list) {
         if (getLogger().isDebugEnabled()) {
           getLogger().debug("Locally destroying session " + session.getId());
         }
@@ -829,12 +806,8 @@ abstract public class DeltaSessionManager extends ManagerBase implements Lifecyc
    * @throws IOException            if an input/output error occurs
    */
   protected void doLoad() throws ClassNotFoundException, IOException {
-    Context context;
-    if (getContainer() instanceof Context) {
-      context = (Context) getContainer();
-    } else {
-      getLogger().error("Unable to unload sessions - container is of type " +
-          getContainer().getClass().getName() + " instead of StandardContext");
+    Context context = getTheContext();
+    if (context == null) {
       return;
     }
 
@@ -855,8 +828,8 @@ abstract public class DeltaSessionManager extends ManagerBase implements Lifecyc
     try {
       fis = new FileInputStream(store.getAbsolutePath());
       bis = new BufferedInputStream(fis);
-      if (container != null) {
-        loader = container.getLoader();
+      if (getTheContext() != null) {
+        loader = getTheContext().getLoader();
       }
       if (loader != null) {
         classLoader = loader.getClassLoader();
@@ -909,7 +882,7 @@ abstract public class DeltaSessionManager extends ManagerBase implements Lifecyc
         session.setManager(this);
 
         Region region = getSessionCache().getOperatingRegion();
-        DeltaSession existingSession = (DeltaSession) region.get(session.getId());
+        DeltaSessionInterface existingSession = (DeltaSessionInterface) region.get(session.getId());
         // Check whether the existing session is newer
         if (existingSession != null && existingSession.getLastAccessedTime() > session.getLastAccessedTime()) {
           if (getLogger().isDebugEnabled()) {
@@ -981,7 +954,7 @@ abstract public class DeltaSessionManager extends ManagerBase implements Lifecyc
     return new StringBuilder().append(getClass().getSimpleName())
         .append("[")
         .append("container=")
-        .append(getContainer())
+        .append(getTheContext())
         .append("; regionName=")
         .append(this.regionName)
         .append("; regionAttributesId=")
@@ -989,4 +962,18 @@ abstract public class DeltaSessionManager extends ManagerBase implements Lifecyc
         .append("]")
         .toString();
   }
+
+  protected String getContextName() {
+    return getTheContext().getName();
+  }
+
+  public Context getTheContext() {
+    if (getContainer() instanceof Context) {
+      return  (Context) getContainer();
+    } else {
+      getLogger().error("Unable to unload sessions - container is of type " +
+                        getContainer().getClass().getName() + " instead of StandardContext");
+      return null;
+    }
+  }
 }