This is an automated email from the ASF dual-hosted git repository.

bross pushed a commit to branch support/1.12
in repository https://gitbox.apache.org/repos/asf/geode.git

commit 64687d7c7d02e4dc082e0b2e1c312fb8ee26850a
Author: Jacob Barrett <jbarr...@pivotal.io>
AuthorDate: Fri Jun 19 10:38:46 2020 -0700

    GEODE-8221: Commits session data prior to sending output to browser (#5246)
    
    * Refactors abstraction of CommitSessionValve.
    * Wraps Coyote OutputBuffer to commit sessions when data is sent to client.
    
    (cherry picked from commit 9939cc0f2f1caad051bd104a0a06a4e1737d3830)
---
 ...AbstractCommitSessionValveIntegrationTest.java} | 42 +++++-----
 .../AbstractSessionValveIntegrationTest.java       |  0
 .../CommitSessionValveIntegrationTest.java         | 57 +++++++++++++
 .../catalina/Tomcat7CommitSessionOutputBuffer.java | 53 ++++++++++++
 .../catalina/Tomcat7CommitSessionValve.java        | 58 +++++++++++++
 .../catalina/Tomcat7DeltaSessionManager.java       | 12 ++-
 .../Tomcat7CommitSessionOutputBufferTest.java      | 63 ++++++++++++++
 .../catalina/Tomcat7CommitSessionValveTest.java    | 98 ++++++++++++++++++++++
 .../CommitSessionValveIntegrationTest.java         | 57 +++++++++++++
 .../modules/session/catalina/DeltaSession8.java    |  1 +
 .../catalina/Tomcat8CommitSessionOutputBuffer.java | 60 +++++++++++++
 .../catalina/Tomcat8CommitSessionValve.java        | 59 +++++++++++++
 .../catalina/Tomcat8DeltaSessionManager.java       |  8 +-
 .../Tomcat8CommitSessionOutputBufferTest.java      | 77 +++++++++++++++++
 .../catalina/Tomcat8CommitSessionValveTest.java    | 98 ++++++++++++++++++++++
 .../CommitSessionValveIntegrationTest.java         | 52 ++++++++++++
 .../catalina/Tomcat9CommitSessionOutputBuffer.java | 53 ++++++++++++
 .../catalina/Tomcat9CommitSessionValve.java        | 58 +++++++++++++
 .../catalina/Tomcat9DeltaSessionManager.java       |  7 +-
 .../Tomcat9CommitSessionOutputBufferTest.java      | 60 +++++++++++++
 .../catalina/Tomcat9CommitSessionValveTest.java    | 94 +++++++++++++++++++++
 .../catalina/AbstractCommitSessionValve.java       | 82 ++++++++++++++++++
 .../session/catalina/CommitSessionValve.java       | 69 ---------------
 .../session/catalina/DeltaSessionManager.java      |  9 +-
 .../session/catalina/SessionCommitter.java}        | 26 ++----
 .../catalina/Tomcat6CommitSessionValve.java}       | 26 ++----
 .../catalina/Tomcat6DeltaSessionManager.java       |  7 +-
 .../integrationTest/resources/assembly_content.txt |  6 +-
 28 files changed, 1153 insertions(+), 139 deletions(-)

diff --git 
a/extensions/geode-modules/src/integrationTest/java/org/apache/geode/modules/session/catalina/CommitSessionValveIntegrationTest.java
 
b/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/AbstractCommitSessionValveIntegrationTest.java
similarity index 83%
rename from 
extensions/geode-modules/src/integrationTest/java/org/apache/geode/modules/session/catalina/CommitSessionValveIntegrationTest.java
rename to 
extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/AbstractCommitSessionValveIntegrationTest.java
index c7e056e..7849d99 100644
--- 
a/extensions/geode-modules/src/integrationTest/java/org/apache/geode/modules/session/catalina/CommitSessionValveIntegrationTest.java
+++ 
b/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/AbstractCommitSessionValveIntegrationTest.java
@@ -19,7 +19,6 @@ import static 
org.assertj.core.api.Assertions.assertThatThrownBy;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -35,35 +34,34 @@ import org.apache.catalina.Manager;
 import org.apache.catalina.connector.Request;
 import org.apache.catalina.connector.Response;
 import org.apache.juli.logging.Log;
-import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 import org.apache.geode.cache.RegionShortcut;
 
 @RunWith(JUnitParamsRunner.class)
-public class CommitSessionValveIntegrationTest extends 
AbstractSessionValveIntegrationTest {
-  private Request request;
-  private Response response;
-  private TestValve testValve;
-  private CommitSessionValve commitSessionValve;
-  private DeltaSessionFacade deltaSessionFacade;
-
-  @Before
-  public void setUp() {
-    request = spy(Request.class);
-    response = spy(Response.class);
+public abstract class 
AbstractCommitSessionValveIntegrationTest<CommitSessionValveT extends 
AbstractCommitSessionValve<CommitSessionValveT>>
+    extends AbstractSessionValveIntegrationTest {
+  protected Request request;
+  protected Response response;
+  protected final TestValve testValve;
+  protected final CommitSessionValveT commitSessionValve;
+  protected DeltaSessionFacade deltaSessionFacade;
+
+  public AbstractCommitSessionValveIntegrationTest() {
     testValve = new TestValve(false);
 
-    commitSessionValve = new CommitSessionValve();
+    commitSessionValve = createCommitSessionValve();
     commitSessionValve.setNext(testValve);
   }
 
-  protected void parameterizedSetUp(RegionShortcut regionShortcut) {
+  protected abstract CommitSessionValveT createCommitSessionValve();
+
+  @Override
+  protected void parameterizedSetUp(final RegionShortcut regionShortcut) {
     super.parameterizedSetUp(regionShortcut);
 
     deltaSessionFacade = new DeltaSessionFacade(deltaSession);
-    when(request.getContext()).thenReturn(mock(Context.class));
 
     // Valve use the context to log messages
     when(deltaSessionManager.getTheContext()).thenReturn(mock(Context.class));
@@ -73,7 +71,7 @@ public class CommitSessionValveIntegrationTest extends 
AbstractSessionValveInteg
   @Test
   @Parameters({"REPLICATE", "PARTITION"})
   public void 
invokeShouldCallNextChainedValveAndDoNothingWhenSessionManagerDoesNotBelongToGeode(
-      RegionShortcut regionShortcut) throws IOException, ServletException {
+      final RegionShortcut regionShortcut) throws IOException, 
ServletException {
     parameterizedSetUp(regionShortcut);
     when(request.getContext().getManager()).thenReturn(mock(Manager.class));
 
@@ -85,7 +83,7 @@ public class CommitSessionValveIntegrationTest extends 
AbstractSessionValveInteg
   @Test
   @Parameters({"REPLICATE", "PARTITION"})
   public void 
invokeShouldCallNextChainedValveAndDoNothingWhenSessionManagerBelongsToGeodeButSessionDoesNotExist(
-      RegionShortcut regionShortcut) throws IOException, ServletException {
+      final RegionShortcut regionShortcut) throws IOException, 
ServletException {
     parameterizedSetUp(regionShortcut);
     doReturn(null).when(request).getSession(false);
     when(request.getContext().getManager()).thenReturn(deltaSessionManager);
@@ -99,7 +97,7 @@ public class CommitSessionValveIntegrationTest extends 
AbstractSessionValveInteg
   @Test
   @Parameters({"REPLICATE", "PARTITION"})
   public void 
invokeShouldCallNextChainedValveAndDoNothingWhenSessionManagerBelongsToGeodeAndSessionExistsButIsNotValid(
-      RegionShortcut regionShortcut) throws IOException, ServletException {
+      final RegionShortcut regionShortcut) throws IOException, 
ServletException {
     parameterizedSetUp(regionShortcut);
     doReturn(false).when(deltaSession).isValid();
     doReturn(deltaSessionFacade).when(request).getSession(false);
@@ -114,7 +112,7 @@ public class CommitSessionValveIntegrationTest extends 
AbstractSessionValveInteg
   @Test
   @Parameters({"REPLICATE", "PARTITION"})
   public void 
invokeShouldCallNextChainedValveAndCommitTheExistingValidSessionWhenSessionManagerBelongsToGeode(
-      RegionShortcut regionShortcut) throws IOException, ServletException {
+      final RegionShortcut regionShortcut) throws IOException, 
ServletException {
     parameterizedSetUp(regionShortcut);
     deltaSessionManager.addSessionToTouch(TEST_SESSION_ID);
     doReturn(deltaSessionFacade).when(request).getSession(false);
@@ -129,9 +127,9 @@ public class CommitSessionValveIntegrationTest extends 
AbstractSessionValveInteg
   @Test
   @Parameters({"REPLICATE", "PARTITION"})
   public void 
invokeShouldCommitTheExistingValidSessionWhenSessionManagerBelongsToGeodeEvenWhenTheNextChainedValveThrowsAnException(
-      RegionShortcut regionShortcut) {
+      final RegionShortcut regionShortcut) {
     parameterizedSetUp(regionShortcut);
-    TestValve exceptionValve = new TestValve(true);
+    final TestValve exceptionValve = new TestValve(true);
     commitSessionValve.setNext(exceptionValve);
     deltaSessionManager.addSessionToTouch(TEST_SESSION_ID);
     doReturn(deltaSessionFacade).when(request).getSession(false);
diff --git 
a/extensions/geode-modules/src/integrationTest/java/org/apache/geode/modules/session/catalina/AbstractSessionValveIntegrationTest.java
 
b/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/AbstractSessionValveIntegrationTest.java
similarity index 100%
rename from 
extensions/geode-modules/src/integrationTest/java/org/apache/geode/modules/session/catalina/AbstractSessionValveIntegrationTest.java
rename to 
extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/catalina/AbstractSessionValveIntegrationTest.java
diff --git 
a/extensions/geode-modules-tomcat7/src/integrationTest/java/org/apache/geode/modules/session/catalina/CommitSessionValveIntegrationTest.java
 
b/extensions/geode-modules-tomcat7/src/integrationTest/java/org/apache/geode/modules/session/catalina/CommitSessionValveIntegrationTest.java
new file mode 100644
index 0000000..b64e862
--- /dev/null
+++ 
b/extensions/geode-modules-tomcat7/src/integrationTest/java/org/apache/geode/modules/session/catalina/CommitSessionValveIntegrationTest.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 org.apache.geode.modules.session.catalina;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.connector.Connector;
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.connector.Response;
+import org.apache.coyote.OutputBuffer;
+import org.apache.juli.logging.Log;
+import org.junit.Before;
+
+public class CommitSessionValveIntegrationTest
+    extends 
AbstractCommitSessionValveIntegrationTest<Tomcat7CommitSessionValve> {
+
+  @Before
+  public void setUp() {
+    final Context context = mock(Context.class);
+    doReturn(mock(Log.class)).when(context).getLogger();
+
+    request = mock(Request.class);
+    doReturn(context).when(request).getContext();
+
+    final OutputBuffer outputBuffer = mock(OutputBuffer.class);
+
+    final org.apache.coyote.Response coyoteResponse = new 
org.apache.coyote.Response();
+    coyoteResponse.setOutputBuffer(outputBuffer);
+
+    response = new Response();
+    response.setConnector(mock(Connector.class));
+    response.setRequest(request);
+    response.setCoyoteResponse(coyoteResponse);
+  }
+
+
+  @Override
+  protected Tomcat7CommitSessionValve createCommitSessionValve() {
+    return new Tomcat7CommitSessionValve();
+  }
+
+}
diff --git 
a/extensions/geode-modules-tomcat7/src/main/java/org/apache/geode/modules/session/catalina/Tomcat7CommitSessionOutputBuffer.java
 
b/extensions/geode-modules-tomcat7/src/main/java/org/apache/geode/modules/session/catalina/Tomcat7CommitSessionOutputBuffer.java
new file mode 100644
index 0000000..fcf01b2
--- /dev/null
+++ 
b/extensions/geode-modules-tomcat7/src/main/java/org/apache/geode/modules/session/catalina/Tomcat7CommitSessionOutputBuffer.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license
+ * agreements. See the NOTICE file distributed with this work for additional 
information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache 
License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the 
License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software 
distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
KIND, either express
+ * or implied. See the License for the specific language governing permissions 
and limitations under
+ * the License.
+ */
+
+package org.apache.geode.modules.session.catalina;
+
+import java.io.IOException;
+
+import org.apache.coyote.OutputBuffer;
+import org.apache.coyote.Response;
+import org.apache.tomcat.util.buf.ByteChunk;
+
+/**
+ * Delegating {@link OutputBuffer} that commits sessions on write through. 
Output data is buffered
+ * ahead of this object and flushed through this interface when full or 
explicitly flushed.
+ */
+class Tomcat7CommitSessionOutputBuffer implements OutputBuffer {
+
+  private final SessionCommitter sessionCommitter;
+  private final OutputBuffer delegate;
+
+  public Tomcat7CommitSessionOutputBuffer(final SessionCommitter 
sessionCommitter,
+      final OutputBuffer delegate) {
+    this.sessionCommitter = sessionCommitter;
+    this.delegate = delegate;
+  }
+
+  @Override
+  public int doWrite(final ByteChunk chunk, final Response response) throws 
IOException {
+    sessionCommitter.commit();
+    return delegate.doWrite(chunk, response);
+  }
+
+  @Override
+  public long getBytesWritten() {
+    return delegate.getBytesWritten();
+  }
+
+  OutputBuffer getDelegate() {
+    return delegate;
+  }
+}
diff --git 
a/extensions/geode-modules-tomcat7/src/main/java/org/apache/geode/modules/session/catalina/Tomcat7CommitSessionValve.java
 
b/extensions/geode-modules-tomcat7/src/main/java/org/apache/geode/modules/session/catalina/Tomcat7CommitSessionValve.java
new file mode 100644
index 0000000..f6a4839
--- /dev/null
+++ 
b/extensions/geode-modules-tomcat7/src/main/java/org/apache/geode/modules/session/catalina/Tomcat7CommitSessionValve.java
@@ -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.
+ */
+
+package org.apache.geode.modules.session.catalina;
+
+import java.lang.reflect.Field;
+
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.connector.Response;
+import org.apache.coyote.OutputBuffer;
+
+public class Tomcat7CommitSessionValve
+    extends AbstractCommitSessionValve<Tomcat7CommitSessionValve> {
+
+  private static final Field outputBufferField;
+
+  static {
+    try {
+      outputBufferField = 
org.apache.coyote.Response.class.getDeclaredField("outputBuffer");
+      outputBufferField.setAccessible(true);
+    } catch (final NoSuchFieldException e) {
+      throw new IllegalStateException(e);
+    }
+  }
+
+  @Override
+  Response wrapResponse(final Response response) {
+    final org.apache.coyote.Response coyoteResponse = 
response.getCoyoteResponse();
+    final OutputBuffer delegateOutputBuffer = getOutputBuffer(coyoteResponse);
+    if (!(delegateOutputBuffer instanceof Tomcat7CommitSessionOutputBuffer)) {
+      final Request request = response.getRequest();
+      final OutputBuffer sessionCommitOutputBuffer =
+          new Tomcat7CommitSessionOutputBuffer(() -> commitSession(request), 
delegateOutputBuffer);
+      coyoteResponse.setOutputBuffer(sessionCommitOutputBuffer);
+    }
+    return response;
+  }
+
+  static OutputBuffer getOutputBuffer(final org.apache.coyote.Response 
coyoteResponse) {
+    try {
+      return (OutputBuffer) outputBufferField.get(coyoteResponse);
+    } catch (final IllegalAccessException e) {
+      throw new IllegalStateException(e);
+    }
+  }
+}
diff --git 
a/extensions/geode-modules-tomcat7/src/main/java/org/apache/geode/modules/session/catalina/Tomcat7DeltaSessionManager.java
 
b/extensions/geode-modules-tomcat7/src/main/java/org/apache/geode/modules/session/catalina/Tomcat7DeltaSessionManager.java
index e965cc5..b6d304a 100644
--- 
a/extensions/geode-modules-tomcat7/src/main/java/org/apache/geode/modules/session/catalina/Tomcat7DeltaSessionManager.java
+++ 
b/extensions/geode-modules-tomcat7/src/main/java/org/apache/geode/modules/session/catalina/Tomcat7DeltaSessionManager.java
@@ -20,14 +20,15 @@ import org.apache.catalina.LifecycleException;
 import org.apache.catalina.LifecycleListener;
 import org.apache.catalina.LifecycleState;
 import org.apache.catalina.session.StandardSession;
-import org.apache.catalina.util.LifecycleSupport;
 
-public class Tomcat7DeltaSessionManager extends DeltaSessionManager {
+public class Tomcat7DeltaSessionManager extends 
DeltaSessionManager<Tomcat7CommitSessionValve> {
 
   /**
    * The <code>LifecycleSupport</code> for this component.
    */
-  protected LifecycleSupport lifecycle = new LifecycleSupport(this);
+  @SuppressWarnings("deprecation")
+  protected org.apache.catalina.util.LifecycleSupport lifecycle =
+      new org.apache.catalina.util.LifecycleSupport(this);
 
   /**
    * Prepare for the beginning of active use of the public methods of this 
component. This method
@@ -165,4 +166,9 @@ public class Tomcat7DeltaSessionManager extends 
DeltaSessionManager {
     return new DeltaSession7(this);
   }
 
+  @Override
+  protected Tomcat7CommitSessionValve createCommitSessionValve() {
+    return new Tomcat7CommitSessionValve();
+  }
+
 }
diff --git 
a/extensions/geode-modules-tomcat7/src/test/java/org/apache/geode/modules/session/catalina/Tomcat7CommitSessionOutputBufferTest.java
 
b/extensions/geode-modules-tomcat7/src/test/java/org/apache/geode/modules/session/catalina/Tomcat7CommitSessionOutputBufferTest.java
new file mode 100644
index 0000000..20facaf
--- /dev/null
+++ 
b/extensions/geode-modules-tomcat7/src/test/java/org/apache/geode/modules/session/catalina/Tomcat7CommitSessionOutputBufferTest.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license
+ * agreements. See the NOTICE file distributed with this work for additional 
information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache 
License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the 
License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software 
distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
KIND, either express
+ * or implied. See the License for the specific language governing permissions 
and limitations under
+ * the License.
+ */
+
+package org.apache.geode.modules.session.catalina;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+
+import org.apache.coyote.OutputBuffer;
+import org.apache.coyote.Response;
+import org.apache.tomcat.util.buf.ByteChunk;
+import org.junit.Test;
+import org.mockito.InOrder;
+
+public class Tomcat7CommitSessionOutputBufferTest {
+
+  final SessionCommitter sessionCommitter = mock(SessionCommitter.class);
+  final OutputBuffer delegate = mock(OutputBuffer.class);
+
+  final Tomcat7CommitSessionOutputBuffer commitSesssionOutputBuffer =
+      new Tomcat7CommitSessionOutputBuffer(sessionCommitter, delegate);
+
+  @Test
+  public void doWrite() throws IOException {
+    final ByteChunk byteChunk = new ByteChunk();
+    final Response response = new Response();
+
+    commitSesssionOutputBuffer.doWrite(byteChunk, response);
+
+    final InOrder inOrder = inOrder(sessionCommitter, delegate);
+    inOrder.verify(sessionCommitter).commit();
+    inOrder.verify(delegate).doWrite(byteChunk, response);
+    inOrder.verifyNoMoreInteractions();
+  }
+
+
+  @Test
+  public void getBytesWritten() {
+    when(delegate.getBytesWritten()).thenReturn(42L);
+
+    assertThat(commitSesssionOutputBuffer.getBytesWritten()).isEqualTo(42L);
+
+    final InOrder inOrder = inOrder(sessionCommitter, delegate);
+    inOrder.verify(delegate).getBytesWritten();
+    inOrder.verifyNoMoreInteractions();
+  }
+}
diff --git 
a/extensions/geode-modules-tomcat7/src/test/java/org/apache/geode/modules/session/catalina/Tomcat7CommitSessionValveTest.java
 
b/extensions/geode-modules-tomcat7/src/test/java/org/apache/geode/modules/session/catalina/Tomcat7CommitSessionValveTest.java
new file mode 100644
index 0000000..c9be9b2
--- /dev/null
+++ 
b/extensions/geode-modules-tomcat7/src/test/java/org/apache/geode/modules/session/catalina/Tomcat7CommitSessionValveTest.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license
+ * agreements. See the NOTICE file distributed with this work for additional 
information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache 
License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the 
License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software 
distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
KIND, either express
+ * or implied. See the License for the specific language governing permissions 
and limitations under
+ * the License.
+ */
+
+package org.apache.geode.modules.session.catalina;
+
+import static 
org.apache.geode.modules.session.catalina.Tomcat7CommitSessionValve.getOutputBuffer;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.connector.Connector;
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.connector.Response;
+import org.apache.coyote.OutputBuffer;
+import org.apache.tomcat.util.buf.ByteChunk;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
+
+
+public class Tomcat7CommitSessionValveTest {
+
+  private final Tomcat7CommitSessionValve valve = new 
Tomcat7CommitSessionValve();
+  private final OutputBuffer outputBuffer = mock(OutputBuffer.class);
+  private Response response;
+  private org.apache.coyote.Response coyoteResponse;
+
+  @Before
+  public void before() {
+    final Connector connector = mock(Connector.class);
+
+    final Context context = mock(Context.class);
+
+    final Request request = mock(Request.class);
+    doReturn(context).when(request).getContext();
+
+    coyoteResponse = new org.apache.coyote.Response();
+    coyoteResponse.setOutputBuffer(outputBuffer);
+
+    response = new Response();
+    response.setConnector(connector);
+    response.setRequest(request);
+    response.setCoyoteResponse(coyoteResponse);
+  }
+
+  @Test
+  public void wrappedOutputBufferForwardsToDelegate() throws IOException {
+    wrappedOutputBufferForwardsToDelegate(new byte[] {'a', 'b', 'c'});
+  }
+
+  @Test
+  public void recycledResponseObjectDoesNotWrapAlreadyWrappedOutputBuffer() 
throws IOException {
+    wrappedOutputBufferForwardsToDelegate(new byte[] {'a', 'b', 'c'});
+    response.recycle();
+    reset(outputBuffer);
+    wrappedOutputBufferForwardsToDelegate(new byte[] {'d', 'e', 'f'});
+  }
+
+  private void wrappedOutputBufferForwardsToDelegate(final byte[] bytes) 
throws IOException {
+    final OutputStream outputStream =
+        valve.wrapResponse(response).getResponse().getOutputStream();
+    outputStream.write(bytes);
+    outputStream.flush();
+
+    final ArgumentCaptor<ByteChunk> byteChunk = 
ArgumentCaptor.forClass(ByteChunk.class);
+
+    final InOrder inOrder = inOrder(outputBuffer);
+    inOrder.verify(outputBuffer).doWrite(byteChunk.capture(), any());
+    inOrder.verifyNoMoreInteractions();
+
+    final OutputBuffer wrappedOutputBuffer = getOutputBuffer(coyoteResponse);
+    
assertThat(wrappedOutputBuffer).isInstanceOf(Tomcat7CommitSessionOutputBuffer.class);
+    assertThat(((Tomcat7CommitSessionOutputBuffer) 
wrappedOutputBuffer).getDelegate())
+        .isNotInstanceOf(Tomcat7CommitSessionOutputBuffer.class);
+
+    assertThat(byteChunk.getValue().getBytes()).contains(bytes);
+  }
+}
diff --git 
a/extensions/geode-modules-tomcat8/src/integrationTest/java/org/apache/geode/modules/session/catalina/CommitSessionValveIntegrationTest.java
 
b/extensions/geode-modules-tomcat8/src/integrationTest/java/org/apache/geode/modules/session/catalina/CommitSessionValveIntegrationTest.java
new file mode 100644
index 0000000..79df936
--- /dev/null
+++ 
b/extensions/geode-modules-tomcat8/src/integrationTest/java/org/apache/geode/modules/session/catalina/CommitSessionValveIntegrationTest.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 org.apache.geode.modules.session.catalina;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.connector.Connector;
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.connector.Response;
+import org.apache.coyote.OutputBuffer;
+import org.apache.juli.logging.Log;
+import org.junit.Before;
+
+public class CommitSessionValveIntegrationTest
+    extends 
AbstractCommitSessionValveIntegrationTest<Tomcat8CommitSessionValve> {
+
+  @Before
+  public void setUp() {
+    final Context context = mock(Context.class);
+    doReturn(mock(Log.class)).when(context).getLogger();
+
+    request = mock(Request.class);
+    doReturn(context).when(request).getContext();
+
+    final OutputBuffer outputBuffer = mock(OutputBuffer.class);
+
+    final org.apache.coyote.Response coyoteResponse = new 
org.apache.coyote.Response();
+    coyoteResponse.setOutputBuffer(outputBuffer);
+
+    response = new Response();
+    response.setConnector(mock(Connector.class));
+    response.setRequest(request);
+    response.setCoyoteResponse(coyoteResponse);
+  }
+
+
+  @Override
+  protected Tomcat8CommitSessionValve createCommitSessionValve() {
+    return new Tomcat8CommitSessionValve();
+  }
+
+}
diff --git 
a/extensions/geode-modules-tomcat8/src/main/java/org/apache/geode/modules/session/catalina/DeltaSession8.java
 
b/extensions/geode-modules-tomcat8/src/main/java/org/apache/geode/modules/session/catalina/DeltaSession8.java
index a17fdde..c2ea5c5 100644
--- 
a/extensions/geode-modules-tomcat8/src/main/java/org/apache/geode/modules/session/catalina/DeltaSession8.java
+++ 
b/extensions/geode-modules-tomcat8/src/main/java/org/apache/geode/modules/session/catalina/DeltaSession8.java
@@ -12,6 +12,7 @@
  * or implied. See the License for the specific language governing permissions 
and limitations under
  * the License.
  */
+
 package org.apache.geode.modules.session.catalina;
 
 import org.apache.catalina.Manager;
diff --git 
a/extensions/geode-modules-tomcat8/src/main/java/org/apache/geode/modules/session/catalina/Tomcat8CommitSessionOutputBuffer.java
 
b/extensions/geode-modules-tomcat8/src/main/java/org/apache/geode/modules/session/catalina/Tomcat8CommitSessionOutputBuffer.java
new file mode 100644
index 0000000..4197b59
--- /dev/null
+++ 
b/extensions/geode-modules-tomcat8/src/main/java/org/apache/geode/modules/session/catalina/Tomcat8CommitSessionOutputBuffer.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license
+ * agreements. See the NOTICE file distributed with this work for additional 
information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache 
License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the 
License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software 
distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
KIND, either express
+ * or implied. See the License for the specific language governing permissions 
and limitations under
+ * the License.
+ */
+
+package org.apache.geode.modules.session.catalina;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+import org.apache.coyote.OutputBuffer;
+import org.apache.tomcat.util.buf.ByteChunk;
+
+/**
+ * Delegating {@link OutputBuffer} that commits sessions on write through. 
Output data is buffered
+ * ahead of this object and flushed through this interface when full or 
explicitly flushed.
+ */
+class Tomcat8CommitSessionOutputBuffer implements OutputBuffer {
+
+  private final SessionCommitter sessionCommitter;
+  private final OutputBuffer delegate;
+
+  public Tomcat8CommitSessionOutputBuffer(final SessionCommitter 
sessionCommitter,
+      final OutputBuffer delegate) {
+    this.sessionCommitter = sessionCommitter;
+    this.delegate = delegate;
+  }
+
+  @Deprecated
+  @Override
+  public int doWrite(final ByteChunk chunk) throws IOException {
+    sessionCommitter.commit();
+    return delegate.doWrite(chunk);
+  }
+
+  @Override
+  public int doWrite(final ByteBuffer chunk) throws IOException {
+    sessionCommitter.commit();
+    return delegate.doWrite(chunk);
+  }
+
+  @Override
+  public long getBytesWritten() {
+    return delegate.getBytesWritten();
+  }
+
+  OutputBuffer getDelegate() {
+    return delegate;
+  }
+}
diff --git 
a/extensions/geode-modules-tomcat8/src/main/java/org/apache/geode/modules/session/catalina/Tomcat8CommitSessionValve.java
 
b/extensions/geode-modules-tomcat8/src/main/java/org/apache/geode/modules/session/catalina/Tomcat8CommitSessionValve.java
new file mode 100644
index 0000000..fe5f65a
--- /dev/null
+++ 
b/extensions/geode-modules-tomcat8/src/main/java/org/apache/geode/modules/session/catalina/Tomcat8CommitSessionValve.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license
+ * agreements. See the NOTICE file distributed with this work for additional 
information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache 
License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the 
License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software 
distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
KIND, either express
+ * or implied. See the License for the specific language governing permissions 
and limitations under
+ * the License.
+ */
+
+package org.apache.geode.modules.session.catalina;
+
+import java.lang.reflect.Field;
+
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.connector.Response;
+import org.apache.coyote.OutputBuffer;
+
+public class Tomcat8CommitSessionValve
+    extends AbstractCommitSessionValve<Tomcat8CommitSessionValve> {
+
+  private static final Field outputBufferField;
+
+  static {
+    try {
+      outputBufferField = 
org.apache.coyote.Response.class.getDeclaredField("outputBuffer");
+      outputBufferField.setAccessible(true);
+    } catch (final NoSuchFieldException e) {
+      throw new IllegalStateException(e);
+    }
+  }
+
+  @Override
+  Response wrapResponse(final Response response) {
+    final org.apache.coyote.Response coyoteResponse = 
response.getCoyoteResponse();
+    final OutputBuffer delegateOutputBuffer = getOutputBuffer(coyoteResponse);
+    if (!(delegateOutputBuffer instanceof Tomcat8CommitSessionOutputBuffer)) {
+      final Request request = response.getRequest();
+      final OutputBuffer sessionCommitOutputBuffer =
+          new Tomcat8CommitSessionOutputBuffer(() -> commitSession(request), 
delegateOutputBuffer);
+      coyoteResponse.setOutputBuffer(sessionCommitOutputBuffer);
+    }
+    return response;
+  }
+
+  static OutputBuffer getOutputBuffer(final org.apache.coyote.Response 
coyoteResponse) {
+    try {
+      return (OutputBuffer) outputBufferField.get(coyoteResponse);
+    } catch (final IllegalAccessException e) {
+      throw new IllegalStateException(e);
+    }
+  }
+
+}
diff --git 
a/extensions/geode-modules-tomcat8/src/main/java/org/apache/geode/modules/session/catalina/Tomcat8DeltaSessionManager.java
 
b/extensions/geode-modules-tomcat8/src/main/java/org/apache/geode/modules/session/catalina/Tomcat8DeltaSessionManager.java
index 8a32ac0..573bf43 100644
--- 
a/extensions/geode-modules-tomcat8/src/main/java/org/apache/geode/modules/session/catalina/Tomcat8DeltaSessionManager.java
+++ 
b/extensions/geode-modules-tomcat8/src/main/java/org/apache/geode/modules/session/catalina/Tomcat8DeltaSessionManager.java
@@ -12,6 +12,7 @@
  * or implied. See the License for the specific language governing permissions 
and limitations under
  * the License.
  */
+
 package org.apache.geode.modules.session.catalina;
 
 import java.io.IOException;
@@ -22,7 +23,7 @@ import org.apache.catalina.LifecycleState;
 import org.apache.catalina.Pipeline;
 import org.apache.catalina.session.StandardSession;
 
-public class Tomcat8DeltaSessionManager extends DeltaSessionManager {
+public class Tomcat8DeltaSessionManager extends 
DeltaSessionManager<Tomcat8CommitSessionValve> {
 
   /**
    * Prepare for the beginning of active use of the public methods of this 
component. This method
@@ -138,6 +139,11 @@ public class Tomcat8DeltaSessionManager extends 
DeltaSessionManager {
   }
 
   @Override
+  protected Tomcat8CommitSessionValve createCommitSessionValve() {
+    return new Tomcat8CommitSessionValve();
+  }
+
+  @Override
   public Context getTheContext() {
     return getContext();
   }
diff --git 
a/extensions/geode-modules-tomcat8/src/test/java/org/apache/geode/modules/session/catalina/Tomcat8CommitSessionOutputBufferTest.java
 
b/extensions/geode-modules-tomcat8/src/test/java/org/apache/geode/modules/session/catalina/Tomcat8CommitSessionOutputBufferTest.java
new file mode 100644
index 0000000..4efc77b
--- /dev/null
+++ 
b/extensions/geode-modules-tomcat8/src/test/java/org/apache/geode/modules/session/catalina/Tomcat8CommitSessionOutputBufferTest.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license
+ * agreements. See the NOTICE file distributed with this work for additional 
information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache 
License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the 
License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software 
distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
KIND, either express
+ * or implied. See the License for the specific language governing permissions 
and limitations under
+ * the License.
+ */
+
+package org.apache.geode.modules.session.catalina;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+import org.apache.coyote.OutputBuffer;
+import org.apache.tomcat.util.buf.ByteChunk;
+import org.junit.Test;
+import org.mockito.InOrder;
+
+public class Tomcat8CommitSessionOutputBufferTest {
+
+  final SessionCommitter sessionCommitter = mock(SessionCommitter.class);
+  final OutputBuffer delegate = mock(OutputBuffer.class);
+
+  final Tomcat8CommitSessionOutputBuffer commitSesssionOutputBuffer =
+      new Tomcat8CommitSessionOutputBuffer(sessionCommitter, delegate);
+
+  /**
+   * @deprecated Remove when {@link OutputBuffer} drops this method.
+   */
+  @Deprecated
+  @Test
+  public void doWrite() throws IOException {
+    final ByteChunk byteChunk = new ByteChunk();
+
+    commitSesssionOutputBuffer.doWrite(byteChunk);
+
+    final InOrder inOrder = inOrder(sessionCommitter, delegate);
+    inOrder.verify(sessionCommitter).commit();
+    inOrder.verify(delegate).doWrite(byteChunk);
+    inOrder.verifyNoMoreInteractions();
+  }
+
+  @Test
+  public void testDoWrite() throws IOException {
+    final ByteBuffer byteBuffer = ByteBuffer.allocate(0);
+
+    commitSesssionOutputBuffer.doWrite(byteBuffer);
+
+    final InOrder inOrder = inOrder(sessionCommitter, delegate);
+    inOrder.verify(sessionCommitter).commit();
+    inOrder.verify(delegate).doWrite(byteBuffer);
+    inOrder.verifyNoMoreInteractions();
+  }
+
+  @Test
+  public void getBytesWritten() {
+    when(delegate.getBytesWritten()).thenReturn(42L);
+
+    assertThat(commitSesssionOutputBuffer.getBytesWritten()).isEqualTo(42L);
+
+    final InOrder inOrder = inOrder(sessionCommitter, delegate);
+    inOrder.verify(delegate).getBytesWritten();
+    inOrder.verifyNoMoreInteractions();
+  }
+}
diff --git 
a/extensions/geode-modules-tomcat8/src/test/java/org/apache/geode/modules/session/catalina/Tomcat8CommitSessionValveTest.java
 
b/extensions/geode-modules-tomcat8/src/test/java/org/apache/geode/modules/session/catalina/Tomcat8CommitSessionValveTest.java
new file mode 100644
index 0000000..5cc2f0a
--- /dev/null
+++ 
b/extensions/geode-modules-tomcat8/src/test/java/org/apache/geode/modules/session/catalina/Tomcat8CommitSessionValveTest.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license
+ * agreements. See the NOTICE file distributed with this work for additional 
information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache 
License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the 
License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software 
distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
KIND, either express
+ * or implied. See the License for the specific language governing permissions 
and limitations under
+ * the License.
+ */
+
+package org.apache.geode.modules.session.catalina;
+
+import static 
org.apache.geode.modules.session.catalina.Tomcat8CommitSessionValve.getOutputBuffer;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.connector.Connector;
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.connector.Response;
+import org.apache.coyote.OutputBuffer;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
+
+
+public class Tomcat8CommitSessionValveTest {
+
+  private final Tomcat8CommitSessionValve valve = new 
Tomcat8CommitSessionValve();
+  private final OutputBuffer outputBuffer = mock(OutputBuffer.class);
+  private Response response;
+  private org.apache.coyote.Response coyoteResponse;
+
+  @Before
+  public void before() {
+    final Connector connector = mock(Connector.class);
+
+    final Context context = mock(Context.class);
+
+    final Request request = mock(Request.class);
+    doReturn(context).when(request).getContext();
+
+    coyoteResponse = new org.apache.coyote.Response();
+    coyoteResponse.setOutputBuffer(outputBuffer);
+
+    response = new Response();
+    response.setConnector(connector);
+    response.setRequest(request);
+    response.setCoyoteResponse(coyoteResponse);
+  }
+
+  @Test
+  public void wrappedOutputBufferForwardsToDelegate() throws IOException {
+    wrappedOutputBufferForwardsToDelegate(new byte[] {'a', 'b', 'c'});
+  }
+
+  @Test
+  public void recycledResponseObjectDoesNotWrapAlreadyWrappedOutputBuffer() 
throws IOException {
+    wrappedOutputBufferForwardsToDelegate(new byte[] {'a', 'b', 'c'});
+    response.recycle();
+    reset(outputBuffer);
+    wrappedOutputBufferForwardsToDelegate(new byte[] {'d', 'e', 'f'});
+  }
+
+  private void wrappedOutputBufferForwardsToDelegate(final byte[] bytes) 
throws IOException {
+    final OutputStream outputStream =
+        valve.wrapResponse(response).getResponse().getOutputStream();
+    outputStream.write(bytes);
+    outputStream.flush();
+
+    final ArgumentCaptor<ByteBuffer> byteBuffer = 
ArgumentCaptor.forClass(ByteBuffer.class);
+
+    final InOrder inOrder = inOrder(outputBuffer);
+    inOrder.verify(outputBuffer).doWrite(byteBuffer.capture());
+    inOrder.verifyNoMoreInteractions();
+
+    final OutputBuffer wrappedOutputBuffer = getOutputBuffer(coyoteResponse);
+    
assertThat(wrappedOutputBuffer).isInstanceOf(Tomcat8CommitSessionOutputBuffer.class);
+    assertThat(((Tomcat8CommitSessionOutputBuffer) 
wrappedOutputBuffer).getDelegate())
+        .isNotInstanceOf(Tomcat8CommitSessionOutputBuffer.class);
+
+    assertThat(byteBuffer.getValue().array()).contains(bytes);
+  }
+
+}
diff --git 
a/extensions/geode-modules-tomcat9/src/integrationTest/java/org/apache/geode/modules/session/catalina/CommitSessionValveIntegrationTest.java
 
b/extensions/geode-modules-tomcat9/src/integrationTest/java/org/apache/geode/modules/session/catalina/CommitSessionValveIntegrationTest.java
new file mode 100644
index 0000000..c43729a
--- /dev/null
+++ 
b/extensions/geode-modules-tomcat9/src/integrationTest/java/org/apache/geode/modules/session/catalina/CommitSessionValveIntegrationTest.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 org.apache.geode.modules.session.catalina;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.connector.Response;
+import org.apache.coyote.OutputBuffer;
+import org.apache.juli.logging.Log;
+import org.junit.Before;
+
+public class CommitSessionValveIntegrationTest
+    extends 
AbstractCommitSessionValveIntegrationTest<Tomcat9CommitSessionValve> {
+
+  @Before
+  public void setUp() {
+    final Context context = mock(Context.class);
+    doReturn(mock(Log.class)).when(context).getLogger();
+
+    request = mock(Request.class);
+    doReturn(context).when(request).getContext();
+
+    final OutputBuffer outputBuffer = mock(OutputBuffer.class);
+
+    final org.apache.coyote.Response coyoteResponse = new 
org.apache.coyote.Response();
+    coyoteResponse.setOutputBuffer(outputBuffer);
+
+    response = new Response();
+    response.setRequest(request);
+    response.setCoyoteResponse(coyoteResponse);
+  }
+
+  @Override
+  protected Tomcat9CommitSessionValve createCommitSessionValve() {
+    return new Tomcat9CommitSessionValve();
+  }
+}
diff --git 
a/extensions/geode-modules-tomcat9/src/main/java/org/apache/geode/modules/session/catalina/Tomcat9CommitSessionOutputBuffer.java
 
b/extensions/geode-modules-tomcat9/src/main/java/org/apache/geode/modules/session/catalina/Tomcat9CommitSessionOutputBuffer.java
new file mode 100644
index 0000000..4e4600b
--- /dev/null
+++ 
b/extensions/geode-modules-tomcat9/src/main/java/org/apache/geode/modules/session/catalina/Tomcat9CommitSessionOutputBuffer.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license
+ * agreements. See the NOTICE file distributed with this work for additional 
information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache 
License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the 
License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software 
distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
KIND, either express
+ * or implied. See the License for the specific language governing permissions 
and limitations under
+ * the License.
+ */
+
+package org.apache.geode.modules.session.catalina;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+import org.apache.coyote.OutputBuffer;
+
+
+/**
+ * Delegating {@link OutputBuffer} that commits sessions on write through. 
Output data is buffered
+ * ahead of this object and flushed through this interface when full or 
explicitly flushed.
+ */
+class Tomcat9CommitSessionOutputBuffer implements OutputBuffer {
+
+  private final SessionCommitter sessionCommitter;
+  private final OutputBuffer delegate;
+
+  public Tomcat9CommitSessionOutputBuffer(final SessionCommitter 
sessionCommitter,
+      final OutputBuffer delegate) {
+    this.sessionCommitter = sessionCommitter;
+    this.delegate = delegate;
+  }
+
+  @Override
+  public int doWrite(final ByteBuffer chunk) throws IOException {
+    sessionCommitter.commit();
+    return delegate.doWrite(chunk);
+  }
+
+  @Override
+  public long getBytesWritten() {
+    return delegate.getBytesWritten();
+  }
+
+  OutputBuffer getDelegate() {
+    return delegate;
+  }
+}
diff --git 
a/extensions/geode-modules-tomcat9/src/main/java/org/apache/geode/modules/session/catalina/Tomcat9CommitSessionValve.java
 
b/extensions/geode-modules-tomcat9/src/main/java/org/apache/geode/modules/session/catalina/Tomcat9CommitSessionValve.java
new file mode 100644
index 0000000..925b0d2
--- /dev/null
+++ 
b/extensions/geode-modules-tomcat9/src/main/java/org/apache/geode/modules/session/catalina/Tomcat9CommitSessionValve.java
@@ -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.
+ */
+
+package org.apache.geode.modules.session.catalina;
+
+import java.lang.reflect.Field;
+
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.connector.Response;
+import org.apache.coyote.OutputBuffer;
+
+public class Tomcat9CommitSessionValve
+    extends AbstractCommitSessionValve<Tomcat9CommitSessionValve> {
+
+  private static final Field outputBufferField;
+
+  static {
+    try {
+      outputBufferField = 
org.apache.coyote.Response.class.getDeclaredField("outputBuffer");
+      outputBufferField.setAccessible(true);
+    } catch (final NoSuchFieldException e) {
+      throw new IllegalStateException(e);
+    }
+  }
+
+  @Override
+  Response wrapResponse(final Response response) {
+    final org.apache.coyote.Response coyoteResponse = 
response.getCoyoteResponse();
+    final OutputBuffer delegateOutputBuffer = getOutputBuffer(coyoteResponse);
+    if (!(delegateOutputBuffer instanceof Tomcat9CommitSessionOutputBuffer)) {
+      final Request request = response.getRequest();
+      final OutputBuffer sessionCommitOutputBuffer =
+          new Tomcat9CommitSessionOutputBuffer(() -> commitSession(request), 
delegateOutputBuffer);
+      coyoteResponse.setOutputBuffer(sessionCommitOutputBuffer);
+    }
+    return response;
+  }
+
+  static OutputBuffer getOutputBuffer(final org.apache.coyote.Response 
coyoteResponse) {
+    try {
+      return (OutputBuffer) outputBufferField.get(coyoteResponse);
+    } catch (final IllegalAccessException e) {
+      throw new IllegalStateException(e);
+    }
+  }
+}
diff --git 
a/extensions/geode-modules-tomcat9/src/main/java/org/apache/geode/modules/session/catalina/Tomcat9DeltaSessionManager.java
 
b/extensions/geode-modules-tomcat9/src/main/java/org/apache/geode/modules/session/catalina/Tomcat9DeltaSessionManager.java
index ac9ac2c..5c7e47d 100644
--- 
a/extensions/geode-modules-tomcat9/src/main/java/org/apache/geode/modules/session/catalina/Tomcat9DeltaSessionManager.java
+++ 
b/extensions/geode-modules-tomcat9/src/main/java/org/apache/geode/modules/session/catalina/Tomcat9DeltaSessionManager.java
@@ -22,7 +22,7 @@ import org.apache.catalina.LifecycleState;
 import org.apache.catalina.Pipeline;
 import org.apache.catalina.session.StandardSession;
 
-public class Tomcat9DeltaSessionManager extends DeltaSessionManager {
+public class Tomcat9DeltaSessionManager extends 
DeltaSessionManager<Tomcat9CommitSessionValve> {
 
   /**
    * Prepare for the beginning of active use of the public methods of this 
component. This method
@@ -138,6 +138,11 @@ public class Tomcat9DeltaSessionManager extends 
DeltaSessionManager {
   }
 
   @Override
+  protected Tomcat9CommitSessionValve createCommitSessionValve() {
+    return new Tomcat9CommitSessionValve();
+  }
+
+  @Override
   public Context getTheContext() {
     return getContext();
   }
diff --git 
a/extensions/geode-modules-tomcat9/src/test/java/org/apache/geode/modules/session/catalina/Tomcat9CommitSessionOutputBufferTest.java
 
b/extensions/geode-modules-tomcat9/src/test/java/org/apache/geode/modules/session/catalina/Tomcat9CommitSessionOutputBufferTest.java
new file mode 100644
index 0000000..0ec3a00
--- /dev/null
+++ 
b/extensions/geode-modules-tomcat9/src/test/java/org/apache/geode/modules/session/catalina/Tomcat9CommitSessionOutputBufferTest.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license
+ * agreements. See the NOTICE file distributed with this work for additional 
information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache 
License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the 
License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software 
distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
KIND, either express
+ * or implied. See the License for the specific language governing permissions 
and limitations under
+ * the License.
+ */
+
+package org.apache.geode.modules.session.catalina;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+import org.apache.coyote.OutputBuffer;
+import org.junit.Test;
+import org.mockito.InOrder;
+
+public class Tomcat9CommitSessionOutputBufferTest {
+
+  final SessionCommitter sessionCommitter = mock(SessionCommitter.class);
+  final OutputBuffer delegate = mock(OutputBuffer.class);
+
+  final Tomcat9CommitSessionOutputBuffer commitSesssionOutputBuffer =
+      new Tomcat9CommitSessionOutputBuffer(sessionCommitter, delegate);
+
+  @Test
+  public void testDoWrite() throws IOException {
+    final ByteBuffer byteBuffer = ByteBuffer.allocate(0);
+
+    commitSesssionOutputBuffer.doWrite(byteBuffer);
+
+    final InOrder inOrder = inOrder(sessionCommitter, delegate);
+    inOrder.verify(sessionCommitter).commit();
+    inOrder.verify(delegate).doWrite(byteBuffer);
+    inOrder.verifyNoMoreInteractions();
+  }
+
+  @Test
+  public void getBytesWritten() {
+    when(delegate.getBytesWritten()).thenReturn(42L);
+
+    assertThat(commitSesssionOutputBuffer.getBytesWritten()).isEqualTo(42L);
+
+    final InOrder inOrder = inOrder(sessionCommitter, delegate);
+    inOrder.verify(delegate).getBytesWritten();
+    inOrder.verifyNoMoreInteractions();
+  }
+}
diff --git 
a/extensions/geode-modules-tomcat9/src/test/java/org/apache/geode/modules/session/catalina/Tomcat9CommitSessionValveTest.java
 
b/extensions/geode-modules-tomcat9/src/test/java/org/apache/geode/modules/session/catalina/Tomcat9CommitSessionValveTest.java
new file mode 100644
index 0000000..32095a2
--- /dev/null
+++ 
b/extensions/geode-modules-tomcat9/src/test/java/org/apache/geode/modules/session/catalina/Tomcat9CommitSessionValveTest.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license
+ * agreements. See the NOTICE file distributed with this work for additional 
information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache 
License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the 
License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software 
distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
KIND, either express
+ * or implied. See the License for the specific language governing permissions 
and limitations under
+ * the License.
+ */
+
+package org.apache.geode.modules.session.catalina;
+
+import static 
org.apache.geode.modules.session.catalina.Tomcat9CommitSessionValve.getOutputBuffer;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.connector.Response;
+import org.apache.coyote.OutputBuffer;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
+
+
+public class Tomcat9CommitSessionValveTest {
+
+  private final Tomcat9CommitSessionValve valve = new 
Tomcat9CommitSessionValve();
+  private final OutputBuffer outputBuffer = mock(OutputBuffer.class);
+  private Response response;
+  private org.apache.coyote.Response coyoteResponse;
+
+  @Before
+  public void before() {
+    final Context context = mock(Context.class);
+
+    final Request request = mock(Request.class);
+    doReturn(context).when(request).getContext();
+
+    coyoteResponse = new org.apache.coyote.Response();
+    coyoteResponse.setOutputBuffer(outputBuffer);
+
+    response = new Response();
+    response.setRequest(request);
+    response.setCoyoteResponse(coyoteResponse);
+  }
+
+  @Test
+  public void wrappedOutputBufferForwardsToDelegate() throws IOException {
+    wrappedOutputBufferForwardsToDelegate(new byte[] {'a', 'b', 'c'});
+  }
+
+  @Test
+  public void recycledResponseObjectDoesNotWrapAlreadyWrappedOutputBuffer() 
throws IOException {
+    wrappedOutputBufferForwardsToDelegate(new byte[] {'a', 'b', 'c'});
+    response.recycle();
+    reset(outputBuffer);
+    wrappedOutputBufferForwardsToDelegate(new byte[] {'d', 'e', 'f'});
+  }
+
+  private void wrappedOutputBufferForwardsToDelegate(final byte[] bytes) 
throws IOException {
+    final OutputStream outputStream =
+        valve.wrapResponse(response).getResponse().getOutputStream();
+    outputStream.write(bytes);
+    outputStream.flush();
+
+    final ArgumentCaptor<ByteBuffer> byteBuffer = 
ArgumentCaptor.forClass(ByteBuffer.class);
+
+    final InOrder inOrder = inOrder(outputBuffer);
+    inOrder.verify(outputBuffer).doWrite(byteBuffer.capture());
+    inOrder.verifyNoMoreInteractions();
+
+    final OutputBuffer wrappedOutputBuffer = getOutputBuffer(coyoteResponse);
+    
assertThat(wrappedOutputBuffer).isInstanceOf(Tomcat9CommitSessionOutputBuffer.class);
+    assertThat(((Tomcat9CommitSessionOutputBuffer) 
wrappedOutputBuffer).getDelegate())
+        .isNotInstanceOf(Tomcat9CommitSessionOutputBuffer.class);
+
+    assertThat(byteBuffer.getValue().array()).contains(bytes);
+  }
+
+}
diff --git 
a/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/AbstractCommitSessionValve.java
 
b/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/AbstractCommitSessionValve.java
new file mode 100644
index 0000000..6276086
--- /dev/null
+++ 
b/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/AbstractCommitSessionValve.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license
+ * agreements. See the NOTICE file distributed with this work for additional 
information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache 
License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the 
License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software 
distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
KIND, either express
+ * or implied. See the License for the specific language governing permissions 
and limitations under
+ * the License.
+ */
+package org.apache.geode.modules.session.catalina;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.Manager;
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.connector.Response;
+import org.apache.catalina.valves.ValveBase;
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+
+public abstract class AbstractCommitSessionValve<SelfT extends 
AbstractCommitSessionValve<?>>
+    extends ValveBase {
+
+  private static final Log log = 
LogFactory.getLog(AbstractCommitSessionValve.class);
+
+  protected static final String info =
+      "org.apache.geode.modules.session.catalina.CommitSessionValve/1.0";
+
+  AbstractCommitSessionValve() {
+    log.info("Initialized");
+  }
+
+  @Override
+  public void invoke(final Request request, final Response response)
+      throws IOException, ServletException {
+    try {
+      getNext().invoke(request, wrapResponse(response));
+    } finally {
+      commitSession(request);
+    }
+  }
+
+  /**
+   * Commit session only if DeltaSessionManager is in place.
+   *
+   * @param request to commit session from.
+   */
+  protected static <SelfT extends AbstractCommitSessionValve<?>> void 
commitSession(
+      final Request request) {
+    final Context context = request.getContext();
+    final Manager manager = context.getManager();
+    if (manager instanceof DeltaSessionManager) {
+      final DeltaSessionFacade session = (DeltaSessionFacade) 
request.getSession(false);
+      if (session != null) {
+        @SuppressWarnings("unchecked")
+        final DeltaSessionManager<SelfT> deltaSessionManager = 
(DeltaSessionManager<SelfT>) manager;
+        if (session.isValid()) {
+          deltaSessionManager.removeTouchedSession(session.getId());
+          session.commit();
+          if (log.isDebugEnabled()) {
+            log.debug(session + ": Committed.");
+          }
+        } else {
+          if (log.isDebugEnabled()) {
+            log.debug(session + ": Not valid so not committing.");
+          }
+        }
+      }
+    }
+  }
+
+  abstract Response wrapResponse(final Response response);
+
+}
diff --git 
a/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/CommitSessionValve.java
 
b/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/CommitSessionValve.java
deleted file mode 100644
index 1da58b7..0000000
--- 
a/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/CommitSessionValve.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license
- * agreements. See the NOTICE file distributed with this work for additional 
information regarding
- * copyright ownership. The ASF licenses this file to You under the Apache 
License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the 
License. You may obtain a
- * copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software 
distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
KIND, either express
- * or implied. See the License for the specific language governing permissions 
and limitations under
- * the License.
- */
-package org.apache.geode.modules.session.catalina;
-
-import java.io.IOException;
-
-import javax.servlet.ServletException;
-
-import org.apache.catalina.Manager;
-import org.apache.catalina.connector.Request;
-import org.apache.catalina.connector.Response;
-import org.apache.catalina.valves.ValveBase;
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
-
-public class CommitSessionValve extends ValveBase {
-
-  private static final Log log = LogFactory.getLog(CommitSessionValve.class);
-
-  protected static final String info =
-      "org.apache.geode.modules.session.catalina.CommitSessionValve/1.0";
-
-  CommitSessionValve() {
-    log.info("Initialized");
-  }
-
-  @Override
-  public void invoke(Request request, Response response) throws IOException, 
ServletException {
-    // Get the Manager
-    Manager manager = request.getContext().getManager();
-    DeltaSessionFacade session;
-
-    // Invoke the next Valve
-    try {
-      getNext().invoke(request, response);
-    } finally {
-      // 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()) {
-            dsm.removeTouchedSession(session.getId());
-            session.commit();
-            if (dsm.getTheContext().getLogger().isDebugEnabled()) {
-              dsm.getTheContext().getLogger().debug(session + ": Committed.");
-            }
-          } else {
-            if (dsm.getTheContext().getLogger().isDebugEnabled()) {
-              dsm.getTheContext().getLogger().debug(session + ": Not valid so 
not committing.");
-            }
-          }
-        }
-      }
-    }
-  }
-}
diff --git 
a/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/DeltaSessionManager.java
 
b/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/DeltaSessionManager.java
index 2af36fe..86103df 100644
--- 
a/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/DeltaSessionManager.java
+++ 
b/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/DeltaSessionManager.java
@@ -63,7 +63,8 @@ import org.apache.geode.modules.util.ContextMapper;
 import org.apache.geode.modules.util.RegionConfiguration;
 import org.apache.geode.modules.util.RegionHelper;
 
-public abstract class DeltaSessionManager extends ManagerBase
+public abstract class DeltaSessionManager<CommitSessionValveT extends 
AbstractCommitSessionValve>
+    extends ManagerBase
     implements Lifecycle, PropertyChangeListener, SessionManager {
 
   static final String catalinaBaseSystemProperty = "catalina.base";
@@ -91,7 +92,7 @@ public abstract class DeltaSessionManager extends ManagerBase
 
   private Valve jvmRouteBinderValve;
 
-  private Valve commitSessionValve;
+  private CommitSessionValveT commitSessionValve;
 
   private SessionCache sessionCache;
 
@@ -601,10 +602,12 @@ public abstract class DeltaSessionManager extends 
ManagerBase
     if (getLogger().isDebugEnabled()) {
       getLogger().debug(this + ": Registering CommitSessionValve");
     }
-    commitSessionValve = new CommitSessionValve();
+    commitSessionValve = createCommitSessionValve();
     getPipeline().addValve(commitSessionValve);
   }
 
+  protected abstract CommitSessionValveT createCommitSessionValve();
+
   protected void unregisterCommitSessionValve() {
     if (getLogger().isDebugEnabled()) {
       getLogger().debug(this + ": Unregistering CommitSessionValve");
diff --git 
a/extensions/geode-modules-tomcat8/src/main/java/org/apache/geode/modules/session/catalina/DeltaSession8.java
 
b/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/SessionCommitter.java
similarity index 60%
copy from 
extensions/geode-modules-tomcat8/src/main/java/org/apache/geode/modules/session/catalina/DeltaSession8.java
copy to 
extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/SessionCommitter.java
index a17fdde..5af9aa2 100644
--- 
a/extensions/geode-modules-tomcat8/src/main/java/org/apache/geode/modules/session/catalina/DeltaSession8.java
+++ 
b/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/SessionCommitter.java
@@ -12,28 +12,16 @@
  * or implied. See the License for the specific language governing permissions 
and limitations under
  * the License.
  */
-package org.apache.geode.modules.session.catalina;
-
-import org.apache.catalina.Manager;
 
+package org.apache.geode.modules.session.catalina;
 
-@SuppressWarnings("serial")
-public class DeltaSession8 extends DeltaSession {
-  /**
-   * Construct a new <code>Session</code> associated with no 
<code>Manager</code>. The
-   * <code>Manager</code> will be assigned later using {@link 
#setOwner(Object)}.
-   */
-  @SuppressWarnings("unused")
-  public DeltaSession8() {
-    super();
-  }
+/**
+ * Lambda interface for committing session data.
+ */
+interface SessionCommitter {
 
   /**
-   * Construct a new Session associated with the specified Manager.
-   *
-   * @param manager The manager with which this Session is associated
+   * Invoked to commit session data.
    */
-  DeltaSession8(Manager manager) {
-    super(manager);
-  }
+  void commit();
 }
diff --git 
a/extensions/geode-modules-tomcat8/src/main/java/org/apache/geode/modules/session/catalina/DeltaSession8.java
 
b/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/Tomcat6CommitSessionValve.java
similarity index 59%
copy from 
extensions/geode-modules-tomcat8/src/main/java/org/apache/geode/modules/session/catalina/DeltaSession8.java
copy to 
extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/Tomcat6CommitSessionValve.java
index a17fdde..b27fe65 100644
--- 
a/extensions/geode-modules-tomcat8/src/main/java/org/apache/geode/modules/session/catalina/DeltaSession8.java
+++ 
b/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/Tomcat6CommitSessionValve.java
@@ -12,28 +12,16 @@
  * or implied. See the License for the specific language governing permissions 
and limitations under
  * the License.
  */
-package org.apache.geode.modules.session.catalina;
 
-import org.apache.catalina.Manager;
+package org.apache.geode.modules.session.catalina;
 
+import org.apache.catalina.connector.Response;
 
-@SuppressWarnings("serial")
-public class DeltaSession8 extends DeltaSession {
-  /**
-   * Construct a new <code>Session</code> associated with no 
<code>Manager</code>. The
-   * <code>Manager</code> will be assigned later using {@link 
#setOwner(Object)}.
-   */
-  @SuppressWarnings("unused")
-  public DeltaSession8() {
-    super();
-  }
+@Deprecated
+public final class Tomcat6CommitSessionValve extends 
AbstractCommitSessionValve {
 
-  /**
-   * Construct a new Session associated with the specified Manager.
-   *
-   * @param manager The manager with which this Session is associated
-   */
-  DeltaSession8(Manager manager) {
-    super(manager);
+  @Override
+  protected Response wrapResponse(Response response) {
+    return response;
   }
 }
diff --git 
a/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/Tomcat6DeltaSessionManager.java
 
b/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/Tomcat6DeltaSessionManager.java
index 555f09e..1abceb9 100644
--- 
a/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/Tomcat6DeltaSessionManager.java
+++ 
b/extensions/geode-modules/src/main/java/org/apache/geode/modules/session/catalina/Tomcat6DeltaSessionManager.java
@@ -21,7 +21,7 @@ import org.apache.catalina.util.LifecycleSupport;
  * @deprecated Tomcat 6 has reached its end of life and support for Tomcat 6 
will be removed
  *             from a future Geode release.
  */
-public class Tomcat6DeltaSessionManager extends DeltaSessionManager {
+public class Tomcat6DeltaSessionManager extends 
DeltaSessionManager<Tomcat6CommitSessionValve> {
 
   /**
    * The <code>LifecycleSupport</code> for this component.
@@ -131,4 +131,9 @@ public class Tomcat6DeltaSessionManager extends 
DeltaSessionManager {
   public void removeLifecycleListener(LifecycleListener listener) {
     this.lifecycle.removeLifecycleListener(listener);
   }
+
+  @Override
+  protected Tomcat6CommitSessionValve createCommitSessionValve() {
+    return new Tomcat6CommitSessionValve();
+  }
 }
diff --git a/geode-assembly/src/integrationTest/resources/assembly_content.txt 
b/geode-assembly/src/integrationTest/resources/assembly_content.txt
index fca61e9..1eaf681 100644
--- a/geode-assembly/src/integrationTest/resources/assembly_content.txt
+++ b/geode-assembly/src/integrationTest/resources/assembly_content.txt
@@ -824,7 +824,11 @@ 
javadoc/org/apache/geode/modules/session/catalina/AbstractCacheLifecycleListener
 javadoc/org/apache/geode/modules/session/catalina/AbstractSessionCache.html
 
javadoc/org/apache/geode/modules/session/catalina/ClientServerCacheLifecycleListener.html
 javadoc/org/apache/geode/modules/session/catalina/ClientServerSessionCache.html
-javadoc/org/apache/geode/modules/session/catalina/CommitSessionValve.html
+javadoc/org/apache/geode/modules/session/catalina/AbstractCommitSessionValve.html
+javadoc/org/apache/geode/modules/session/catalina/Tomcat6CommitSessionValve.html
+javadoc/org/apache/geode/modules/session/catalina/Tomcat7CommitSessionValve.html
+javadoc/org/apache/geode/modules/session/catalina/Tomcat8CommitSessionValve.html
+javadoc/org/apache/geode/modules/session/catalina/Tomcat9CommitSessionValve.html
 javadoc/org/apache/geode/modules/session/catalina/DeltaSession.html
 javadoc/org/apache/geode/modules/session/catalina/DeltaSession7.html
 javadoc/org/apache/geode/modules/session/catalina/DeltaSession8.html

Reply via email to