You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by kl...@apache.org on 2016/02/08 22:58:49 UTC

[22/50] [abbrv] incubator-geode git commit: GEODE-14: Integration of GemFire Session Replication and Hibernate modules

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/attributes/ImmediateSessionAttributes.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/attributes/ImmediateSessionAttributes.java b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/attributes/ImmediateSessionAttributes.java
new file mode 100644
index 0000000..15936ba
--- /dev/null
+++ b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/attributes/ImmediateSessionAttributes.java
@@ -0,0 +1,68 @@
+/*
+* 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.internal.filter.attributes;
+
+import com.gemstone.gemfire.DataSerializable;
+import com.gemstone.gemfire.Instantiator;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This class implements immediately transmitted attributes. All attributes are
+ * transmitted for every attribute update. This is bound to be a performance hit
+ * in some cases but ensures much higher data availability.
+ */
+public class ImmediateSessionAttributes extends AbstractSessionAttributes {
+
+  private static final Logger LOG =
+      LoggerFactory.getLogger(ImmediateSessionAttributes.class.getName());
+
+  /**
+   * Register ourselves for de-serialization
+   */
+  static {
+    Instantiator.register(
+        new Instantiator(ImmediateSessionAttributes.class, 347) {
+          @Override
+          public DataSerializable newInstance() {
+            return new ImmediateSessionAttributes();
+          }
+        });
+  }
+
+  /**
+   * Default constructor
+   */
+  public ImmediateSessionAttributes() {
+  }
+
+  @Override
+  public Object putAttribute(String attr, Object value) {
+    Object obj = attributes.put(attr, value);
+    flush();
+    return obj;
+  }
+
+  @Override
+  public Object removeAttribute(String attr) {
+    Object obj = attributes.remove(attr);
+    flush();
+    return obj;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/attributes/QueuedSessionAttributes.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/attributes/QueuedSessionAttributes.java b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/attributes/QueuedSessionAttributes.java
new file mode 100644
index 0000000..8d20b43
--- /dev/null
+++ b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/attributes/QueuedSessionAttributes.java
@@ -0,0 +1,65 @@
+/*
+* 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.internal.filter.attributes;
+
+import com.gemstone.gemfire.DataSerializable;
+import com.gemstone.gemfire.Instantiator;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This class implements an attribute container which delays sending updates
+ * until the session goes out of scope. All attributes are transmitted during
+ * the update.
+ */
+public class QueuedSessionAttributes extends AbstractSessionAttributes {
+
+  private static final Logger LOG =
+      LoggerFactory.getLogger(QueuedSessionAttributes.class.getName());
+
+  /**
+   * Register ourselves for de-serialization
+   */
+  static {
+    Instantiator.register(new Instantiator(QueuedSessionAttributes.class, 347) {
+      @Override
+      public DataSerializable newInstance() {
+        return new QueuedSessionAttributes();
+      }
+    });
+  }
+
+  /**
+   * Default constructor
+   */
+  public QueuedSessionAttributes() {
+  }
+
+  @Override
+  public Object putAttribute(String attr, Object value) {
+    Object obj = attributes.put(attr, value);
+    return obj;
+  }
+
+  @Override
+  public Object removeAttribute(String attr) {
+    Object obj = attributes.remove(attr);
+    return obj;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/attributes/SessionAttributes.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/attributes/SessionAttributes.java b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/attributes/SessionAttributes.java
new file mode 100644
index 0000000..b3b0cef
--- /dev/null
+++ b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/attributes/SessionAttributes.java
@@ -0,0 +1,120 @@
+/*
+* 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.internal.filter.attributes;
+
+import com.gemstone.gemfire.DataSerializable;
+import com.gemstone.gemfire.modules.session.internal.filter.GemfireHttpSession;
+
+import java.util.Set;
+
+/**
+ * Interface for session attribute storage. In reality, this interface is
+ * responsible for anything, in the session which needs to be propagated for
+ * caching - as such it also includes other 'attributes' such as
+ * maxInactiveInterval and lastAccessedTime
+ */
+public interface SessionAttributes extends DataSerializable {
+
+  /**
+   * Set the session to which these attributes belong.
+   *
+   * @param session the session to set
+   */
+  public void setSession(GemfireHttpSession session);
+
+  /**
+   * Set an attribute value.
+   *
+   * @param attr  the name of the attribute to set
+   * @param value the value for the attribute
+   * @return the value object
+   */
+  public Object putAttribute(String attr, Object value);
+
+  /**
+   * Retrieve an attribute's value.
+   *
+   * @param attr the name of the attribute
+   * @return the object associated with the attribute or null if none exists.
+   */
+  public Object getAttribute(String attr);
+
+  /**
+   * Remove the named attribute.
+   *
+   * @param attr the name of the attribute to remove
+   * @return the value of the attribute removed or null if the named attribute
+   * did not exist.
+   */
+  public Object removeAttribute(String attr);
+
+  /**
+   * Return a set of all attribute names.
+   *
+   * @return a set of all attribute names
+   */
+  public Set<String> getAttributeNames();
+
+  /**
+   * Set the max inactive interval for replication to other systems
+   *
+   * @param interval the time interval in seconds
+   */
+  public void setMaxInactiveInterval(int interval);
+
+  /**
+   * Retrieve the max inactive interval
+   *
+   * @return the max inactive interval in seconds
+   */
+  public int getMaxIntactiveInterval();
+
+  /**
+   * Set the last accessed time for replication to other systems
+   *
+   * @param time the last accessed time in milliseconds
+   */
+  public void setLastAccessedTime(long time);
+
+  /**
+   * Return the last accessed time in milliseconds
+   *
+   * @return the last accessed time
+   */
+  public long getLastAccessedTime();
+
+  /**
+   * Explicitly flush the attributes to backing store.
+   */
+  public void flush();
+
+  /**
+   * Return the last jvm which 'owned' these attributes
+   *
+   * @return the jvmId
+   */
+  public String getJvmOwnerId();
+
+  /**
+   * Set the jvmId. This is set every time the attributes are flushed to the
+   * cache.
+   *
+   * @param jvmId
+   */
+  public void setJvmOwnerId(String jvmId);
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/util/NamedThreadFactory.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/util/NamedThreadFactory.java b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/util/NamedThreadFactory.java
new file mode 100644
index 0000000..7491cf0
--- /dev/null
+++ b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/util/NamedThreadFactory.java
@@ -0,0 +1,68 @@
+/*
+* 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.internal.filter.util;
+
+import java.lang.Thread.UncaughtExceptionHandler;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Factory to create named threads for easy identification at runtime.
+ */
+public class NamedThreadFactory implements ThreadFactory {
+
+  private static final Logger LOG = Logger.getLogger(
+      NamedThreadFactory.class.getName());
+
+  private final String id;
+
+  private final AtomicLong serial = new AtomicLong();
+
+  /**
+   * Create a new thread factory, using the specified pool ID as a basis for
+   * naming each thread.
+   *
+   * @param poolID pool name/ID
+   */
+  public NamedThreadFactory(final String poolID) {
+    id = poolID;
+  }
+
+  /**
+   * {@inheritDoc}
+   * <p/>
+   * This implementation sets the name of the thread, sets the thread to be a
+   * daemon thread, and adds an uncaught exception handler.
+   */
+  @Override
+  public Thread newThread(Runnable r) {
+    Thread thr = new Thread(r);
+    thr.setDaemon(true);
+    thr.setName(id + " - " + serial.incrementAndGet());
+    thr.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
+      @Override
+      public void uncaughtException(Thread t, Throwable e) {
+        LOG.log(Level.WARNING,
+            "Uncaught Exception in thread: " + t.getName(), e);
+      }
+    });
+    return thr;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/util/ThreadLocalSession.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/util/ThreadLocalSession.java b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/util/ThreadLocalSession.java
new file mode 100644
index 0000000..996b1fd
--- /dev/null
+++ b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/util/ThreadLocalSession.java
@@ -0,0 +1,39 @@
+/*
+* 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.internal.filter.util;
+
+import javax.servlet.http.HttpSession;
+
+/**
+ */
+public class ThreadLocalSession {
+  private static ThreadLocal<HttpSession> threadLocal =
+      new ThreadLocal<HttpSession>();
+
+  public static HttpSession get() {
+    return threadLocal.get();
+  }
+
+  public static void set(HttpSession session) {
+    threadLocal.set(session);
+  }
+
+  public static void remove() {
+    threadLocal.remove();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/util/TypeAwareMap.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/util/TypeAwareMap.java b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/util/TypeAwareMap.java
new file mode 100644
index 0000000..705bafd
--- /dev/null
+++ b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/filter/util/TypeAwareMap.java
@@ -0,0 +1,50 @@
+/*
+* 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.internal.filter.util;
+
+import com.gemstone.gemfire.modules.session.internal.common.CacheProperty;
+
+import java.util.HashMap;
+
+/**
+ *
+ */
+public class TypeAwareMap<K extends CacheProperty, Object> extends HashMap {
+
+  private Class<K> keyType;
+
+  public TypeAwareMap(Class<K> keyType) {
+    super();
+    this.keyType = keyType;
+  }
+
+  public Object put(K key, Object value) {
+    if (!key.getClazz().isAssignableFrom(value.getClass())) {
+      if (key.getClazz() == Boolean.class) {
+        return (Object) super.put(key, Boolean.valueOf((String) value));
+      } else if (key.getClazz() == Integer.class) {
+        return (Object) super.put(key, Integer.valueOf((String) value));
+      } else {
+        throw new IllegalArgumentException("Value is not of type " +
+            key.getClazz().getName());
+      }
+    }
+
+    return (Object) super.put(key, value);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/jmx/SessionStatistics.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/jmx/SessionStatistics.java b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/jmx/SessionStatistics.java
new file mode 100644
index 0000000..9f945da
--- /dev/null
+++ b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/jmx/SessionStatistics.java
@@ -0,0 +1,78 @@
+/*
+* 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.internal.jmx;
+
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * Class to manage session statistics
+ */
+public class SessionStatistics implements SessionStatisticsMXBean {
+
+  private AtomicInteger activeSessions = new AtomicInteger(0);
+
+  private AtomicInteger totalSessions = new AtomicInteger(0);
+
+  private AtomicLong regionUpdates = new AtomicLong(0);
+
+  @Override
+  public int getActiveSessions() {
+    return activeSessions.get();
+  }
+
+  @Override
+  public int getTotalSessions() {
+    return totalSessions.get();
+  }
+
+  @Override
+  public long getRegionUpdates() {
+    return regionUpdates.get();
+  }
+
+  public void setActiveSessions(int sessions) {
+    activeSessions.set(sessions);
+  }
+
+  public void setTotalSessions(int sessions) {
+    totalSessions.set(sessions);
+  }
+
+  public void incActiveSessions() {
+    activeSessions.incrementAndGet();
+    totalSessions.incrementAndGet();
+  }
+
+  public void decActiveSessions() {
+    activeSessions.decrementAndGet();
+  }
+
+  public void incTotalSessions() {
+    totalSessions.incrementAndGet();
+  }
+
+  public void decTotalSessions() {
+    totalSessions.decrementAndGet();
+  }
+
+  public void incRegionUpdates() {
+    regionUpdates.incrementAndGet();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/jmx/SessionStatisticsMXBean.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/jmx/SessionStatisticsMXBean.java b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/jmx/SessionStatisticsMXBean.java
new file mode 100644
index 0000000..33cfc3e
--- /dev/null
+++ b/extensions/gemfire-modules-session/src/main/java/com/gemstone/gemfire/modules/session/internal/jmx/SessionStatisticsMXBean.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.gemstone.gemfire.modules.session.internal.jmx;
+
+/**
+ * MXBean interface to retrieve Session statistics
+ */
+public interface SessionStatisticsMXBean {
+
+  public int getActiveSessions();
+
+  public int getTotalSessions();
+
+  public long getRegionUpdates();
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/AbstractListener.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/AbstractListener.java b/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/AbstractListener.java
new file mode 100644
index 0000000..0bca895
--- /dev/null
+++ b/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/AbstractListener.java
@@ -0,0 +1,57 @@
+/*
+* 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.internal.filter;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author jdeppe
+ */
+public abstract class AbstractListener {
+
+  protected final List<ListenerEventType> events =
+      new ArrayList<ListenerEventType>();
+
+  protected CountDownLatch latch;
+
+  public AbstractListener() {
+    this(1);
+  }
+
+  public AbstractListener(int numCalls) {
+    latch = new CountDownLatch(numCalls);
+    RendezvousManager.registerListener(this);
+  }
+
+  public synchronized void setLatch(int numCalls) {
+    latch = new CountDownLatch(numCalls);
+    events.clear();
+  }
+
+  public boolean await(long timeout,
+      TimeUnit unit) throws InterruptedException {
+    return latch.await(timeout, unit);
+  }
+
+  public List<ListenerEventType> getEvents() {
+    return events;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/BasicServlet.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/BasicServlet.java b/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/BasicServlet.java
new file mode 100644
index 0000000..5804317
--- /dev/null
+++ b/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/BasicServlet.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.internal.filter;
+
+import java.io.IOException;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.servlet.DefaultServlet;
+/**
+ *
+ */
+public class BasicServlet extends DefaultServlet {
+
+  Callback callback = null;
+
+  @Override
+  public void doGet(HttpServletRequest request, HttpServletResponse response)
+      throws IOException, ServletException {
+
+    if (callback != null) {
+      callback.call(request, response);
+    }
+  }
+
+  @Override
+  public void init(ServletConfig config) throws ServletException {
+    super.init(config);
+    ServletContext context = config.getServletContext();
+
+    String cbInitParam = config.getInitParameter("test.callback");
+    callback = (Callback) context.getAttribute(cbInitParam);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/Callback.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/Callback.java b/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/Callback.java
new file mode 100644
index 0000000..fa5b64f
--- /dev/null
+++ b/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/Callback.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.gemstone.gemfire.modules.session.internal.filter;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * Interface which, when implemented, can be put into a servlet context and executed by the servlet.
+ */
+public interface Callback {
+  void call(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/CallbackServlet.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/CallbackServlet.java b/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/CallbackServlet.java
new file mode 100644
index 0000000..3050280
--- /dev/null
+++ b/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/CallbackServlet.java
@@ -0,0 +1,91 @@
+/*
+* 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.internal.filter;
+
+import java.io.IOException;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public class CallbackServlet extends HttpServlet {
+
+  private Callback callback;
+
+  /**
+   * Processes requests for both HTTP <code>GET</code> and <code>POST</code>
+   * methods.
+   *
+   * @param request  servlet request
+   * @param response servlet response
+   * @throws ServletException if a servlet-specific error occurs
+   * @throws IOException      if an I/O error occurs
+   */
+  protected void processRequest(HttpServletRequest request,
+      HttpServletResponse response)
+      throws ServletException, IOException {
+
+    if (callback != null) {
+      callback.call(request, response);
+    }
+  }
+
+  public void setCallback(Callback callback) {
+    this.callback = callback;
+  }
+
+  /**
+   * Handles the HTTP <code>GET</code> method.
+   *
+   * @param request  servlet request
+   * @param response servlet response
+   * @throws ServletException if a servlet-specific error occurs
+   * @throws IOException      if an I/O error occurs
+   */
+  @Override
+  protected void doGet(HttpServletRequest request, HttpServletResponse response)
+      throws ServletException, IOException {
+    processRequest(request, response);
+  }
+
+  /**
+   * Handles the HTTP <code>POST</code> method.
+   *
+   * @param request  servlet request
+   * @param response servlet response
+   * @throws ServletException if a servlet-specific error occurs
+   * @throws IOException      if an I/O error occurs
+   */
+  @Override
+  protected void doPost(HttpServletRequest request,
+      HttpServletResponse response)
+      throws ServletException, IOException {
+    processRequest(request, response);
+  }
+
+  /**
+   * Returns a short description of the servlet.
+   *
+   * @return a String containing servlet description
+   */
+  @Override
+  public String getServletInfo() {
+    return "Short description";
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/CommonTests.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/CommonTests.java b/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/CommonTests.java
new file mode 100644
index 0000000..4a37d36
--- /dev/null
+++ b/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/CommonTests.java
@@ -0,0 +1,582 @@
+/*
+* 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.internal.filter;
+
+import com.mockrunner.mock.web.MockHttpServletRequest;
+import com.mockrunner.mock.web.MockHttpServletResponse;
+import com.mockrunner.mock.web.MockHttpSession;
+import com.mockrunner.servlet.BasicServletTestCaseAdapter;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.util.concurrent.TimeUnit;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.HttpSessionAttributeListener;
+
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.*;
+
+/**
+ * This servlet tests the effects of the downstream SessionCachingFilter filter.
+ * When these tests are performed, the filter would already have taken effect.
+ */
+public abstract class CommonTests extends BasicServletTestCaseAdapter {
+
+  protected static final String CONTEXT_PATH = "/test";
+
+  @Test
+  public void testGetSession1() throws Exception {
+    doFilter();
+    HttpSession session1 =
+        ((HttpServletRequest) getFilteredRequest()).getSession();
+    HttpSession session2 =
+        ((HttpServletRequest) getFilteredRequest()).getSession();
+
+    assertSame("Session should be the same", session1, session2);
+  }
+
+  @Test
+  public void testGetSession2() throws Exception {
+    doFilter();
+
+    HttpSession session1 = ((HttpServletRequest) getFilteredRequest()).getSession();
+
+    MockHttpServletResponse response = getWebMockObjectFactory().getMockResponse();
+    Cookie cookie = (Cookie) response.getCookies().get(0);
+    getWebMockObjectFactory().getMockRequest().addCookie(cookie);
+
+    doFilter();
+
+    HttpSession session2 = ((HttpServletRequest) getFilteredRequest()).getSession();
+
+    assertEquals("Session objects across requests should be the same", session1, session2);
+  }
+
+  @Test
+  public void testGetAttributeRequest1() throws Exception {
+    doFilter();
+
+    getFilteredRequest().setAttribute("foo", "bar");
+
+    assertEquals("bar", getFilteredRequest().getAttribute("foo"));
+    assertNull("Unknown attribute should be null",
+        getFilteredRequest().getAttribute("baz"));
+  }
+
+  @Test
+  public void testGetAttributeRequest2() throws Exception {
+    // Setup
+    CallbackServlet s = (CallbackServlet) getServlet();
+    s.setCallback(new Callback() {
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response) {
+        request.setAttribute("foo", "bar");
+      }
+    });
+    doFilter();
+
+    assertEquals("bar", getFilteredRequest().getAttribute("foo"));
+    assertNull("Unknown attribute should be null",
+        getFilteredRequest().getAttribute("baz"));
+  }
+
+  @Test
+  public void testGetAttributeSession1() throws Exception {
+    doFilter();
+
+    ((HttpServletRequest) getFilteredRequest()).getSession().setAttribute("foo", "bar");
+
+    HttpServletRequest request = (HttpServletRequest) getFilteredRequest();
+    assertEquals("bar", request.getSession().getAttribute("foo"));
+  }
+
+  /**
+   * Are attributes preserved across client requests?
+   */
+  @Test
+  public void testGetAttributeSession2() throws Exception {
+    doFilter();
+
+    ((HttpServletRequest) getFilteredRequest()).getSession().setAttribute("foo", "bar");
+
+    MockHttpServletResponse response = getWebMockObjectFactory().getMockResponse();
+    Cookie cookie = (Cookie) response.getCookies().get(0);
+    getWebMockObjectFactory().getMockRequest().addCookie(cookie);
+
+    doFilter();
+    HttpServletRequest request = (HttpServletRequest) getFilteredRequest();
+
+    assertEquals("bar", request.getSession().getAttribute("foo"));
+  }
+
+  /**
+   * Setting a session attribute to null should remove it
+   */
+  @Test
+  public void testSetAttributeNullSession1() throws Exception {
+    // Setup
+    CallbackServlet s = (CallbackServlet) getServlet();
+    s.setCallback(new Callback() {
+      private boolean called = false;
+
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response) {
+        if (called) {
+          request.getSession().setAttribute("foo", null);
+        } else {
+          request.getSession().setAttribute("foo", "bar");
+          called = true;
+        }
+      }
+    });
+
+    doFilter();
+    doFilter();
+
+    HttpSession session = ((HttpServletRequest) getFilteredRequest()).getSession();
+
+    String attr = (String) session.getAttribute("foo");
+    assertNull("Attribute should be null but is " + attr, attr);
+  }
+
+
+  /**
+   * Test that various methods throw the appropriate exception when the session is
+   * invalid.
+   */
+  @Test
+  public void testInvalidate1() throws Exception {
+    doFilter();
+
+    HttpSession session = ((HttpServletRequest) getFilteredRequest()).getSession();
+    session.invalidate();
+
+    try {
+      session.getAttribute("foo");
+      fail("Session should be invalid and an exception should be thrown");
+    } catch (IllegalStateException iex) {
+      // Pass
+    }
+  }
+
+  @Test
+  public void testInvalidate2() throws Exception {
+    doFilter();
+
+    HttpSession session = ((HttpServletRequest) getFilteredRequest()).getSession();
+    session.invalidate();
+
+    try {
+      session.getAttributeNames();
+      fail("Session should be invalid and an exception should be thrown");
+    } catch (IllegalStateException iex) {
+      // Pass
+    }
+  }
+
+  @Ignore(value = "until mockrunner 1.0.9 - see pull request #23")
+  public void testInvalidate3() throws Exception {
+    doFilter();
+
+    HttpSession session = ((HttpServletRequest) getFilteredRequest()).getSession();
+    session.invalidate();
+
+    try {
+      session.getCreationTime();
+      fail("Session should be invalid and an exception should be thrown");
+    } catch (IllegalStateException iex) {
+      // Pass
+    }
+  }
+
+  @Test
+  public void testInvalidate4() throws Exception {
+    doFilter();
+
+    HttpSession session = ((HttpServletRequest) getFilteredRequest()).getSession();
+    session.invalidate();
+
+    try {
+      session.getId();
+    } catch (Exception iex) {
+      fail("Exception should not be thrown");
+    }
+  }
+
+  @Test
+  public void testInvalidate5() throws Exception {
+    doFilter();
+
+    HttpSession session = ((HttpServletRequest) getFilteredRequest()).getSession();
+    session.invalidate();
+
+    try {
+      session.getLastAccessedTime();
+      fail("Session should be invalid and an exception should be thrown");
+    } catch (IllegalStateException iex) {
+      // Pass
+    }
+  }
+
+  @Test
+  public void testInvalidate6() throws Exception {
+    doFilter();
+
+    HttpSession session = ((HttpServletRequest) getFilteredRequest()).getSession();
+    session.invalidate();
+
+    try {
+      session.getMaxInactiveInterval();
+    } catch (Exception ex) {
+      fail("Exception should not be thrown");
+    }
+  }
+
+  @Test
+  public void testInvalidate7() throws Exception {
+    doFilter();
+
+    HttpSession session = ((HttpServletRequest) getFilteredRequest()).getSession();
+    session.invalidate();
+
+    try {
+      session.getServletContext();
+    } catch (Exception ex) {
+      fail("Exception should not be thrown");
+    }
+  }
+
+  @Test
+  public void testInvalidate8() throws Exception {
+    doFilter();
+
+    HttpSession session = ((HttpServletRequest) getFilteredRequest()).getSession();
+    session.invalidate();
+
+    try {
+      session.isNew();
+      fail("Session should be invalid and an exception should be thrown");
+    } catch (IllegalStateException iex) {
+      // Pass
+    }
+  }
+
+  @Test
+  public void testInvalidate9() throws Exception {
+    doFilter();
+
+    HttpSession session = ((HttpServletRequest) getFilteredRequest()).getSession();
+    session.invalidate();
+
+    try {
+      session.removeAttribute("foo");
+      fail("Session should be invalid and an exception should be thrown");
+    } catch (IllegalStateException iex) {
+      // Pass
+    }
+  }
+
+  @Test
+  public void testInvalidate10() throws Exception {
+    doFilter();
+
+    HttpSession session = ((HttpServletRequest) getFilteredRequest()).getSession();
+    session.invalidate();
+
+    try {
+      session.setAttribute("foo", "bar");
+      fail("Session should be invalid and an exception should be thrown");
+    } catch (IllegalStateException iex) {
+      // Pass
+    }
+  }
+
+  @Test
+  public void testInvalidate11() throws Exception {
+    doFilter();
+
+    HttpSession session = ((HttpServletRequest) getFilteredRequest()).getSession();
+    session.invalidate();
+
+    try {
+      session.setMaxInactiveInterval(1);
+    } catch (Exception ex) {
+      fail("Exception should not be thrown");
+    }
+  }
+
+  /**
+   * Test that Session Attribute events get triggered
+   */
+  @Test
+  public void testSessionAttributeListener1() throws Exception {
+    AbstractListener listener = new HttpSessionAttributeListenerImpl();
+    RendezvousManager.registerListener(listener);
+    listener.setLatch(3);
+
+    doFilter();
+
+    // Ugh
+    MockHttpSession session = (MockHttpSession) ((GemfireHttpSession) ((HttpServletRequest) getFilteredRequest()).getSession()).getNativeSession();
+    session.addAttributeListener((HttpSessionAttributeListener) listener);
+    session.setAttribute("foo", "bar");
+    session.setAttribute("foo", "baz");
+    session.setAttribute("foo", null);
+
+    assertTrue("Event timeout", listener.await(1, TimeUnit.SECONDS));
+    assertEquals(ListenerEventType.SESSION_ATTRIBUTE_ADDED, listener.getEvents().get(0));
+    assertEquals(ListenerEventType.SESSION_ATTRIBUTE_REPLACED,
+        listener.getEvents().get(1));
+    assertEquals(ListenerEventType.SESSION_ATTRIBUTE_REMOVED,
+        listener.getEvents().get(2));
+  }
+
+  /**
+   * Test that both replace and remove events get triggered
+   */
+  @Test
+  public void testHttpSessionBindingListener1() throws Exception {
+    doFilter();
+
+    HttpSession session =
+        ((HttpServletRequest) getFilteredRequest()).getSession();
+
+    HttpSessionBindingListenerImpl listener1 =
+        new HttpSessionBindingListenerImpl(2);
+    HttpSessionBindingListenerImpl listener2 =
+        new HttpSessionBindingListenerImpl(2);
+
+    session.setAttribute("foo", listener1);
+    session.setAttribute("foo", listener2);
+    session.setAttribute("foo", null);
+
+    assertTrue("Event timeout", listener1.await(1, TimeUnit.SECONDS));
+    assertTrue("Event timeout", listener2.await(1, TimeUnit.SECONDS));
+
+    assertEquals("Event list size incorrect", 2, listener1.getEvents().size());
+    assertEquals("Event list size incorrect", 2, listener2.getEvents().size());
+    assertEquals(ListenerEventType.SESSION_VALUE_BOUND, listener1.getEvents().get(0));
+    assertEquals(ListenerEventType.SESSION_VALUE_UNBOUND,
+        listener1.getEvents().get(1));
+    assertEquals(ListenerEventType.SESSION_VALUE_BOUND, listener2.getEvents().get(0));
+    assertEquals(ListenerEventType.SESSION_VALUE_UNBOUND,
+        listener2.getEvents().get(1));
+  }
+
+  @Test
+  public void testGetId1() throws Exception {
+    doFilter();
+
+    assertNotNull("Session Id should not be null",
+        ((HttpServletRequest) getFilteredRequest()).getSession().getId());
+  }
+
+  /**
+   * Test that multiple calls from the same client return the same session id
+   */
+  @Test
+  public void testGetId2() throws Exception {
+    doFilter();
+
+    String sessionId = ((HttpServletRequest) getFilteredRequest()).getSession().getId();
+
+    MockHttpServletResponse response = getWebMockObjectFactory().getMockResponse();
+    Cookie cookie = (Cookie) response.getCookies().get(0);
+    getWebMockObjectFactory().getMockRequest().addCookie(cookie);
+
+    doFilter();
+
+    assertEquals("Session Ids should be the same", sessionId,
+        ((HttpServletRequest) getFilteredRequest()).getSession().getId());
+  }
+
+  @Test
+  public void testGetCreationTime1() throws Exception {
+    doFilter();
+
+    HttpServletRequest request = (HttpServletRequest) getFilteredRequest();
+    assertTrue("Session should have a non-zero creation time",
+        request.getSession().getCreationTime() > 0);
+  }
+
+
+  /**
+   * Test that multiple calls from the same client don't change the creation time.
+   */
+  @Test
+  public void testGetCreationTime2() throws Exception {
+    doFilter();
+
+    long creationTime = ((HttpServletRequest) getFilteredRequest()).getSession().getCreationTime();
+
+    MockHttpServletResponse response = getWebMockObjectFactory().getMockResponse();
+    Cookie cookie = (Cookie) response.getCookies().get(0);
+    getWebMockObjectFactory().getMockRequest().addCookie(cookie);
+
+    doFilter();
+
+    assertEquals("Session creation time should be the same", creationTime,
+        ((HttpServletRequest) getFilteredRequest()).getSession().getCreationTime());
+  }
+
+  @Test
+  public void testResponseContainsRequestedSessionId1() throws Exception {
+    Cookie cookie = new Cookie("JSESSIONID", "999-GF");
+    getWebMockObjectFactory().getMockRequest().addCookie(cookie);
+
+    doFilter();
+
+    HttpServletRequest request = (HttpServletRequest) getFilteredRequest();
+
+    assertEquals("Request does not contain requested session ID", "999-GF",
+        request.getRequestedSessionId());
+  }
+
+  @Test
+  public void testGetLastAccessedTime1() throws Exception {
+    doFilter();
+
+    HttpServletRequest request = (HttpServletRequest) getFilteredRequest();
+    assertTrue("Session should have a non-zero last access time",
+        request.getSession().getLastAccessedTime() > 0);
+  }
+
+
+  /**
+   * Test that repeated accesses update the last accessed time
+   */
+  @Test
+  public void testGetLastAccessedTime2() throws Exception {
+    // Setup
+    CallbackServlet s = (CallbackServlet) getServlet();
+    s.setCallback(new Callback() {
+
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response) {
+        request.getSession();
+      }
+    });
+
+    doFilter();
+
+    HttpServletRequest request = (HttpServletRequest) getFilteredRequest();
+    long lastAccess = request.getSession().getLastAccessedTime();
+    assertTrue("Session should have a non-zero last access time", lastAccess > 0);
+
+    MockHttpServletResponse response = getWebMockObjectFactory().getMockResponse();
+    Cookie cookie = (Cookie) response.getCookies().get(0);
+
+    MockHttpServletRequest mRequest = getWebMockObjectFactory().createMockRequest();
+    mRequest.setRequestURL("/test/foo/bar");
+    mRequest.setContextPath(CONTEXT_PATH);
+    mRequest.addCookie(cookie);
+    getWebMockObjectFactory().addRequestWrapper(mRequest);
+
+    Thread.sleep(50);
+    doFilter();
+
+    assertTrue("Last access time should be changing",
+        request.getSession().getLastAccessedTime() > lastAccess);
+  }
+
+  @Test
+  public void testGetSetMaxInactiveInterval() throws Exception {
+    doFilter();
+
+    HttpServletRequest request = (HttpServletRequest) getFilteredRequest();
+    request.getSession().setMaxInactiveInterval(50);
+
+    assertEquals(50, request.getSession().getMaxInactiveInterval());
+  }
+
+  @Test
+  public void testIsNew1() throws Exception {
+    doFilter();
+
+    HttpServletRequest request = (HttpServletRequest) getFilteredRequest();
+    assertTrue("Session should be new", request.getSession().isNew());
+  }
+
+  /**
+   * Subsequent calls should not return true
+   */
+  @Test
+  public void testIsNew2() throws Exception {
+    // Setup
+    CallbackServlet s = (CallbackServlet) getServlet();
+    s.setCallback(new Callback() {
+
+      @Override
+      public void call(HttpServletRequest request, HttpServletResponse response) {
+        request.getSession();
+      }
+    });
+
+    doFilter();
+
+    HttpServletRequest request = (HttpServletRequest) getFilteredRequest();
+    request.getSession();
+
+    MockHttpServletResponse response = getWebMockObjectFactory().getMockResponse();
+    Cookie cookie = (Cookie) response.getCookies().get(0);
+
+    MockHttpServletRequest mRequest = getWebMockObjectFactory().createMockRequest();
+    mRequest.setRequestURL("/test/foo/bar");
+    mRequest.setContextPath(CONTEXT_PATH);
+    mRequest.addCookie(cookie);
+    getWebMockObjectFactory().addRequestWrapper(mRequest);
+
+    doFilter();
+
+    request = (HttpServletRequest) getFilteredRequest();
+    HttpSession s1 = request.getSession();
+
+    assertFalse("Subsequent isNew() calls should be false", request.getSession().isNew());
+  }
+
+  @Test
+  public void testIsRequestedSessionIdFromCookie() {
+    MockHttpServletRequest mRequest = getWebMockObjectFactory().getMockRequest();
+    Cookie c = new Cookie("JSESSIONID", "1-GF");
+    mRequest.addCookie(c);
+
+    doFilter();
+    HttpServletRequest request = (HttpServletRequest) getFilteredRequest();
+    request.getSession();
+
+    assertTrue(request.isRequestedSessionIdFromCookie());
+  }
+
+  @Test
+  public void testIsRequestedSessionIdFromURL() {
+    MockHttpServletRequest mRequest = getWebMockObjectFactory().getMockRequest();
+    mRequest.setRequestURL("/foo/bar;jsessionid=1");
+
+    doFilter();
+    HttpServletRequest request = (HttpServletRequest) getFilteredRequest();
+    request.getSession();
+
+    assertFalse("Session ID should not be from cookie",
+        request.isRequestedSessionIdFromCookie());
+    assertTrue("Session ID should be from URL", request.isRequestedSessionIdFromURL());
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/HttpSessionAttributeListenerImpl.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/HttpSessionAttributeListenerImpl.java b/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/HttpSessionAttributeListenerImpl.java
new file mode 100644
index 0000000..6d5679a
--- /dev/null
+++ b/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/HttpSessionAttributeListenerImpl.java
@@ -0,0 +1,46 @@
+/*
+* 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.internal.filter;
+
+import javax.servlet.http.HttpSessionAttributeListener;
+import javax.servlet.http.HttpSessionBindingEvent;
+
+/**
+ *
+ */
+public class HttpSessionAttributeListenerImpl extends AbstractListener
+    implements HttpSessionAttributeListener {
+
+  @Override
+  public synchronized void attributeAdded(HttpSessionBindingEvent se) {
+    events.add(ListenerEventType.SESSION_ATTRIBUTE_ADDED);
+    latch.countDown();
+  }
+
+  @Override
+  public synchronized void attributeRemoved(HttpSessionBindingEvent se) {
+    events.add(ListenerEventType.SESSION_ATTRIBUTE_REMOVED);
+    latch.countDown();
+  }
+
+  @Override
+  public synchronized void attributeReplaced(HttpSessionBindingEvent se) {
+    events.add(ListenerEventType.SESSION_ATTRIBUTE_REPLACED);
+    latch.countDown();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/HttpSessionBindingListenerImpl.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/HttpSessionBindingListenerImpl.java b/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/HttpSessionBindingListenerImpl.java
new file mode 100644
index 0000000..ce25cb6
--- /dev/null
+++ b/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/HttpSessionBindingListenerImpl.java
@@ -0,0 +1,42 @@
+/*
+* 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.internal.filter;
+
+import java.io.Serializable;
+import javax.servlet.http.HttpSessionBindingEvent;
+import javax.servlet.http.HttpSessionBindingListener;
+
+public class HttpSessionBindingListenerImpl extends AbstractListener implements
+    HttpSessionBindingListener, Serializable {
+
+  public HttpSessionBindingListenerImpl(int i) {
+    super(i);
+  }
+
+  @Override
+  public synchronized void valueBound(HttpSessionBindingEvent event) {
+    events.add(ListenerEventType.SESSION_VALUE_BOUND);
+    latch.countDown();
+  }
+
+  @Override
+  public synchronized void valueUnbound(HttpSessionBindingEvent event) {
+    events.add(ListenerEventType.SESSION_VALUE_UNBOUND);
+    latch.countDown();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/HttpSessionListenerImpl.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/HttpSessionListenerImpl.java b/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/HttpSessionListenerImpl.java
new file mode 100644
index 0000000..55510a6
--- /dev/null
+++ b/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/HttpSessionListenerImpl.java
@@ -0,0 +1,41 @@
+/*
+* 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.internal.filter;
+
+import com.gemstone.gemfire.modules.session.filter.SessionCachingFilter;
+
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.HttpSessionEvent;
+import javax.servlet.http.HttpSessionListener;
+
+public class HttpSessionListenerImpl extends AbstractListener
+    implements HttpSessionListener {
+
+  public synchronized void sessionCreated(HttpSessionEvent se) {
+    HttpSession gfeSession = SessionCachingFilter.getWrappingSession(
+        se.getSession());
+    gfeSession.setAttribute("gemfire-session-id", gfeSession.getId());
+    events.add(ListenerEventType.SESSION_CREATED);
+    latch.countDown();
+  }
+
+  public synchronized void sessionDestroyed(HttpSessionEvent se) {
+    events.add(ListenerEventType.SESSION_DESTROYED);
+    latch.countDown();
+  }
+}

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

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/MyServletTester.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/MyServletTester.java b/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/MyServletTester.java
new file mode 100644
index 0000000..09c9536
--- /dev/null
+++ b/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/MyServletTester.java
@@ -0,0 +1,38 @@
+/*
+* 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.internal.filter;
+
+import org.eclipse.jetty.servlet.ServletTester;
+
+/**
+ * Extend the base ServletTester class with a couple of helper methods. This
+ * depends on a patched ServletTester class which exposes the _server variable
+ * as package-private.
+ */
+public class MyServletTester extends ServletTester {
+
+  public boolean isStarted() {
+//    return _server.isStarted();
+    return false;
+  }
+
+  public boolean isStopped() {
+//    return _server.isStopped();
+    return false;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/RendezvousManager.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/RendezvousManager.java b/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/RendezvousManager.java
new file mode 100644
index 0000000..acb5a1b
--- /dev/null
+++ b/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/RendezvousManager.java
@@ -0,0 +1,46 @@
+/*
+* 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.internal.filter;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ *
+ */
+public class RendezvousManager {
+
+  private static AbstractListener listener = null;
+
+  private static CountDownLatch latch = new CountDownLatch(1);
+
+  public static void registerListener(AbstractListener listener) {
+    RendezvousManager.listener = listener;
+    latch.countDown();
+  }
+
+  public static AbstractListener getListener() {
+    try {
+      latch.await(2, TimeUnit.SECONDS);
+    } catch (InterruptedException ex) {
+    }
+
+    return listener;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/ServletRequestAttributeListenerImpl.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/ServletRequestAttributeListenerImpl.java b/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/ServletRequestAttributeListenerImpl.java
new file mode 100644
index 0000000..ab06356
--- /dev/null
+++ b/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/ServletRequestAttributeListenerImpl.java
@@ -0,0 +1,45 @@
+/*
+* 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.internal.filter;
+
+import javax.servlet.ServletRequestAttributeEvent;
+import javax.servlet.ServletRequestAttributeListener;
+
+/**
+ * @author jdeppe
+ */
+public class ServletRequestAttributeListenerImpl extends AbstractListener
+    implements ServletRequestAttributeListener {
+
+  public synchronized void attributeAdded(ServletRequestAttributeEvent srae) {
+    events.add(ListenerEventType.SERVLET_REQUEST_ATTRIBUTE_ADDED);
+    latch.countDown();
+  }
+
+  public synchronized void attributeRemoved(ServletRequestAttributeEvent srae) {
+    events.add(ListenerEventType.SERVLET_REQUEST_ATTRIBUTE_REMOVED);
+    latch.countDown();
+  }
+
+  public synchronized void attributeReplaced(
+      ServletRequestAttributeEvent srae) {
+    events.add(ListenerEventType.SERVLET_REQUEST_ATTRIBUTE_REPLACED);
+    latch.countDown();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/ServletRequestListenerImpl.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/ServletRequestListenerImpl.java b/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/ServletRequestListenerImpl.java
new file mode 100644
index 0000000..5e007dd
--- /dev/null
+++ b/extensions/gemfire-modules-session/src/test/java/com/gemstone/gemfire/modules/session/internal/filter/ServletRequestListenerImpl.java
@@ -0,0 +1,36 @@
+/*
+* 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.internal.filter;
+
+import javax.servlet.ServletRequestEvent;
+import javax.servlet.ServletRequestListener;
+
+public class ServletRequestListenerImpl extends AbstractListener
+    implements ServletRequestListener {
+
+  public synchronized void requestDestroyed(ServletRequestEvent sre) {
+    events.add(ListenerEventType.SERVLET_REQUEST_DESTROYED);
+    latch.countDown();
+  }
+
+  public synchronized void requestInitialized(ServletRequestEvent sre) {
+    events.add(ListenerEventType.SERVLET_REQUEST_INITIALIZED);
+    latch.countDown();
+  }
+
+}