Merge branch 'master' into unix-socket
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpConnectionOverHTTP.java b/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpConnectionOverHTTP.java
index 564e91a..5c60de2 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpConnectionOverHTTP.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpConnectionOverHTTP.java
@@ -42,8 +42,8 @@
     private static final Logger LOG = Log.getLogger(HttpConnectionOverHTTP.class);
 
     private final AtomicBoolean closed = new AtomicBoolean();
-    private final Promise<Connection> promise;
     private final AtomicInteger sweeps = new AtomicInteger();
+    private final Promise<Connection> promise;
     private final Delegate delegate;
     private final HttpChannelOverHTTP channel;
     private long idleTimeout;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/AbstractHttpClientServerTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/AbstractHttpClientServerTest.java
index edb6c9c..9cea0fd 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/AbstractHttpClientServerTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/AbstractHttpClientServerTest.java
@@ -60,6 +60,12 @@
 
     public void start(Handler handler) throws Exception
     {
+        startServer(handler);
+        startClient();
+    }
+
+    protected void startServer(Handler handler) throws Exception
+    {
         if (sslContextFactory != null)
         {
             sslContextFactory.setEndpointIdentificationAlgorithm("");
@@ -79,8 +85,6 @@
         server.addConnector(connector);
         server.setHandler(handler);
         server.start();
-
-        startClient();
     }
 
     protected void startClient() throws Exception
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java
index 1d803b9..404a3e8 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java
@@ -47,6 +47,7 @@
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.atomic.AtomicReference;
@@ -63,6 +64,7 @@
 import org.eclipse.jetty.client.api.Request;
 import org.eclipse.jetty.client.api.Response;
 import org.eclipse.jetty.client.api.Result;
+import org.eclipse.jetty.client.http.HttpClientTransportOverHTTP;
 import org.eclipse.jetty.client.http.HttpConnectionOverHTTP;
 import org.eclipse.jetty.client.http.HttpDestinationOverHTTP;
 import org.eclipse.jetty.client.util.BufferingResponseListener;
@@ -75,6 +77,7 @@
 import org.eclipse.jetty.http.HttpHeaderValue;
 import org.eclipse.jetty.http.HttpMethod;
 import org.eclipse.jetty.http.HttpVersion;
+import org.eclipse.jetty.io.EndPoint;
 import org.eclipse.jetty.server.handler.AbstractHandler;
 import org.eclipse.jetty.toolchain.test.TestingDir;
 import org.eclipse.jetty.toolchain.test.annotation.Slow;
@@ -1434,6 +1437,54 @@
     }
 
     @Test
+    public void testRequestSentOnlyAfterConnectionOpen() throws Exception
+    {
+        startServer(new AbstractHandler()
+        {
+            @Override
+            public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+            {
+                baseRequest.setHandled(true);
+            }
+        });
+
+        final AtomicBoolean open = new AtomicBoolean();
+        client = new HttpClient(new HttpClientTransportOverHTTP()
+        {
+            @Override
+            protected HttpConnectionOverHTTP newHttpConnection(EndPoint endPoint, HttpDestination destination, Promise<Connection> promise)
+            {
+                return new HttpConnectionOverHTTP(endPoint, destination, promise)
+                {
+                    @Override
+                    public void onOpen()
+                    {
+                        open.set(true);
+                        super.onOpen();
+                    }
+                };
+            }
+        }, sslContextFactory);
+        client.start();
+
+        final CountDownLatch latch = new CountDownLatch(2);
+        client.newRequest("localhost", connector.getLocalPort())
+                .scheme(scheme)
+                .onRequestBegin(request ->
+                {
+                    Assert.assertTrue(open.get());
+                    latch.countDown();
+                })
+                .send(result ->
+                {
+                    if (result.isSucceeded())
+                        latch.countDown();
+                });
+
+        Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
+    }
+
+    @Test
     public void testCONNECTWithHTTP10() throws Exception
     {
         try (ServerSocket server = new ServerSocket(0))
diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpConnectionOverFCGI.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpConnectionOverFCGI.java
index 4be9cbf..4d9691d 100644
--- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpConnectionOverFCGI.java
+++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpConnectionOverFCGI.java
@@ -181,7 +181,7 @@
         if (channels.isEmpty())
             close();
         else
-            failAndClose(new EOFException());
+            failAndClose(new EOFException(String.valueOf(getEndPoint())));
     }
 
     @Override
diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/BeginRequestContentParser.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/BeginRequestContentParser.java
index 2367fb6..912f4f8 100644
--- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/BeginRequestContentParser.java
+++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/BeginRequestContentParser.java
@@ -22,6 +22,16 @@
 
 import org.eclipse.jetty.fcgi.FCGI;
 
+/**
+ * <p>Parser for the BEGIN_REQUEST frame body.</p>
+ * <pre>
+ * struct begin_request_body {
+ *     ushort role;
+ *     ubyte flags;
+ *     ubyte[5] reserved;
+ * }
+ * </pre>
+ */
 public class BeginRequestContentParser extends ContentParser
 {
     private final ServerParser.Listener listener;
diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/EndRequestContentParser.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/EndRequestContentParser.java
index b8173bf..dc07bd5 100644
--- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/EndRequestContentParser.java
+++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/EndRequestContentParser.java
@@ -20,6 +20,16 @@
 
 import java.nio.ByteBuffer;
 
+/**
+ * <p>Parser for the END_REQUEST frame body.</p>
+ * <pre>
+ * struct end_request_body {
+ *     uint applicationStatus;
+ *     ubyte protocolStatus;
+ *     ubyte[3] reserved;
+ * }
+ * </pre>
+ */
 public class EndRequestContentParser extends ContentParser
 {
     private final Parser.Listener listener;
@@ -80,7 +90,7 @@
                     }
                     else
                     {
-                        state = State.APPLICATION_BYTES;
+                        state = State.RESERVED_BYTES;
                         cursor = 0;
                         break;
                     }
@@ -88,7 +98,7 @@
                 case RESERVED_BYTES:
                 {
                     buffer.get();
-                    if (++cursor == 0)
+                    if (++cursor == 3)
                     {
                         onEnd();
                         reset();
diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/HeaderParser.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/HeaderParser.java
index 078105a..7d43112 100644
--- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/HeaderParser.java
+++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/HeaderParser.java
@@ -21,9 +21,28 @@
 import java.nio.ByteBuffer;
 
 import org.eclipse.jetty.fcgi.FCGI;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
 
+/**
+ * <p>Parser for FastCGI frame headers.</p>
+ * <pre>
+ * struct frame_header {
+ *     ubyte version;
+ *     ubyte type;
+ *     ushort requestId;
+ *     ushort contentLength;
+ *     ubyte paddingLength;
+ *     ubyte reserved;
+ * }
+ * </pre>
+ *
+ * @see Parser
+ */
 public class HeaderParser
 {
+    private static final Logger LOG = Log.getLogger(Parser.class);
+
     private State state = State.VERSION;
     private int cursor;
     private int version;
@@ -109,6 +128,8 @@
                 case RESERVED:
                 {
                     buffer.get();
+                    if (LOG.isDebugEnabled())
+                        LOG.debug("Parsed request {} header {} length={}", getRequest(), getFrameType(), getContentLength());
                     return true;
                 }
                 default:
diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ParamsContentParser.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ParamsContentParser.java
index 4678ad5..dcf34fe 100644
--- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ParamsContentParser.java
+++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ParamsContentParser.java
@@ -20,11 +20,44 @@
 
 import java.nio.ByteBuffer;
 import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
 
 import org.eclipse.jetty.http.HttpField;
 import org.eclipse.jetty.util.log.Log;
 import org.eclipse.jetty.util.log.Logger;
 
+/**
+ * <p>Parser for the PARAMS frame body.</p>
+ * <pre>
+ * struct small_name_small_value_params_body {
+ *     ubyte nameLength;
+ *     ubyte valueLength;
+ *     ubyte[] nameBytes;
+ *     ubyte[] valueBytes;
+ * }
+ *
+ * struct small_name_large_value_params_body {
+ *     ubyte nameLength;
+ *     uint valueLength;
+ *     ubyte[] nameBytes;
+ *     ubyte[] valueBytes;
+ * }
+ *
+ * struct large_name_small_value_params_body {
+ *     uint nameLength;
+ *     ubyte valueLength;
+ *     ubyte[] nameBytes;
+ *     ubyte[] valueBytes;
+ * }
+ *
+ * struct large_name_large_value_params_body {
+ *     uint nameLength;
+ *     uint valueLength;
+ *     ubyte[] nameBytes;
+ *     ubyte[] valueBytes;
+ * }
+ * </pre>
+ */
 public class ParamsContentParser extends ContentParser
 {
     private static final Logger LOG = Log.getLogger(ParamsContentParser.class);
@@ -179,7 +212,7 @@
                 }
                 case PARAM:
                 {
-                    Charset utf8 = Charset.forName("UTF-8");
+                    Charset utf8 = StandardCharsets.UTF_8;
                     onParam(new String(nameBytes, utf8), new String(valueBytes, utf8));
                     partialReset();
                     if (length == 0)
diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/Parser.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/Parser.java
index 402f3a4..be2ac48 100644
--- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/Parser.java
+++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/Parser.java
@@ -22,6 +22,8 @@
 
 import org.eclipse.jetty.fcgi.FCGI;
 import org.eclipse.jetty.http.HttpField;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
 
 /**
  * <p>The FastCGI protocol exchanges <em>frames</em>.</p>
@@ -39,9 +41,14 @@
  * </pre>
  * <p>Depending on the {@code type}, the content may have a different format,
  * so there are specialized content parsers.</p>
+ *
+ * @see HeaderParser
+ * @see ContentParser
  */
 public abstract class Parser
 {
+    private static final Logger LOG = Log.getLogger(Parser.class);
+
     protected final HeaderParser headerParser = new HeaderParser();
     private State state = State.HEADER;
     private int padding;
@@ -73,6 +80,9 @@
                     else
                     {
                         ContentParser.Result result = contentParser.parse(buffer);
+                        if (LOG.isDebugEnabled())
+                            LOG.debug("Parsed request {} content {} result={}", headerParser.getRequest(), headerParser.getFrameType(), result);
+
                         if (result == ContentParser.Result.PENDING)
                         {
                             // Not enough data, signal to read/parse more.
diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ResponseContentParser.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ResponseContentParser.java
index def4394..6d0fefa 100644
--- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ResponseContentParser.java
+++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ResponseContentParser.java
@@ -35,8 +35,8 @@
 import org.eclipse.jetty.util.log.Logger;
 
 /**
- * <p>The parser for STDOUT type frames.</p>
- * <p>STDOUT frames contain both the HTTP headers (but not the response line)
+ * <p>The parser for STDOUT type frame bodies.</p>
+ * <p>STDOUT frame bodies contain both the HTTP headers (but not the response line)
  * and the HTTP content (either Content-Length delimited or chunked).</p>
  * <p>For this reason, a special HTTP parser is used to parse the frames body.
  * This special HTTP parser is configured to skip the response line, and to
@@ -99,12 +99,12 @@
 
         public boolean parse(ByteBuffer buffer)
         {
-            if (LOG.isDebugEnabled())
-                LOG.debug("Response {} {} content {} {}", request, FCGI.StreamType.STD_OUT, state, buffer);
-
             int remaining = buffer.remaining();
             while (remaining > 0)
             {
+                if (LOG.isDebugEnabled())
+                    LOG.debug("Response {} {}, state {} {}", request, FCGI.StreamType.STD_OUT, state, buffer);
+
                 switch (state)
                 {
                     case HEADERS:
diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/StreamContentParser.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/StreamContentParser.java
index ae7f7bc..70602a6 100644
--- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/StreamContentParser.java
+++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/StreamContentParser.java
@@ -25,8 +25,8 @@
 import org.eclipse.jetty.util.log.Logger;
 
 /**
- * <p>A stream content parser parses frames of type STDIN, STDOUT and STDERR.</p>
- * <p>STDOUT frames are handled specially by {@link ResponseContentParser}.
+ * <p>A stream content parser parses frame bodies of type STDIN, STDOUT and STDERR.</p>
+ * <p>STDOUT frame bodies are handled specially by {@link ResponseContentParser}.
  */
 public class StreamContentParser extends ContentParser
 {
diff --git a/jetty-gcloud/gcloud-session-manager/src/main/java/org/eclipse/jetty/gcloud/session/GCloudSessionManager.java b/jetty-gcloud/gcloud-session-manager/src/main/java/org/eclipse/jetty/gcloud/session/GCloudSessionManager.java
index b6b39a9..a6137e4 100644
--- a/jetty-gcloud/gcloud-session-manager/src/main/java/org/eclipse/jetty/gcloud/session/GCloudSessionManager.java
+++ b/jetty-gcloud/gcloud-session-manager/src/main/java/org/eclipse/jetty/gcloud/session/GCloudSessionManager.java
@@ -829,6 +829,7 @@
          if (memSession == null)
          {
              memSession = session;
+             _sessionsStats.increment();
          }
 
         //final check
@@ -1008,6 +1009,7 @@
                     {
                         //indicate that the session was reinflated
                         session.didActivate();
+                        _sessionsStats.increment();
                         LOG.debug("getSession({}): loaded session from cluster", idInCluster);
                     }
                     return session;
diff --git a/jetty-infinispan/src/main/java/org/eclipse/jetty/session/infinispan/InfinispanSessionManager.java b/jetty-infinispan/src/main/java/org/eclipse/jetty/session/infinispan/InfinispanSessionManager.java
index 039263a..072d0f1 100644
--- a/jetty-infinispan/src/main/java/org/eclipse/jetty/session/infinispan/InfinispanSessionManager.java
+++ b/jetty-infinispan/src/main/java/org/eclipse/jetty/session/infinispan/InfinispanSessionManager.java
@@ -664,7 +664,7 @@
         for (String candidateId:candidateIds)
         {
             if (LOG.isDebugEnabled())
-                LOG.debug("Session {} expired ", candidateId);
+                LOG.debug("Session {} candidate for expiry", candidateId);
             
             Session candidateSession = _sessions.get(candidateId);
             if (candidateSession != null)
@@ -691,6 +691,7 @@
                     if (LOG.isDebugEnabled()) LOG.debug("Session({}) not local to this session manager, removing from local memory", candidateId);
                     candidateSession.willPassivate();
                     _sessions.remove(candidateSession.getClusterId());
+                    _sessionsStats.decrement();
                 }
 
             }
@@ -870,6 +871,7 @@
                     {
                         //indicate that the session was reinflated
                         session.didActivate();
+                        _sessionsStats.increment();
                         LOG.debug("getSession({}): loaded session from cluster", idInCluster);
                     }
                     return session;
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractEndPoint.java b/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractEndPoint.java
index a2ba180..ceab75b 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractEndPoint.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractEndPoint.java
@@ -394,7 +394,7 @@
         Connection old_connection = getConnection();
 
         if (LOG.isDebugEnabled())
-            LOG.debug("{} upgradeing from {} to {}", this, old_connection, newConnection);
+            LOG.debug("{} upgrading from {} to {}", this, old_connection, newConnection);
 
         ByteBuffer prefilled = (old_connection instanceof Connection.UpgradeFrom)
                 ?((Connection.UpgradeFrom)old_connection).onUpgradeFrom():null;
diff --git a/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/NoSqlSessionManager.java b/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/NoSqlSessionManager.java
index 7d5e9dc..51b8d60 100644
--- a/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/NoSqlSessionManager.java
+++ b/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/NoSqlSessionManager.java
@@ -96,7 +96,10 @@
                     session=race;
                 }
                 else
+                {
                     __log.debug("session loaded ", idInCluster);
+                    _sessionsStats.increment();
+                }
                 
                 //check if the session we just loaded has actually expired, maybe while we weren't running
                 if (getMaxInactiveInterval() > 0 && session.getAccessed() > 0 && ((getMaxInactiveInterval()*1000L)+session.getAccessed()) < System.currentTimeMillis())
diff --git a/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/MongoSessionIdManager.java b/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/MongoSessionIdManager.java
index d822ea7..894a3fd 100644
--- a/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/MongoSessionIdManager.java
+++ b/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/MongoSessionIdManager.java
@@ -206,7 +206,7 @@
     protected void scavenge()
     {
         long now = System.currentTimeMillis();
-        __log.debug("SessionIdManager:scavenge:at {}", now);        
+        __log.debug(getWorkerName()+":SessionIdManager:scavenge:at {}", now);        
         /*
          * run a query returning results that:
          *  - are in the known list of sessionIds
@@ -258,7 +258,7 @@
                         
         for ( DBObject session : checkSessions )
         {             
-            __log.debug("SessionIdManager:scavenge: expiring session {}", (String)session.get(MongoSessionManager.__ID));
+            __log.debug(getWorkerName()+":SessionIdManager:scavenge: {} expiring session {}", atTime,(String)session.get(MongoSessionManager.__ID));
             expireAll((String)session.get(MongoSessionManager.__ID));
         }            
     }
diff --git a/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/MongoSessionManager.java b/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/MongoSessionManager.java
index df8f917..8c44e9f 100644
--- a/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/MongoSessionManager.java
+++ b/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/MongoSessionManager.java
@@ -268,7 +268,9 @@
                         if (currentMaxIdle != null && getMaxInactiveInterval() > 0 && getMaxInactiveInterval() < currentMaxIdle)
                             sets.put(__MAX_IDLE, getMaxInactiveInterval());
                         if (currentExpiry != null && expiry > 0 && expiry != currentExpiry)
+                        {
                             sets.put(__EXPIRY, expiry);
+                        }
                     }
                 }
                 
diff --git a/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ConnectHandler.java b/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ConnectHandler.java
index d6dd814..7b19662 100644
--- a/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ConnectHandler.java
+++ b/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ConnectHandler.java
@@ -18,6 +18,7 @@
 
 package org.eclipse.jetty.proxy;
 
+import java.io.Closeable;
 import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.nio.ByteBuffer;
@@ -53,6 +54,7 @@
 import org.eclipse.jetty.server.handler.HandlerWrapper;
 import org.eclipse.jetty.util.BufferUtil;
 import org.eclipse.jetty.util.Callback;
+import org.eclipse.jetty.util.Promise;
 import org.eclipse.jetty.util.TypeUtil;
 import org.eclipse.jetty.util.log.Log;
 import org.eclipse.jetty.util.log.Logger;
@@ -162,21 +164,17 @@
     protected void doStart() throws Exception
     {
         if (executor == null)
-        {
-            setExecutor(getServer().getThreadPool());
-        }
+            executor = getServer().getThreadPool();
+
         if (scheduler == null)
-        {
-            setScheduler(new ScheduledExecutorScheduler());
-            addBean(getScheduler());
-        }
+            addBean(scheduler = new ScheduledExecutorScheduler());
+
         if (bufferPool == null)
-        {
-            setByteBufferPool(new MappedByteBufferPool());
-            addBean(getByteBufferPool());
-        }
+            addBean(bufferPool = new MappedByteBufferPool());
+
         addBean(selector = newSelectorManager());
         selector.setConnectTimeout(getConnectTimeout());
+
         super.doStart();
     }
 
@@ -193,16 +191,8 @@
             String serverAddress = request.getRequestURI();
             if (LOG.isDebugEnabled())
                 LOG.debug("CONNECT request for {}", serverAddress);
-            try
-            {
-                handleConnect(baseRequest, request, response, serverAddress);
-            }
-            catch (Exception x)
-            {
-                // TODO
-                LOG.warn("ConnectHandler " + baseRequest.getHttpURI() + " " + x);
-                LOG.debug(x);
-            }
+
+            handleConnect(baseRequest, request, response, serverAddress);
         }
         else
         {
@@ -251,32 +241,40 @@
                 return;
             }
 
-            SocketChannel channel = SocketChannel.open();
-            channel.socket().setTcpNoDelay(true);
-            channel.configureBlocking(false);
-
-            AsyncContext asyncContext = request.startAsync();
-            asyncContext.setTimeout(0);
-
             HttpTransport transport = baseRequest.getHttpChannel().getHttpTransport();
-            
             // TODO Handle CONNECT over HTTP2!
             if (!(transport instanceof HttpConnection))
             {
                 if (LOG.isDebugEnabled())
-                    LOG.debug("CONNECT forbidden for {}", transport);
+                    LOG.debug("CONNECT not supported for {}", transport);
                 sendConnectResponse(request, response, HttpServletResponse.SC_FORBIDDEN);
                 return;
             }
 
-            InetSocketAddress address = newConnectAddress(host, port);
+            AsyncContext asyncContext = request.startAsync();
+            asyncContext.setTimeout(0);
+
             if (LOG.isDebugEnabled())
-                LOG.debug("Connecting to {}", address);
-            ConnectContext connectContext = new ConnectContext(request, response, asyncContext, (HttpConnection)transport);
-            if (channel.connect(address))
-                selector.accept(channel, connectContext);
-            else
-                selector.connect(channel, connectContext);
+                LOG.debug("Connecting to {}:{}", host, port);
+
+            connectToServer(request, host, port, new Promise<SocketChannel>()
+            {
+                @Override
+                public void succeeded(SocketChannel channel)
+                {
+                    ConnectContext connectContext = new ConnectContext(request, response, asyncContext, (HttpConnection)transport);
+                    if (channel.isConnected())
+                        selector.accept(channel, connectContext);
+                    else
+                        selector.connect(channel, connectContext);
+                }
+
+                @Override
+                public void failed(Throwable x)
+                {
+                    onConnectFailure(request, response, asyncContext, x);
+                }
+            });
         }
         catch (Exception x)
         {
@@ -284,37 +282,59 @@
         }
     }
 
-    /* ------------------------------------------------------------ */
-    /** Create the address the connect channel will connect to.
-     * @param host The host from the connect request
-     * @param port The port from the connect request
+    protected void connectToServer(HttpServletRequest request, String host, int port, Promise<SocketChannel> promise)
+    {
+        SocketChannel channel = null;
+        try
+        {
+            channel = SocketChannel.open();
+            channel.socket().setTcpNoDelay(true);
+            channel.configureBlocking(false);
+            InetSocketAddress address = newConnectAddress(host, port);
+            channel.connect(address);
+            promise.succeeded(channel);
+        }
+        catch (Throwable x)
+        {
+            close(channel);
+            promise.failed(x);
+        }
+    }
+
+    private void close(Closeable closeable)
+    {
+        try
+        {
+            if (closeable != null)
+                closeable.close();
+        }
+        catch (Throwable x)
+        {
+            LOG.ignore(x);
+        }
+    }
+
+    /**
+     * Creates the server address to connect to.
+     *
+     * @param host The host from the CONNECT request
+     * @param port The port from the CONNECT request
      * @return The InetSocketAddress to connect to.
      */
     protected InetSocketAddress newConnectAddress(String host, int port)
     {
         return new InetSocketAddress(host, port);
     }
-    
+
     protected void onConnectSuccess(ConnectContext connectContext, UpstreamConnection upstreamConnection)
     {
-        HttpConnection httpConnection = connectContext.getHttpConnection();
-        ByteBuffer requestBuffer = httpConnection.getRequestBuffer();
-        ByteBuffer buffer = BufferUtil.EMPTY_BUFFER;
-        int remaining = requestBuffer.remaining();
-        if (remaining > 0)
-        {
-            buffer = bufferPool.acquire(remaining, requestBuffer.isDirect());
-            BufferUtil.flipToFill(buffer);
-            buffer.put(requestBuffer);
-            buffer.flip();
-        }
-
         ConcurrentMap<String, Object> context = connectContext.getContext();
         HttpServletRequest request = connectContext.getRequest();
         prepareContext(request, context);
 
+        HttpConnection httpConnection = connectContext.getHttpConnection();
         EndPoint downstreamEndPoint = httpConnection.getEndPoint();
-        DownstreamConnection downstreamConnection = newDownstreamConnection(downstreamEndPoint, context, buffer);
+        DownstreamConnection downstreamConnection = newDownstreamConnection(downstreamEndPoint, context);
         downstreamConnection.setInputBufferSize(getBufferSize());
 
         upstreamConnection.setConnection(downstreamConnection);
@@ -326,6 +346,7 @@
         sendConnectResponse(request, response, HttpServletResponse.SC_OK);
 
         upgradeConnection(request, response, downstreamConnection);
+
         connectContext.getAsyncContext().complete();
     }
 
@@ -351,7 +372,8 @@
         }
         catch (IOException x)
         {
-            // TODO: nothing we can do, close the connection
+            if (LOG.isDebugEnabled())
+                LOG.debug("Could not send CONNECT response", x);
         }
     }
 
@@ -369,9 +391,9 @@
         return true;
     }
 
-    protected DownstreamConnection newDownstreamConnection(EndPoint endPoint, ConcurrentMap<String, Object> context, ByteBuffer buffer)
+    protected DownstreamConnection newDownstreamConnection(EndPoint endPoint, ConcurrentMap<String, Object> context)
     {
-        return new DownstreamConnection(endPoint, getExecutor(), getByteBufferPool(), context, buffer);
+        return new DownstreamConnection(endPoint, getExecutor(), getByteBufferPool(), context);
     }
 
     protected UpstreamConnection newUpstreamConnection(EndPoint endPoint, ConnectContext connectContext)
@@ -398,13 +420,17 @@
      *
      * @param endPoint the endPoint to read from
      * @param buffer   the buffer to read data into
+     * @param context  the context information related to the connection
      * @return the number of bytes read (possibly 0 since the read is non-blocking)
      *         or -1 if the channel has been closed remotely
      * @throws IOException if the endPoint cannot be read
      */
-    protected int read(EndPoint endPoint, ByteBuffer buffer) throws IOException
+    protected int read(EndPoint endPoint, ByteBuffer buffer, ConcurrentMap<String, Object> context) throws IOException
     {
-        return endPoint.fill(buffer);
+        int read = endPoint.fill(buffer);
+        if (LOG.isDebugEnabled())
+            LOG.debug("{} read {} bytes", this, read);
+        return read;
     }
 
     /**
@@ -413,8 +439,9 @@
      * @param endPoint the endPoint to write to
      * @param buffer   the buffer to write
      * @param callback the completion callback to invoke
+     * @param context  the context information related to the connection
      */
-    protected void write(EndPoint endPoint, ByteBuffer buffer, Callback callback)
+    protected void write(EndPoint endPoint, ByteBuffer buffer, Callback callback, ConcurrentMap<String, Object> context)
     {
         if (LOG.isDebugEnabled())
             LOG.debug("{} writing {} bytes", this, buffer.remaining());
@@ -498,14 +525,9 @@
         @Override
         protected void connectionFailed(SelectableChannel channel, final Throwable ex, final Object attachment)
         {
-            getExecutor().execute(new Runnable()
-            {
-                public void run()
-                {
-                    ConnectContext connectContext = (ConnectContext)attachment;
-                    onConnectFailure(connectContext.request, connectContext.response, connectContext.asyncContext, ex);
-                }
-            });
+            close(channel);
+            ConnectContext connectContext = (ConnectContext)attachment;
+            onConnectFailure(connectContext.request, connectContext.response, connectContext.asyncContext, ex);
         }
     }
 
@@ -565,37 +587,36 @@
         public void onOpen()
         {
             super.onOpen();
-            getExecutor().execute(new Runnable()
-            {
-                public void run()
-                {
-                    onConnectSuccess(connectContext, UpstreamConnection.this);
-                    fillInterested();
-                }
-            });
+            onConnectSuccess(connectContext, UpstreamConnection.this);
+            fillInterested();
         }
 
         @Override
         protected int read(EndPoint endPoint, ByteBuffer buffer) throws IOException
         {
-            return ConnectHandler.this.read(endPoint, buffer);
+            return ConnectHandler.this.read(endPoint, buffer, getContext());
         }
 
         @Override
         protected void write(EndPoint endPoint, ByteBuffer buffer,Callback callback)
         {
-            ConnectHandler.this.write(endPoint, buffer, callback);
+            ConnectHandler.this.write(endPoint, buffer, callback, getContext());
         }
     }
 
-    public class DownstreamConnection extends ProxyConnection
+    public class DownstreamConnection extends ProxyConnection implements Connection.UpgradeTo
     {
-        private final ByteBuffer buffer;
+        private ByteBuffer buffer;
 
-        public DownstreamConnection(EndPoint endPoint, Executor executor, ByteBufferPool bufferPool, ConcurrentMap<String, Object> context, ByteBuffer buffer)
+        public DownstreamConnection(EndPoint endPoint, Executor executor, ByteBufferPool bufferPool, ConcurrentMap<String, Object> context)
         {
             super(endPoint, executor, bufferPool, context);
-            this.buffer = buffer;
+        }
+
+        @Override
+        public void onUpgradeTo(ByteBuffer buffer)
+        {
+            this.buffer = buffer == null ? BufferUtil.EMPTY_BUFFER : buffer;
         }
 
         @Override
@@ -627,13 +648,13 @@
         @Override
         protected int read(EndPoint endPoint, ByteBuffer buffer) throws IOException
         {
-            return ConnectHandler.this.read(endPoint, buffer);
+            return ConnectHandler.this.read(endPoint, buffer, getContext());
         }
 
         @Override
         protected void write(EndPoint endPoint, ByteBuffer buffer, Callback callback)
         {
-            ConnectHandler.this.write(endPoint, buffer, callback);
+            ConnectHandler.this.write(endPoint, buffer, callback, getContext());
         }
     }
 }
diff --git a/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ConnectHandlerTest.java b/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ConnectHandlerTest.java
index f601975..780e706 100644
--- a/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ConnectHandlerTest.java
+++ b/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ConnectHandlerTest.java
@@ -27,6 +27,8 @@
 import java.net.InetAddress;
 import java.net.Socket;
 import java.net.UnknownHostException;
+import java.nio.ByteBuffer;
+import java.nio.channels.SocketChannel;
 import java.nio.charset.StandardCharsets;
 import java.util.Locale;
 import java.util.concurrent.ConcurrentMap;
@@ -36,12 +38,15 @@
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.eclipse.jetty.io.EndPoint;
 import org.eclipse.jetty.server.Request;
 import org.eclipse.jetty.server.Server;
 import org.eclipse.jetty.server.ServerConnector;
 import org.eclipse.jetty.server.handler.AbstractHandler;
 import org.eclipse.jetty.toolchain.test.http.SimpleHttpResponse;
 import org.eclipse.jetty.util.B64Code;
+import org.eclipse.jetty.util.Callback;
+import org.eclipse.jetty.util.Promise;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
@@ -631,12 +636,33 @@
             }
 
             @Override
+            protected void connectToServer(HttpServletRequest request, String host, int port, Promise<SocketChannel> promise)
+            {
+                Assert.assertEquals(contextValue, request.getAttribute(contextKey));
+                super.connectToServer(request, host, port, promise);
+            }
+
+            @Override
             protected void prepareContext(HttpServletRequest request, ConcurrentMap<String, Object> context)
             {
                 // Transfer data from the HTTP request to the connection context
                 Assert.assertEquals(contextValue, request.getAttribute(contextKey));
                 context.put(contextKey, request.getAttribute(contextKey));
             }
+
+            @Override
+            protected int read(EndPoint endPoint, ByteBuffer buffer, ConcurrentMap<String, Object> context) throws IOException
+            {
+                Assert.assertEquals(contextValue, context.get(contextKey));
+                return super.read(endPoint, buffer, context);
+            }
+
+            @Override
+            protected void write(EndPoint endPoint, ByteBuffer buffer, Callback callback, ConcurrentMap<String, Object> context)
+            {
+                Assert.assertEquals(contextValue, context.get(contextKey));
+                super.write(endPoint, buffer, callback, context);
+            }
         });
         proxy.start();
 
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionIdManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionIdManager.java
index 99108d8..3bfb8ba 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionIdManager.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionIdManager.java
@@ -1250,6 +1250,8 @@
      */
     private void scavenge ()
     {
+        Set<String> candidateIds = getAllCandidateExpiredSessionIds();
+        
         Connection connection = null;
         try
         {
@@ -1283,7 +1285,7 @@
                         }
                     }
                 }
-                scavengeSessions(expiredSessionIds, false);
+                scavengeSessions(candidateIds, expiredSessionIds, false);
 
 
                 //Pass 2: find sessions that have expired a while ago for which this node was their last manager
@@ -1306,7 +1308,7 @@
                                 if (LOG.isDebugEnabled()) LOG.debug ("Found expired sessionId="+sessionId+" last managed by "+getWorkerName());
                             }
                         }
-                        scavengeSessions(expiredSessionIds, false);
+                        scavengeSessions(candidateIds, expiredSessionIds, false);
                     }
 
 
@@ -1329,9 +1331,13 @@
                                 if (LOG.isDebugEnabled()) LOG.debug ("Found expired sessionId="+sessionId);
                             }
                         }
-                        scavengeSessions(expiredSessionIds, true);
+                        scavengeSessions(candidateIds, expiredSessionIds, true);
                     }
                 }
+                
+                //Tell session managers to check remaining sessions in memory that may have expired 
+                //but are no longer in the database
+                scavengeSessions(candidateIds);
             }
         }
         catch (Exception e)
@@ -1363,24 +1369,20 @@
     /**
      * @param expiredSessionIds
      */
-    private void scavengeSessions (Set<String> expiredSessionIds, boolean forceDelete)
+    private void scavengeSessions (Set<String> candidateIds, Set<String> expiredSessionIds, boolean forceDelete)
     {       
         Set<String> remainingIds = new HashSet<String>(expiredSessionIds);
-        Handler[] contexts = _server.getChildHandlersByClass(ContextHandler.class);
-        for (int i=0; contexts!=null && i<contexts.length; i++)
+        Set<SessionManager> managers = getAllSessionManagers();
+        for (SessionManager m:managers)
         {
-            SessionHandler sessionHandler = ((ContextHandler)contexts[i]).getChildHandlerByClass(SessionHandler.class);
-            if (sessionHandler != null)
+            Set<String> successfullyExpiredIds = ((JDBCSessionManager)m).expire(expiredSessionIds);
+            if (successfullyExpiredIds != null)
             {
-                SessionManager manager = sessionHandler.getSessionManager();
-                if (manager != null && manager instanceof JDBCSessionManager)
-                {
-                    Set<String> successfullyExpiredIds = ((JDBCSessionManager)manager).expire(expiredSessionIds);
-                    if (successfullyExpiredIds != null)
-                        remainingIds.removeAll(successfullyExpiredIds);
-                }
+                remainingIds.removeAll(successfullyExpiredIds);
+                candidateIds.removeAll(successfullyExpiredIds);
             }
         }
+    
 
         //Any remaining ids are of those sessions that no context removed
         if (!remainingIds.isEmpty() && forceDelete)
@@ -1402,6 +1404,63 @@
             }
         }
     }
+    
+    /**
+     * These are the session ids that the session managers thought had 
+     * expired, but were not expired in the database. This could be
+     * because the session is live on another node, or that the
+     * session no longer exists in the database because some other
+     * node removed it.
+     * @param candidateIds
+     */
+    private void scavengeSessions (Set<String> candidateIds)
+    {
+        if (candidateIds.isEmpty())
+            return;
+        
+        
+        Set<SessionManager> managers = getAllSessionManagers();
+        
+        for (SessionManager m:managers)
+        {
+            //tell the session managers to check the sessions that have expired in memory
+            //if they are no longer in the database, they should be removed
+            ((JDBCSessionManager)m).expireCandidates(candidateIds);
+        }
+    }
+    
+    private Set<String>  getAllCandidateExpiredSessionIds()
+    {
+        HashSet<String> candidateIds = new HashSet<>();
+        
+        Set<SessionManager> managers = getAllSessionManagers();
+        
+        for (SessionManager m:managers)
+        {
+            candidateIds.addAll(((JDBCSessionManager)m).getCandidateExpiredIds());
+        }
+        
+        return candidateIds;
+    }
+    
+    
+    private Set<SessionManager> getAllSessionManagers()
+    {
+        HashSet<SessionManager> managers = new HashSet<>();
+    
+        Handler[] contexts = _server.getChildHandlersByClass(ContextHandler.class);
+        for (int i=0; contexts!=null && i<contexts.length; i++)
+        {
+            SessionHandler sessionHandler = ((ContextHandler)contexts[i]).getChildHandlerByClass(SessionHandler.class);
+            if (sessionHandler != null)
+            {
+                SessionManager manager = sessionHandler.getSessionManager();
+                if (manager != null && manager instanceof JDBCSessionManager)
+                    managers.add(manager);
+            }
+        }
+        return managers;
+    }
 
 
    
@@ -1411,7 +1470,7 @@
     {
         if (expiredIds == null || expiredIds.isEmpty())
             return;
-
+        
         String[] ids = expiredIds.toArray(new String[expiredIds.size()]);
         try (Connection con = getConnection())
         {
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java
index bae2647..6962694 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java
@@ -535,6 +535,7 @@
 
                         session.setLastNode(getSessionIdManager().getWorkerName());                            
                         _sessions.put(idInCluster, session);
+                        _sessionsStats.increment();
 
                         //update in db
                         try
@@ -569,6 +570,11 @@
             }
             else
             {
+                if (memSession != null)
+                {
+                    //Session must have been removed from db by another node
+                    removeSession(memSession, true);
+                }
                 //No session in db with matching id and context path.
                 LOG.debug("getSession({}): No session in database matching id={}",idInCluster,idInCluster);
             }
@@ -838,6 +844,7 @@
                         //loaded an expired session last managed on this node for this context, add it to the list so we can 
                         //treat it like a normal expired session
                         _sessions.put(session.getClusterId(), session);
+                        _sessionsStats.increment();
                     }
                     else
                     {
@@ -866,7 +873,54 @@
         }
     }
     
-  
+    protected void expireCandidates (Set<String> candidateIds)
+    {
+        Iterator<String> itor = candidateIds.iterator();
+        long now = System.currentTimeMillis();
+        while (itor.hasNext())
+        {
+            String id = itor.next();
+
+            //check if expired in db
+            try
+            {
+                Session memSession = _sessions.get(id);
+                if (memSession == null)
+                {
+                    continue; //no longer in memory
+                }
+
+                Session s = loadSession(id,  canonicalize(_context.getContextPath()), getVirtualHost(_context));
+                if (s == null)
+                {
+                    //session no longer exists, can be safely expired
+                    memSession.timeout();
+                }
+            }
+            catch (Exception e)
+            {
+                LOG.warn("Error checking db for expiry for session {}", id);
+            }
+        }
+    }
+    
+    protected Set<String> getCandidateExpiredIds ()
+    {
+        HashSet<String> expiredIds = new HashSet<>();
+
+        Iterator<String> itor = _sessions.keySet().iterator();
+        while (itor.hasNext())
+        {
+            String id = itor.next();
+            //check to see if session should have expired
+            Session session = _sessions.get(id);
+            if (session._expiryTime > 0 &&  System.currentTimeMillis() > session._expiryTime)
+                expiredIds.add(id);           
+        }
+        return expiredIds;
+    }
+
+
     /**
      * Load a session from the database
      * @param id the id
diff --git a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/LastAccessTimeTest.java b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/LastAccessTimeTest.java
index 25c0ad2..bb09b64 100644
--- a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/LastAccessTimeTest.java
+++ b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/LastAccessTimeTest.java
@@ -18,14 +18,6 @@
 
 package org.eclipse.jetty.server.session;
 
-import java.io.File;
-
-import org.eclipse.jetty.util.IO;
-import org.infinispan.Cache;
-import org.infinispan.configuration.cache.Configuration;
-import org.infinispan.configuration.cache.ConfigurationBuilder;
-import org.infinispan.manager.DefaultCacheManager;
-import org.infinispan.manager.EmbeddedCacheManager;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 
@@ -61,5 +53,13 @@
         super.testLastAccessTime();
     }
 
+    @Override
+    public void assertAfterScavenge(AbstractSessionManager manager)
+    {
+        //The infinispan session manager will remove a session from its local memory that was a candidate to be scavenged if
+        //it checks with the cluster and discovers that another node is managing it, so the count is 0
+        assertSessionCounts(0, 1, 1, manager);
+    }
+
     
 }
diff --git a/tests/test-sessions/test-jdbc-sessions/pom.xml b/tests/test-sessions/test-jdbc-sessions/pom.xml
index 9d4a1b8..b4a75a5 100644
--- a/tests/test-sessions/test-jdbc-sessions/pom.xml
+++ b/tests/test-sessions/test-jdbc-sessions/pom.xml
@@ -65,13 +65,13 @@
         <dependency>
             <groupId>org.apache.derby</groupId>
             <artifactId>derby</artifactId>
-            <version>10.4.1.3</version>
+            <version>10.12.1.1</version>
             <scope>test</scope>
          </dependency>
          <dependency>
             <groupId>org.apache.derby</groupId>
             <artifactId>derbytools</artifactId>
-            <version>10.4.1.3</version>
+            <version>10.12.1.1</version>
             <scope>test</scope>
        </dependency>
     <dependency>
diff --git a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ClientCrossContextSessionTest.java b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ClientCrossContextSessionTest.java
index eb4109b..a5348ef 100644
--- a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ClientCrossContextSessionTest.java
+++ b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ClientCrossContextSessionTest.java
@@ -18,9 +18,6 @@
 
 package org.eclipse.jetty.server.session;
 
-import java.sql.DriverManager;
-import java.sql.SQLException;
-
 import org.junit.After;
 import org.junit.Test;
 
@@ -46,12 +43,8 @@
     @After
     public void tearDown() throws Exception 
     {
-        try
-        {
-            DriverManager.getConnection( "jdbc:derby:sessions;shutdown=true" );
-        }
-        catch( SQLException expected )
-        {
-        }
+        JdbcTestServer.shutdown(null);
     }
+    
+   
 }
diff --git a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/DirtyAttributeTest.java b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/DirtyAttributeTest.java
index 5d2379a..e123a80 100644
--- a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/DirtyAttributeTest.java
+++ b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/DirtyAttributeTest.java
@@ -38,6 +38,7 @@
 import org.eclipse.jetty.client.api.ContentResponse;
 import org.eclipse.jetty.client.api.Request;
 import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.junit.After;
 import org.junit.Test;
 
 
@@ -127,6 +128,14 @@
         }
     }
     
+    
+    @After
+    public void tearDown() throws Exception 
+    {
+        JdbcTestServer.shutdown(null);
+    }
+    
+    
     public static class TestValue implements HttpSessionActivationListener, HttpSessionBindingListener, Serializable
     {
         int passivates = 0;
diff --git a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ForwardedSessionTest.java b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ForwardedSessionTest.java
index 7d2f42b..de843b8 100644
--- a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ForwardedSessionTest.java
+++ b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ForwardedSessionTest.java
@@ -19,6 +19,7 @@
 
 package org.eclipse.jetty.server.session;
 
+import org.junit.After;
 import org.junit.Test;
 
 /**
@@ -45,6 +46,12 @@
     }
     
     
+    @After
+    public void tearDown() throws Exception 
+    {
+        JdbcTestServer.shutdown(null);
+    }
+    
     
 
 }
diff --git a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ImmortalSessionTest.java b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ImmortalSessionTest.java
index cabd724..fd4b53e 100644
--- a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ImmortalSessionTest.java
+++ b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ImmortalSessionTest.java
@@ -18,9 +18,6 @@
 
 package org.eclipse.jetty.server.session;
 
-import java.sql.DriverManager;
-import java.sql.SQLException;
-
 import org.junit.After;
 import org.junit.Test;
 
@@ -46,12 +43,7 @@
     @After
     public void tearDown() throws Exception 
     {
-        try
-        {
-            DriverManager.getConnection( "jdbc:derby:sessions;shutdown=true" );
-        }
-        catch( SQLException expected )
-        {
-        }
+        JdbcTestServer.shutdown(null);
     }
+   
 }
diff --git a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/InvalidationSessionTest.java b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/InvalidationSessionTest.java
index 8075dbd..dd68fff 100644
--- a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/InvalidationSessionTest.java
+++ b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/InvalidationSessionTest.java
@@ -18,9 +18,6 @@
 
 package org.eclipse.jetty.server.session;
 
-import java.sql.DriverManager;
-import java.sql.SQLException;
-
 import org.junit.After;
 import org.junit.Test;
 
@@ -60,12 +57,6 @@
     @After
     public void tearDown() throws Exception 
     {
-        try
-        {
-            DriverManager.getConnection( "jdbc:derby:sessions;shutdown=true" );
-        }
-        catch( SQLException expected )
-        {
-        }
+        JdbcTestServer.shutdown(null);
     }
 }
diff --git a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/JdbcTestServer.java b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/JdbcTestServer.java
index 5b55861..03e9ff1 100644
--- a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/JdbcTestServer.java
+++ b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/JdbcTestServer.java
@@ -22,6 +22,7 @@
 import java.sql.DriverManager;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
+import java.sql.SQLException;
 import java.util.HashSet;
 import java.util.Set;
 
@@ -35,7 +36,8 @@
 public class JdbcTestServer extends AbstractTestServer
 {
     public static final String DRIVER_CLASS = "org.apache.derby.jdbc.EmbeddedDriver";
-    public static final String DEFAULT_CONNECTION_URL = "jdbc:derby:sessions;create=true";
+    public static final String DEFAULT_CONNECTION_URL = "jdbc:derby:memory:sessions;create=true";
+    public static final String DEFAULT_SHUTDOWN_URL = "jdbc:derby:memory:sessions;drop=true";
     public static final int SAVE_INTERVAL = 1;
     
     
@@ -43,6 +45,26 @@
     {
         System.setProperty("derby.system.home", MavenTestingUtils.getTargetFile("test-derby").getAbsolutePath());
     }
+    
+    
+    public static void shutdown (String connectionUrl)
+    throws Exception
+    {
+        if (connectionUrl == null)
+            connectionUrl = DEFAULT_SHUTDOWN_URL;
+        
+        try
+        {
+            DriverManager.getConnection(connectionUrl);
+        }
+        catch( SQLException expected )
+        {
+            if (!"08006".equals(expected.getSQLState()))
+            {
+               throw expected;
+            }
+        }
+    }
 
     
     public JdbcTestServer(int port)
diff --git a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/LastAccessTimeTest.java b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/LastAccessTimeTest.java
index 541c1ef..6939fb4 100644
--- a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/LastAccessTimeTest.java
+++ b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/LastAccessTimeTest.java
@@ -18,9 +18,6 @@
 
 package org.eclipse.jetty.server.session;
 
-import java.sql.DriverManager;
-import java.sql.SQLException;
-
 import org.junit.After;
 import org.junit.Test;
 
@@ -37,20 +34,13 @@
     @Test
     public void testLastAccessTime() throws Exception
     {
-        // Log.getLog().setDebugEnabled(true);
         super.testLastAccessTime();
     }
     
     @After
     public void tearDown() throws Exception 
     {
-        try
-        {
-            DriverManager.getConnection( "jdbc:derby:sessions;shutdown=true" );
-        }
-        catch( SQLException expected )
-        {
-        }
+        JdbcTestServer.shutdown(null);
     }
     
 }
diff --git a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/LocalSessionScavengingTest.java b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/LocalSessionScavengingTest.java
index 87eec2c..ac89427 100644
--- a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/LocalSessionScavengingTest.java
+++ b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/LocalSessionScavengingTest.java
@@ -18,9 +18,6 @@
 
 package org.eclipse.jetty.server.session;
 
-import java.sql.DriverManager;
-import java.sql.SQLException;
-
 import org.junit.After;
 import org.junit.Test;
 
@@ -56,16 +53,11 @@
     {
         super.testLocalSessionsScavenging();
     }
+
     
     @After
     public void tearDown() throws Exception 
     {
-        try
-        {
-            DriverManager.getConnection( "jdbc:derby:sessions;shutdown=true" );
-        }
-        catch( SQLException expected )
-        {
-        }
+        JdbcTestServer.shutdown(null);
     }
 }
diff --git a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/MaxInactiveMigrationTest.java b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/MaxInactiveMigrationTest.java
index 6256945..b32500a 100644
--- a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/MaxInactiveMigrationTest.java
+++ b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/MaxInactiveMigrationTest.java
@@ -23,8 +23,6 @@
 
 import java.io.IOException;
 import java.io.PrintWriter;
-import java.sql.DriverManager;
-import java.sql.SQLException;
 
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
@@ -81,13 +79,8 @@
         testServer1.stop();
         testServer2.stop();
         client.stop();
-        try
-        {
-            DriverManager.getConnection( "jdbc:derby:sessions;shutdown=true" );
-        }
-        catch( SQLException expected )
-        {
-        }
+
+        JdbcTestServer.shutdown(null);
     }
 
 
diff --git a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ModifyMaxInactiveIntervalTest.java b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ModifyMaxInactiveIntervalTest.java
index a39b655..d777a61 100644
--- a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ModifyMaxInactiveIntervalTest.java
+++ b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ModifyMaxInactiveIntervalTest.java
@@ -33,6 +33,7 @@
 import org.eclipse.jetty.client.api.ContentResponse;
 import org.eclipse.jetty.client.api.Request;
 import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.junit.After;
 import org.junit.Test;
 
 
@@ -103,6 +104,13 @@
         }
     }
     
+    
+    @After
+    public void tearDown() throws Exception 
+    {
+        JdbcTestServer.shutdown(null);
+    }
+    
     public static class TestModServlet extends HttpServlet
     {
         @Override
diff --git a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/NewSessionTest.java b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/NewSessionTest.java
index fc05235..5a6006c 100644
--- a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/NewSessionTest.java
+++ b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/NewSessionTest.java
@@ -18,9 +18,6 @@
 
 package org.eclipse.jetty.server.session;
 
-import java.sql.DriverManager;
-import java.sql.SQLException;
-
 import org.junit.After;
 import org.junit.Test;
 
@@ -46,12 +43,7 @@
     @After
     public void tearDown() throws Exception 
     {
-        try
-        {
-            DriverManager.getConnection( "jdbc:derby:sessions;shutdown=true" );
-        }
-        catch( SQLException expected )
-        {
-        }
+        JdbcTestServer.shutdown(null);
     }
+  
 }
diff --git a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/OrphanedSessionTest.java b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/OrphanedSessionTest.java
index 391f3e0..4042f37 100644
--- a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/OrphanedSessionTest.java
+++ b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/OrphanedSessionTest.java
@@ -18,9 +18,6 @@
 
 package org.eclipse.jetty.server.session;
 
-import java.sql.DriverManager;
-import java.sql.SQLException;
-
 import org.junit.After;
 import org.junit.Test;
 
@@ -43,12 +40,6 @@
     @After
     public void tearDown() throws Exception 
     {
-        try
-        {
-            DriverManager.getConnection( "jdbc:derby:sessions;shutdown=true" );
-        }
-        catch( SQLException expected )
-        {
-        }
+        JdbcTestServer.shutdown(null);
     }
 }
diff --git a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ProxySerializationTest.java b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ProxySerializationTest.java
index 38db019..6efffa4 100644
--- a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ProxySerializationTest.java
+++ b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ProxySerializationTest.java
@@ -20,6 +20,7 @@
 package org.eclipse.jetty.server.session;
 
 import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.junit.After;
 import org.junit.Test;
 
 /**
@@ -55,4 +56,11 @@
         super.testProxySerialization();
     }
 
+ 
+    
+    @After
+    public void tearDown() throws Exception 
+    {
+        JdbcTestServer.shutdown(null);
+    }
 }
diff --git a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ReentrantRequestSessionTest.java b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ReentrantRequestSessionTest.java
index dced30d..82b3d5f 100644
--- a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ReentrantRequestSessionTest.java
+++ b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ReentrantRequestSessionTest.java
@@ -18,9 +18,6 @@
 
 package org.eclipse.jetty.server.session;
 
-import java.sql.DriverManager;
-import java.sql.SQLException;
-
 import org.junit.After;
 import org.junit.Test;
 
@@ -42,15 +39,11 @@
         super.testReentrantRequestSession();
     }
     
+    
     @After
     public void tearDown() throws Exception 
     {
-        try
-        {
-            DriverManager.getConnection( "jdbc:derby:sessions;shutdown=true" );
-        }
-        catch( SQLException expected )
-        {
-        }
+        JdbcTestServer.shutdown(null);
     }
+   
 }
diff --git a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ReloadedSessionMissingClassTest.java b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ReloadedSessionMissingClassTest.java
index 4dbec1c..44acb9d 100644
--- a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ReloadedSessionMissingClassTest.java
+++ b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ReloadedSessionMissingClassTest.java
@@ -38,6 +38,7 @@
 import org.eclipse.jetty.util.log.StdErrLog;
 import org.eclipse.jetty.util.resource.Resource;
 import org.eclipse.jetty.webapp.WebAppContext;
+import org.junit.After;
 import org.junit.Rule;
 import org.junit.Test;
 
@@ -139,4 +140,11 @@
             server1.stop();
         }
     }
+    
+    @After
+    public void tearDown() throws Exception 
+    {
+        JdbcTestServer.shutdown(null);
+    }
+    
 }
diff --git a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SaveIntervalTest.java b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SaveIntervalTest.java
index 3b02825..e031b29 100644
--- a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SaveIntervalTest.java
+++ b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SaveIntervalTest.java
@@ -35,6 +35,7 @@
 import org.eclipse.jetty.client.api.Request;
 import org.eclipse.jetty.servlet.ServletContextHandler;
 import org.eclipse.jetty.servlet.ServletHolder;
+import org.junit.After;
 import org.junit.Ignore;
 import org.junit.Test;
 
@@ -133,6 +134,12 @@
         }  
     }
     
+    @After
+    public void tearDown() throws Exception 
+    {
+        JdbcTestServer.shutdown(null);
+    }
+    
     public static class TestSaveIntervalServlet extends HttpServlet
     {
         public HttpSession _session;
diff --git a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ServerCrossContextSessionTest.java b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ServerCrossContextSessionTest.java
index 83c6944..497881f 100644
--- a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ServerCrossContextSessionTest.java
+++ b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/ServerCrossContextSessionTest.java
@@ -18,9 +18,6 @@
 
 package org.eclipse.jetty.server.session;
 
-import java.sql.DriverManager;
-import java.sql.SQLException;
-
 import org.junit.After;
 import org.junit.Test;
 
@@ -44,12 +41,6 @@
     @After
     public void tearDown() throws Exception 
     {
-        try
-        {
-            DriverManager.getConnection( "jdbc:derby:sessions;shutdown=true" );
-        }
-        catch( SQLException expected )
-        {
-        }
+        JdbcTestServer.shutdown(null);
     }
 }
diff --git a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SessionExpiryTest.java b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SessionExpiryTest.java
index 5177b93..581113d 100644
--- a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SessionExpiryTest.java
+++ b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SessionExpiryTest.java
@@ -18,9 +18,6 @@
 
 package org.eclipse.jetty.server.session;
 
-import java.sql.DriverManager;
-import java.sql.SQLException;
-
 import org.junit.After;
 import org.junit.Test;
 
@@ -58,18 +55,10 @@
         super.testSessionNotExpired();
     }
 
-  
-    
-    
     @After
     public void tearDown() throws Exception 
     {
-        try
-        {
-            DriverManager.getConnection( "jdbc:derby:sessions;shutdown=true" );
-        }
-        catch( SQLException expected )
-        {
-        }
+        JdbcTestServer.shutdown(null);
     }
+    
 }
diff --git a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SessionInvalidateAndCreateTest.java b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SessionInvalidateAndCreateTest.java
index 746e0bd..de88616 100644
--- a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SessionInvalidateAndCreateTest.java
+++ b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SessionInvalidateAndCreateTest.java
@@ -19,6 +19,7 @@
 
 package org.eclipse.jetty.server.session;
 
+import org.junit.After;
 import org.junit.Test;
 
 public class SessionInvalidateAndCreateTest extends AbstractSessionInvalidateAndCreateTest
@@ -35,4 +36,12 @@
     {
         super.testSessionScavenge();
     }
+    
+    
+    @After
+    public void tearDown() throws Exception 
+    {
+        JdbcTestServer.shutdown(null);
+    }
+    
 }
diff --git a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SessionMigrationTest.java b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SessionMigrationTest.java
index 2ff6fa4..e8bbbf7 100644
--- a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SessionMigrationTest.java
+++ b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SessionMigrationTest.java
@@ -18,9 +18,6 @@
 
 package org.eclipse.jetty.server.session;
 
-import java.sql.DriverManager;
-import java.sql.SQLException;
-
 import org.junit.After;
 import org.junit.Test;
 
@@ -44,12 +41,6 @@
     @After
     public void tearDown() throws Exception 
     {
-        try
-        {
-            DriverManager.getConnection( "jdbc:derby:sessions;shutdown=true" );
-        }
-        catch( SQLException expected )
-        {
-        }
+        JdbcTestServer.shutdown(null);
     }
 }
diff --git a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SessionRenewTest.java b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SessionRenewTest.java
index 60416b6..cfd4f15 100644
--- a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SessionRenewTest.java
+++ b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SessionRenewTest.java
@@ -18,9 +18,6 @@
 
 package org.eclipse.jetty.server.session;
 
-import java.sql.DriverManager;
-import java.sql.SQLException;
-
 import org.junit.After;
 import org.junit.Test;
 
@@ -39,16 +36,11 @@
         super.testSessionRenewal();
     }
     
+    
     @After
     public void tearDown() throws Exception 
     {
-        try
-        {
-            DriverManager.getConnection( "jdbc:derby:sessions;shutdown=true" );
-        }
-        catch( SQLException expected )
-        {
-        }
+        JdbcTestServer.shutdown(null);
     }
-
+    
 }
diff --git a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SessionValueSavingTest.java b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SessionValueSavingTest.java
index 41c2560..d647534 100644
--- a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SessionValueSavingTest.java
+++ b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SessionValueSavingTest.java
@@ -18,9 +18,6 @@
 
 package org.eclipse.jetty.server.session;
 
-import java.sql.DriverManager;
-import java.sql.SQLException;
-
 import org.junit.After;
 import org.junit.Test;
 
@@ -34,21 +31,16 @@
         return new JdbcTestServer(port,max,scavenge);
     }
 
-        @Test
-        public void testSessionValueSaving() throws Exception 
-        {
-                super.testSessionValueSaving();
-        } 
+    @Test
+    public void testSessionValueSaving() throws Exception 
+    {
+        super.testSessionValueSaving();
+    } 
 
-        @After
-        public void tearDown() throws Exception 
-        {
-            try
-            {
-                DriverManager.getConnection( "jdbc:derby:sessions;shutdown=true" );
-            }
-            catch( SQLException expected )
-            {
-            }
-        }
+
+    @After
+    public void tearDown() throws Exception 
+    {
+        JdbcTestServer.shutdown(null);
+    }
 }
diff --git a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/StopSessionManagerPreserveSessionTest.java b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/StopSessionManagerPreserveSessionTest.java
index 84b2ac3..1c43a75 100644
--- a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/StopSessionManagerPreserveSessionTest.java
+++ b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/StopSessionManagerPreserveSessionTest.java
@@ -21,9 +21,6 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
 
-import java.sql.DriverManager;
-import java.sql.SQLException;
-
 import org.eclipse.jetty.servlet.ServletContextHandler;
 import org.junit.After;
 import org.junit.Test;
@@ -31,17 +28,12 @@
 public class StopSessionManagerPreserveSessionTest extends AbstractStopSessionManagerPreserveSessionTest
 {
     JdbcTestServer _server;
-    
+
+
     @After
     public void tearDown() throws Exception 
     {
-        try
-        {
-            DriverManager.getConnection( "jdbc:derby:sessions;shutdown=true" );
-        }
-        catch( SQLException expected )
-        {
-        }
+        JdbcTestServer.shutdown(null);
     }
     
     @Override
diff --git a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/WebAppObjectInSessionTest.java b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/WebAppObjectInSessionTest.java
index 8a48090..88d7df1 100644
--- a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/WebAppObjectInSessionTest.java
+++ b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/WebAppObjectInSessionTest.java
@@ -18,9 +18,6 @@
 
 package org.eclipse.jetty.server.session;
 
-import java.sql.DriverManager;
-import java.sql.SQLException;
-
 import org.eclipse.jetty.util.resource.Resource;
 import org.junit.After;
 import org.junit.Test;
@@ -45,17 +42,11 @@
         super.testWebappObjectInSession();
     }
     
-    
 
     @After
     public void tearDown() throws Exception 
     {
-        try
-        {
-            DriverManager.getConnection( "jdbc:derby:sessions;shutdown=true" );
-        }
-        catch( SQLException expected )
-        {
-        }
+        JdbcTestServer.shutdown(null);
     }
+  
 }
diff --git a/tests/test-sessions/test-mongodb-sessions/src/test/java/org/eclipse/jetty/nosql/mongodb/MongoTestServer.java b/tests/test-sessions/test-mongodb-sessions/src/test/java/org/eclipse/jetty/nosql/mongodb/MongoTestServer.java
index e3c78c2..0ada08a 100644
--- a/tests/test-sessions/test-mongodb-sessions/src/test/java/org/eclipse/jetty/nosql/mongodb/MongoTestServer.java
+++ b/tests/test-sessions/test-mongodb-sessions/src/test/java/org/eclipse/jetty/nosql/mongodb/MongoTestServer.java
@@ -39,6 +39,7 @@
 {
     static int __workers=0;
     private boolean _saveAllAttributes = false; // false save dirty, true save all
+    private int _saveInterval = 0;
     
     
     public static class TestMongoSessionIdManager extends MongoSessionIdManager 
@@ -70,13 +71,13 @@
     public MongoTestServer(int port, int maxInactivePeriod, int scavengePeriod)
     {
         super(port, maxInactivePeriod, scavengePeriod);
+        _saveInterval = 0;
     }
     
     
     public MongoTestServer(int port, int maxInactivePeriod, int scavengePeriod, boolean saveAllAttributes)
     {
         super(port, maxInactivePeriod, scavengePeriod);
-        
         _saveAllAttributes = saveAllAttributes;
     }
 
@@ -109,10 +110,9 @@
             throw new RuntimeException(e);
         }
         
-        manager.setSavePeriod(1);
+        manager.setSavePeriod(_saveInterval);
         manager.setStalePeriod(0);
         manager.setSaveAllAttributes(_saveAllAttributes);
-        //manager.setScavengePeriod((int)TimeUnit.SECONDS.toMillis(_scavengePeriod));
         return manager;
     }
 
diff --git a/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractInvalidationSessionTest.java b/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractInvalidationSessionTest.java
index 8d2d660..de345ef 100644
--- a/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractInvalidationSessionTest.java
+++ b/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractInvalidationSessionTest.java
@@ -32,6 +32,7 @@
 import org.eclipse.jetty.client.HttpClient;
 import org.eclipse.jetty.client.api.ContentResponse;
 import org.eclipse.jetty.client.api.Request;
+import org.eclipse.jetty.servlet.ServletContextHandler;
 import org.eclipse.jetty.util.thread.QueuedThreadPool;
 import org.junit.Test;
 
@@ -51,16 +52,20 @@
         String contextPath = "";
         String servletMapping = "/server";
         AbstractTestServer server1 = createServer(0);
-        server1.addContext(contextPath).addServlet(TestServlet.class, servletMapping);
+        ServletContextHandler context1 = server1.addContext(contextPath);
+        context1.addServlet(TestServlet.class, servletMapping);
 
+        AbstractSessionManager m1 = (AbstractSessionManager) context1.getSessionHandler().getSessionManager();
 
         try
         {
             server1.start();
             int port1 = server1.getPort();
             AbstractTestServer server2 = createServer(0);
-            server2.addContext(contextPath).addServlet(TestServlet.class, servletMapping);
-
+            ServletContextHandler context2 = server2.addContext(contextPath);
+            context2.addServlet(TestServlet.class, servletMapping);
+            AbstractSessionManager m2 = (AbstractSessionManager) context2.getSessionHandler().getSessionManager();
+            
             try
             {
                 server2.start();
@@ -81,25 +86,33 @@
                     assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
                     String sessionCookie = response1.getHeaders().get("Set-Cookie");
                     assertTrue(sessionCookie != null);
+                    assertEquals(1, m1.getSessions());
+                    assertEquals(1, m1.getSessionsMax());
+                    assertEquals(1, m1.getSessionsTotal());
+                    
                     // Mangle the cookie, replacing Path with $Path, etc.
                     sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
                     
                     
                     // Be sure the session is also present in node2
-
                     Request request2 = client.newRequest(urls[1] + "?action=increment");
                     request2.header("Cookie", sessionCookie);
                     ContentResponse response2 = request2.send();
                     assertEquals(HttpServletResponse.SC_OK,response2.getStatus());
- 
+                    assertEquals(1, m2.getSessions());
+                    assertEquals(1, m2.getSessionsMax());
+                    assertEquals(1, m2.getSessionsTotal());
+                    
 
                     // Invalidate on node1
                     Request request1 = client.newRequest(urls[0] + "?action=invalidate");
                     request1.header("Cookie", sessionCookie);
                     response1 = request1.send();
                     assertEquals(HttpServletResponse.SC_OK, response1.getStatus());
-           
-
+                    assertEquals(0, m1.getSessions());
+                    assertEquals(1, m1.getSessionsMax());
+                    assertEquals(1, m1.getSessionsTotal());
+                   
                     pause();
 
                     // Be sure on node2 we don't see the session anymore
@@ -107,6 +120,9 @@
                     request2.header("Cookie", sessionCookie);
                     response2 = request2.send();
                     assertEquals(HttpServletResponse.SC_OK,response2.getStatus());
+                    assertEquals(0, m2.getSessions());
+                    assertEquals(1, m2.getSessionsMax());
+                    assertEquals(1, m2.getSessionsTotal());
                 }
                 finally
                 {
diff --git a/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractLastAccessTimeTest.java b/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractLastAccessTimeTest.java
index 787eb73..847e800 100644
--- a/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractLastAccessTimeTest.java
+++ b/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractLastAccessTimeTest.java
@@ -65,15 +65,19 @@
         ServletHolder holder1 = new ServletHolder(servlet1);
         ServletContextHandler context = server1.addContext(contextPath);
         TestSessionListener listener1 = new TestSessionListener();
-        context.addEventListener(listener1);
+        context.getSessionHandler().addEventListener(listener1);
         context.addServlet(holder1, servletMapping);
+        AbstractSessionManager m1 = (AbstractSessionManager)context.getSessionHandler().getSessionManager();
+        
 
         try
         {
             server1.start();
             int port1=server1.getPort();
             AbstractTestServer server2 = createServer(0, maxInactivePeriod, scavengePeriod);
-            server2.addContext(contextPath).addServlet(TestServlet.class, servletMapping);
+            ServletContextHandler context2 = server2.addContext(contextPath);
+            context2.addServlet(TestServlet.class, servletMapping);
+            AbstractSessionManager m2 = (AbstractSessionManager)context2.getSessionHandler().getSessionManager();
 
             try
             {
@@ -89,9 +93,12 @@
                     assertEquals("test", response1.getContentAsString());
                     String sessionCookie = response1.getHeaders().get("Set-Cookie");
                     assertTrue( sessionCookie != null );
+                    assertEquals(1, m1.getSessions());
+                    assertEquals(1, m1.getSessionsMax());
+                    assertEquals(1, m1.getSessionsTotal());
                     // Mangle the cookie, replacing Path with $Path, etc.
-                    sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
-
+                    sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");        
+                    
                     // Perform some request to server2 using the session cookie from the previous request
                     // This should migrate the session from server1 to server2, and leave server1's
                     // session in a very stale state, while server2 has a very fresh session.
@@ -111,14 +118,15 @@
                             sessionCookie = setCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
 
                         Thread.sleep(requestInterval);
+                        assertSessionCounts(1,1,1, m2);
                     }
-
                     // At this point, session1 should be eligible for expiration.
                     // Let's wait for the scavenger to run, waiting 2.5 times the scavenger period
                     Thread.sleep(scavengePeriod * 2500L);
 
                     //check that the session was not scavenged over on server1 by ensuring that the SessionListener destroy method wasn't called
                     assertFalse(listener1.destroyed);
+                    assertAfterScavenge(m1);
                 }
                 finally
                 {
@@ -135,6 +143,23 @@
             server1.stop();
         }
     }
+    
+    public void assertAfterSessionCreated (AbstractSessionManager m)
+    {
+        assertSessionCounts(1, 1, 1, m);
+    }
+    
+    public void assertAfterScavenge (AbstractSessionManager manager)
+    {
+        assertSessionCounts(1,1,1, manager);
+    }
+    
+    public void assertSessionCounts (int current, int max, int total, AbstractSessionManager manager)
+    {
+        assertEquals(current, manager.getSessions());
+        assertEquals(max, manager.getSessionsMax());
+        assertEquals(total, manager.getSessionsTotal());
+    }
 
     public static class TestSessionListener implements HttpSessionListener
     {
diff --git a/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractRemoveSessionTest.java b/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractRemoveSessionTest.java
index c344d72..bb126f6 100644
--- a/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractRemoveSessionTest.java
+++ b/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractRemoveSessionTest.java
@@ -39,6 +39,12 @@
 import org.eclipse.jetty.servlet.ServletContextHandler;
 import org.junit.Test;
 
+/**
+ * AbstractRemoveSessionTest
+ *
+ * Test that invalidating a session does not return the session on the next request.
+ * 
+ */
 public abstract class AbstractRemoveSessionTest
 {
     public abstract AbstractTestServer createServer(int port, int max, int scavenge);
@@ -55,6 +61,7 @@
         context.addServlet(TestServlet.class, servletMapping);
         TestEventListener testListener = new TestEventListener();
         context.getSessionHandler().addEventListener(testListener);
+        AbstractSessionManager m = (AbstractSessionManager)context.getSessionHandler().getSessionManager();
         try
         {
             server.start();
@@ -72,7 +79,10 @@
                 sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
                 //ensure sessionCreated listener is called
                 assertTrue (testListener.isCreated());
-
+                assertEquals(1, m.getSessions());
+                assertEquals(1, m.getSessionsMax());
+                assertEquals(1, m.getSessionsTotal());
+                
                 //now delete the session
                 Request request = client.newRequest("http://localhost:" + port + contextPath + servletMapping + "?action=delete");
                 request.header("Cookie", sessionCookie);
@@ -80,13 +90,18 @@
                 assertEquals(HttpServletResponse.SC_OK,response.getStatus());
                 //ensure sessionDestroyed listener is called
                 assertTrue(testListener.isDestroyed());
-
+                assertEquals(0, m.getSessions());
+                assertEquals(1, m.getSessionsMax());
+                assertEquals(1, m.getSessionsTotal());
 
                 // The session is not there anymore, even if we present an old cookie
                 request = client.newRequest("http://localhost:" + port + contextPath + servletMapping + "?action=check");
                 request.header("Cookie", sessionCookie);
                 response = request.send();
                 assertEquals(HttpServletResponse.SC_OK,response.getStatus());
+                assertEquals(0, m.getSessions());
+                assertEquals(1, m.getSessionsMax());
+                assertEquals(1, m.getSessionsTotal());
             }
             finally
             {
diff --git a/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSameNodeLoadTest.java b/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSameNodeLoadTest.java
index 999858f..28e6cbd 100644
--- a/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSameNodeLoadTest.java
+++ b/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSameNodeLoadTest.java
@@ -19,8 +19,8 @@
 package org.eclipse.jetty.server.session;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
 import java.io.IOException;
 import java.io.PrintWriter;
diff --git a/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractServerCrossContextSessionTest.java b/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractServerCrossContextSessionTest.java
index 30a080a..ed7737f 100644
--- a/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractServerCrossContextSessionTest.java
+++ b/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractServerCrossContextSessionTest.java
@@ -22,7 +22,6 @@
 import static org.junit.Assert.assertTrue;
 
 import java.io.IOException;
-import java.util.Collections;
 
 import javax.servlet.RequestDispatcher;
 import javax.servlet.ServletContext;
@@ -87,10 +86,9 @@
         {
             HttpSession session = request.getSession(false);
             if (session == null) session = request.getSession(true);
-
             // Add something to the session
             session.setAttribute("A", "A");
-            System.out.println("A: session.getAttributeNames() = " + Collections.list(session.getAttributeNames()));
+           
 
             // Perform cross context dispatch to another context
             // Over there we will check that the session attribute added above is not visible
@@ -101,7 +99,6 @@
             // Check that we don't see things put in session by contextB
             Object objectB = session.getAttribute("B");
             assertTrue(objectB == null);
-            System.out.println("A: session.getAttributeNames() = " + Collections.list(session.getAttributeNames()));
         }
     }
 
@@ -119,7 +116,6 @@
 
             // Add something, so in contextA we can check if it is visible (it must not).
             session.setAttribute("B", "B");
-            System.out.println("B: session.getAttributeNames() = " + Collections.list(session.getAttributeNames()));
         }
     }
 }
diff --git a/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSessionCookieTest.java b/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSessionCookieTest.java
index b79a0a3..a867711 100644
--- a/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSessionCookieTest.java
+++ b/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSessionCookieTest.java
@@ -29,8 +29,6 @@
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
 
-import junit.framework.Assert;
-
 import org.eclipse.jetty.client.HttpClient;
 import org.eclipse.jetty.client.api.ContentResponse;
 import org.eclipse.jetty.client.api.Request;
@@ -38,6 +36,8 @@
 import org.junit.Ignore;
 import org.junit.Test;
 
+import junit.framework.Assert;
+
 /**
  * AbstractSessionCookieTest
  */
diff --git a/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSessionExpiryTest.java b/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSessionExpiryTest.java
index 5c11f8b..0c221a2 100644
--- a/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSessionExpiryTest.java
+++ b/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSessionExpiryTest.java
@@ -40,6 +40,11 @@
 import org.eclipse.jetty.servlet.ServletHolder;
 import org.junit.Test;
 
+/**
+ * AbstractSessionExpiryTest
+ *
+ *
+ */
 public abstract class AbstractSessionExpiryTest
 {
     public abstract AbstractTestServer createServer(int port, int max, int scavenge);
@@ -104,6 +109,7 @@
 
             //now stop the server
             server1.stop();
+   
 
             //start the server again, before the session times out
             server1.start();
@@ -161,12 +167,12 @@
             sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
             
             String sessionId = AbstractTestServer.extractSessionId(sessionCookie);     
-            
+
             verifySessionCreated(listener,sessionId);
             
             //now stop the server
             server1.stop();
-
+            
             //and wait until the expiry time has passed
             pause(inactivePeriod);