You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2017/11/05 17:05:26 UTC

[1/2] httpcomponents-client git commit: Improved internal client exchange handling code

Repository: httpcomponents-client
Updated Branches:
  refs/heads/master d88e32f95 -> 45f1a2a74


Improved internal client exchange handling code


Project: http://git-wip-us.apache.org/repos/asf/httpcomponents-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/httpcomponents-client/commit/45f1a2a7
Tree: http://git-wip-us.apache.org/repos/asf/httpcomponents-client/tree/45f1a2a7
Diff: http://git-wip-us.apache.org/repos/asf/httpcomponents-client/diff/45f1a2a7

Branch: refs/heads/master
Commit: 45f1a2a740250882bb2bc9912146dae763c92946
Parents: 389272d
Author: Oleg Kalnichevski <ol...@apache.org>
Authored: Sun Nov 5 13:42:26 2017 +0100
Committer: Oleg Kalnichevski <ol...@apache.org>
Committed: Sun Nov 5 13:57:34 2017 +0100

----------------------------------------------------------------------
 .../impl/async/InternalAsyncEntityProducer.java |  98 --------
 .../impl/async/InternalHttpAsyncClient.java     | 229 ++++++++++++-------
 2 files changed, 142 insertions(+), 185 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/45f1a2a7/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalAsyncEntityProducer.java
----------------------------------------------------------------------
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalAsyncEntityProducer.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalAsyncEntityProducer.java
deleted file mode 100644
index 4c067f2..0000000
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalAsyncEntityProducer.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * ====================================================================
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- */
-
-package org.apache.hc.client5.http.impl.async;
-
-import java.io.IOException;
-import java.util.Set;
-
-import org.apache.hc.core5.http.EntityDetails;
-import org.apache.hc.core5.http.nio.AsyncDataProducer;
-import org.apache.hc.core5.http.nio.AsyncEntityProducer;
-import org.apache.hc.core5.http.nio.DataStreamChannel;
-
-final class InternalAsyncEntityProducer implements AsyncEntityProducer {
-
-    private final AsyncDataProducer dataProducer;
-    private final EntityDetails entityDetails;
-
-    InternalAsyncEntityProducer(final AsyncDataProducer dataProducer, final EntityDetails entityDetails) {
-        this.dataProducer = dataProducer;
-        this.entityDetails = entityDetails;
-    }
-
-    @Override
-    public void releaseResources() {
-        dataProducer.releaseResources();
-    }
-
-    @Override
-    public void failed(final Exception cause) {
-        dataProducer.releaseResources();
-    }
-
-    @Override
-    public long getContentLength() {
-        return entityDetails.getContentLength();
-    }
-
-    @Override
-    public String getContentType() {
-        return entityDetails.getContentType();
-    }
-
-    @Override
-    public String getContentEncoding() {
-        return entityDetails.getContentEncoding();
-    }
-
-    @Override
-    public boolean isRepeatable() {
-        return false;
-    }
-
-    @Override
-    public boolean isChunked() {
-        return entityDetails.isChunked();
-    }
-
-    @Override
-    public Set<String> getTrailerNames() {
-        return entityDetails.getTrailerNames();
-    }
-
-    @Override
-    public int available() {
-        return dataProducer.available();
-    }
-
-    @Override
-    public void produce(final DataStreamChannel channel) throws IOException {
-        dataProducer.produce(channel);
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/45f1a2a7/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalHttpAsyncClient.java
----------------------------------------------------------------------
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalHttpAsyncClient.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalHttpAsyncClient.java
index 431111c..02b4d9e 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalHttpAsyncClient.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalHttpAsyncClient.java
@@ -29,8 +29,10 @@ package org.apache.hc.client5.http.impl.async;
 import java.io.Closeable;
 import java.io.IOException;
 import java.util.List;
+import java.util.Set;
 import java.util.concurrent.Future;
 import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.hc.client5.http.HttpRoute;
 import org.apache.hc.client5.http.async.AsyncExecCallback;
@@ -54,15 +56,16 @@ import org.apache.hc.core5.http.HttpException;
 import org.apache.hc.core5.http.HttpHost;
 import org.apache.hc.core5.http.HttpRequest;
 import org.apache.hc.core5.http.HttpResponse;
+import org.apache.hc.core5.http.HttpStatus;
 import org.apache.hc.core5.http.HttpVersion;
 import org.apache.hc.core5.http.ProtocolVersion;
 import org.apache.hc.core5.http.config.Lookup;
-import org.apache.hc.core5.http.nio.AsyncClientExchangeHandler;
 import org.apache.hc.core5.http.nio.AsyncDataConsumer;
+import org.apache.hc.core5.http.nio.AsyncEntityProducer;
 import org.apache.hc.core5.http.nio.AsyncRequestProducer;
 import org.apache.hc.core5.http.nio.AsyncResponseConsumer;
+import org.apache.hc.core5.http.nio.DataStreamChannel;
 import org.apache.hc.core5.http.nio.RequestChannel;
-import org.apache.hc.core5.http.nio.support.BasicClientExchangeHandler;
 import org.apache.hc.core5.http.protocol.HttpContext;
 import org.apache.hc.core5.http2.HttpVersionPolicy;
 import org.apache.hc.core5.reactor.DefaultConnectingIOReactor;
@@ -139,70 +142,6 @@ class InternalHttpAsyncClient extends AbstractHttpAsyncClientBase {
         }
     }
 
-    private void executeChain(
-            final String exchangeId,
-            final AsyncExecChainElement execChain,
-            final HttpRoute route,
-            final HttpRequest request,
-            final EntityDetails entityDetails,
-            final AsyncClientExchangeHandler exchangeHandler,
-            final HttpClientContext clientContext,
-            final AsyncExecRuntime execRuntime) throws IOException, HttpException {
-
-        if (log.isDebugEnabled()) {
-            log.debug(exchangeId + ": preparing request execution");
-        }
-
-        final ProtocolVersion protocolVersion = clientContext.getProtocolVersion();
-        if (route.isTunnelled() && protocolVersion.greaterEquals(HttpVersion.HTTP_2_0)) {
-            throw new HttpException("HTTP/2 tunneling not supported");
-        }
-
-        setupContext(clientContext);
-
-        final AsyncExecChain.Scope scope = new AsyncExecChain.Scope(exchangeId, route, request, clientContext, execRuntime);
-        execChain.execute(
-                RequestCopier.INSTANCE.copy(request),
-                entityDetails != null ? new InternalAsyncEntityProducer(exchangeHandler, entityDetails) : null,
-                scope,
-                new AsyncExecCallback() {
-
-                    @Override
-                    public AsyncDataConsumer handleResponse(
-                            final HttpResponse response,
-                            final EntityDetails entityDetails) throws HttpException, IOException {
-                        exchangeHandler.consumeResponse(response, entityDetails);
-                        return exchangeHandler;
-                    }
-
-                    @Override
-                    public void completed() {
-                        if (log.isDebugEnabled()) {
-                            log.debug(exchangeId + ": message exchange successfully completed");
-                        }
-                        try {
-                            exchangeHandler.releaseResources();
-                        } finally {
-                            execRuntime.releaseConnection();
-                        }
-                    }
-
-                    @Override
-                    public void failed(final Exception cause) {
-                        if (log.isDebugEnabled()) {
-                            log.debug(exchangeId + ": request failed: " + cause.getMessage());
-                        }
-                        try {
-                            exchangeHandler.failed(cause);
-                            exchangeHandler.releaseResources();
-                        } finally {
-                            execRuntime.discardConnection();
-                        }
-                    }
-
-                });
-    }
-
     @Override
     public <T> Future<T> execute(
             final AsyncRequestProducer requestProducer,
@@ -222,25 +161,7 @@ class InternalHttpAsyncClient extends AbstractHttpAsyncClientBase {
                 clientContext.setRequestConfig(requestConfig);
             }
 
-            final AsyncClientExchangeHandler exchangeHandler = new BasicClientExchangeHandler<>(requestProducer, responseConsumer, new FutureCallback<T>() {
-
-                @Override
-                public void completed(final T result) {
-                    future.completed(result);
-                }
-
-                @Override
-                public void failed(final Exception ex) {
-                    future.failed(ex);
-                }
-
-                @Override
-                public void cancelled() {
-                    future.cancel();
-                }
-
-            });
-            exchangeHandler.produceRequest(new RequestChannel() {
+            requestProducer.sendRequest(new RequestChannel() {
 
                 @Override
                 public void sendRequest(
@@ -251,11 +172,145 @@ class InternalHttpAsyncClient extends AbstractHttpAsyncClientBase {
                     final HttpRoute route = routePlanner.determineRoute(target, clientContext);
                     final String exchangeId = String.format("ex-%08X", ExecSupport.getNextExecNumber());
                     final AsyncExecRuntime execRuntime = new AsyncExecRuntimeImpl(log, connmgr, getConnectionInitiator(), versionPolicy);
-                    executeChain(exchangeId, execChain, route, request, entityDetails, exchangeHandler, clientContext, execRuntime);
+                    if (log.isDebugEnabled()) {
+                        log.debug(exchangeId + ": preparing request execution");
+                    }
+
+                    final ProtocolVersion protocolVersion = clientContext.getProtocolVersion();
+                    if (route.isTunnelled() && protocolVersion.greaterEquals(HttpVersion.HTTP_2_0)) {
+                        throw new HttpException("HTTP/2 tunneling not supported");
+                    }
+
+                    setupContext(clientContext);
+
+                    final AsyncExecChain.Scope scope = new AsyncExecChain.Scope(exchangeId, route, request, clientContext, execRuntime);
+                    final AtomicBoolean outputTerminated = new AtomicBoolean(false);
+                    execChain.execute(
+                            RequestCopier.INSTANCE.copy(request),
+                            entityDetails != null ? new AsyncEntityProducer() {
+
+                                @Override
+                                public void releaseResources() {
+                                    requestProducer.releaseResources();
+                                }
+
+                                @Override
+                                public void failed(final Exception cause) {
+                                    requestProducer.failed(cause);
+                                }
+
+                                @Override
+                                public boolean isRepeatable() {
+                                    return false;
+                                }
+
+                                @Override
+                                public long getContentLength() {
+                                    return entityDetails.getContentLength();
+                                }
+
+                                @Override
+                                public String getContentType() {
+                                    return entityDetails.getContentType();
+                                }
+
+                                @Override
+                                public String getContentEncoding() {
+                                    return entityDetails.getContentEncoding();
+                                }
+
+                                @Override
+                                public boolean isChunked() {
+                                    return entityDetails.isChunked();
+                                }
+
+                                @Override
+                                public Set<String> getTrailerNames() {
+                                    return entityDetails.getTrailerNames();
+                                }
+
+                                @Override
+                                public int available() {
+                                    return requestProducer.available();
+                                }
+
+                                @Override
+                                public void produce(final DataStreamChannel channel) throws IOException {
+                                    if (outputTerminated.get()) {
+                                        channel.endStream();
+                                        return;
+                                    }
+                                    requestProducer.produce(channel);
+                                }
+
+                            } : null,
+                            scope,
+                            new AsyncExecCallback() {
+
+                                @Override
+                                public AsyncDataConsumer handleResponse(
+                                        final HttpResponse response,
+                                        final EntityDetails entityDetails) throws HttpException, IOException {
+                                    if (response.getCode() >= HttpStatus.SC_CLIENT_ERROR) {
+                                        outputTerminated.set(true);
+                                        requestProducer.releaseResources();
+                                    }
+                                    responseConsumer.consumeResponse(response, entityDetails, new FutureCallback<T>() {
+
+                                        @Override
+                                        public void completed(final T result) {
+                                            future.completed(result);
+                                        }
+
+                                        @Override
+                                        public void failed(final Exception ex) {
+                                            future.failed(ex);
+                                        }
+
+                                        @Override
+                                        public void cancelled() {
+                                            future.cancel();
+                                        }
+
+                                    });
+                                    return responseConsumer;
+                                }
+
+                                @Override
+                                public void completed() {
+                                    if (log.isDebugEnabled()) {
+                                        log.debug(exchangeId + ": message exchange successfully completed");
+                                    }
+                                    try {
+                                        responseConsumer.releaseResources();
+                                        requestProducer.releaseResources();
+                                    } finally {
+                                        execRuntime.releaseConnection();
+                                    }
+                                }
+
+                                @Override
+                                public void failed(final Exception cause) {
+                                    if (log.isDebugEnabled()) {
+                                        log.debug(exchangeId + ": request failed: " + cause.getMessage());
+                                    }
+                                    try {
+                                        try {
+                                            future.failed(cause);
+                                            responseConsumer.failed(cause);
+                                        } finally {
+                                            responseConsumer.releaseResources();
+                                            requestProducer.releaseResources();
+                                        }
+                                    } finally {
+                                        execRuntime.discardConnection();
+                                    }
+                                }
+
+                            });
                 }
 
             });
-
         } catch (final HttpException | IOException ex) {
             future.failed(ex);
         }


[2/2] httpcomponents-client git commit: Upgraded HttpCore dependency to version 5.0-beta1

Posted by ol...@apache.org.
Upgraded HttpCore dependency to version 5.0-beta1


Project: http://git-wip-us.apache.org/repos/asf/httpcomponents-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/httpcomponents-client/commit/389272de
Tree: http://git-wip-us.apache.org/repos/asf/httpcomponents-client/tree/389272de
Diff: http://git-wip-us.apache.org/repos/asf/httpcomponents-client/diff/389272de

Branch: refs/heads/master
Commit: 389272de3a5f0e22e3d8e10a5ddb8b1445d2c102
Parents: d88e32f
Author: Oleg Kalnichevski <ol...@apache.org>
Authored: Sat Nov 4 11:44:36 2017 +0100
Committer: Oleg Kalnichevski <ol...@apache.org>
Committed: Sun Nov 5 13:57:34 2017 +0100

----------------------------------------------------------------------
 httpclient5-fluent/pom.xml                      |  1 -
 .../testing/async/AsyncRandomHandler.java       |  6 ++
 .../impl/async/InternalAsyncEntityProducer.java |  5 ++
 .../http/impl/async/LoggingIOSession.java       | 20 +++++++
 .../io/PoolingHttpClientConnectionManager.java  | 12 ++--
 .../PoolingAsyncClientConnectionManager.java    | 12 ++--
 .../http/impl/classic/MockConnPoolControl.java  |  7 +++
 .../TestPoolingHttpClientConnectionManager.java | 58 +++++++++++++++++---
 pom.xml                                         |  2 +-
 9 files changed, 103 insertions(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/389272de/httpclient5-fluent/pom.xml
----------------------------------------------------------------------
diff --git a/httpclient5-fluent/pom.xml b/httpclient5-fluent/pom.xml
index 84923bb..c30ac24 100644
--- a/httpclient5-fluent/pom.xml
+++ b/httpclient5-fluent/pom.xml
@@ -67,7 +67,6 @@
       <artifactId>junit</artifactId>
       <scope>test</scope>
     </dependency>
-    <!-- TODO: does not appear to be needed; remove? -->
     <dependency>
       <groupId>org.mockito</groupId>
       <artifactId>mockito-core</artifactId>

http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/389272de/httpclient5-testing/src/main/java/org/apache/hc/client5/testing/async/AsyncRandomHandler.java
----------------------------------------------------------------------
diff --git a/httpclient5-testing/src/main/java/org/apache/hc/client5/testing/async/AsyncRandomHandler.java b/httpclient5-testing/src/main/java/org/apache/hc/client5/testing/async/AsyncRandomHandler.java
index 57bb64d..5a3135b 100644
--- a/httpclient5-testing/src/main/java/org/apache/hc/client5/testing/async/AsyncRandomHandler.java
+++ b/httpclient5-testing/src/main/java/org/apache/hc/client5/testing/async/AsyncRandomHandler.java
@@ -173,6 +173,12 @@ public class AsyncRandomHandler implements AsyncServerExchangeHandler {
 
         @Override
         public void releaseResources() {
+            remaining = length;
+        }
+
+        @Override
+        public boolean isRepeatable() {
+            return true;
         }
 
         @Override

http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/389272de/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalAsyncEntityProducer.java
----------------------------------------------------------------------
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalAsyncEntityProducer.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalAsyncEntityProducer.java
index 14840e5..4c067f2 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalAsyncEntityProducer.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalAsyncEntityProducer.java
@@ -71,6 +71,11 @@ final class InternalAsyncEntityProducer implements AsyncEntityProducer {
     }
 
     @Override
+    public boolean isRepeatable() {
+        return false;
+    }
+
+    @Override
     public boolean isChunked() {
         return entityDetails.isChunked();
     }

http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/389272de/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/LoggingIOSession.java
----------------------------------------------------------------------
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/LoggingIOSession.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/LoggingIOSession.java
index fad7f1e..c8f27c1 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/LoggingIOSession.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/LoggingIOSession.java
@@ -190,6 +190,26 @@ class LoggingIOSession implements TlsCapableIOSession {
     }
 
     @Override
+    public long getLastReadTime() {
+        return this.session.getLastReadTime();
+    }
+
+    @Override
+    public long getLastWriteTime() {
+        return this.session.getLastWriteTime();
+    }
+
+    @Override
+    public void updateReadTime() {
+        this.session.updateReadTime();
+    }
+
+    @Override
+    public void updateWriteTime() {
+        this.session.updateWriteTime();
+    }
+
+    @Override
     public IOEventHandler getHandler() {
         return this.session.getHandler();
     }

http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/389272de/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/PoolingHttpClientConnectionManager.java
----------------------------------------------------------------------
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/PoolingHttpClientConnectionManager.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/PoolingHttpClientConnectionManager.java
index f3ff470..c5e7e86 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/PoolingHttpClientConnectionManager.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/PoolingHttpClientConnectionManager.java
@@ -27,6 +27,7 @@
 package org.apache.hc.client5.http.impl.io;
 
 import java.io.IOException;
+import java.util.Set;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
@@ -249,11 +250,7 @@ public class PoolingHttpClientConnectionManager
         if (this.log.isDebugEnabled()) {
             this.log.debug("Connection request: " + ConnPoolSupport.formatStats(null, route, state, this.pool));
         }
-        //TODO: fix me.
-        if (log.isWarnEnabled() && Timeout.isPositive(requestTimeout)) {
-            log.warn("Connection request timeout is not supported");
-        }
-        final Future<PoolEntry<HttpRoute, ManagedHttpClientConnection>> leaseFuture = this.pool.lease(route, state, /** requestTimeout, */ null);
+        final Future<PoolEntry<HttpRoute, ManagedHttpClientConnection>> leaseFuture = this.pool.lease(route, state, requestTimeout, null);
         return new LeaseRequest() {
 
             private volatile ConnectionEndpoint endpoint;
@@ -412,6 +409,11 @@ public class PoolingHttpClientConnectionManager
     }
 
     @Override
+    public Set<HttpRoute> getRoutes() {
+        return this.pool.getRoutes();
+    }
+
+    @Override
     public int getMaxTotal() {
         return this.pool.getMaxTotal();
     }

http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/389272de/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManager.java
----------------------------------------------------------------------
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManager.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManager.java
index 1cad085..1afb96e 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManager.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManager.java
@@ -29,6 +29,7 @@ package org.apache.hc.client5.http.impl.nio;
 
 import java.io.IOException;
 import java.net.InetSocketAddress;
+import java.util.Set;
 import java.util.concurrent.Future;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicLong;
@@ -212,12 +213,8 @@ public class PoolingAsyncClientConnectionManager implements AsyncClientConnectio
             log.debug("Connection request: " + ConnPoolSupport.formatStats(null, route, state, pool));
         }
         final ComplexFuture<AsyncConnectionEndpoint> resultFuture = new ComplexFuture<>(callback);
-        //TODO: fix me.
-        if (log.isWarnEnabled() && Timeout.isPositive(requestTimeout)) {
-            log.warn("Connection request timeout is not supported");
-        }
         final Future<PoolEntry<HttpRoute, ManagedAsyncClientConnection>> leaseFuture = pool.lease(
-                route, state, /** requestTimeout, **/ new FutureCallback<PoolEntry<HttpRoute, ManagedAsyncClientConnection>>() {
+                route, state, requestTimeout, new FutureCallback<PoolEntry<HttpRoute, ManagedAsyncClientConnection>>() {
 
                     void leaseCompleted(final PoolEntry<HttpRoute, ManagedAsyncClientConnection> poolEntry) {
                         if (log.isDebugEnabled()) {
@@ -395,6 +392,11 @@ public class PoolingAsyncClientConnectionManager implements AsyncClientConnectio
     }
 
     @Override
+    public Set<HttpRoute> getRoutes() {
+        return pool.getRoutes();
+    }
+
+    @Override
     public void setMaxTotal(final int max) {
         pool.setMaxTotal(max);
     }

http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/389272de/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/MockConnPoolControl.java
----------------------------------------------------------------------
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/MockConnPoolControl.java b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/MockConnPoolControl.java
index 24e17ba..0d977dc 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/MockConnPoolControl.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/MockConnPoolControl.java
@@ -26,7 +26,9 @@
  */
 package org.apache.hc.client5.http.impl.classic;
 
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
 import org.apache.hc.client5.http.HttpRoute;
@@ -110,6 +112,11 @@ public final class MockConnPoolControl implements ConnPoolControl<HttpRoute> {
     }
 
     @Override
+    public Set<HttpRoute> getRoutes() {
+        return new HashSet<>(this.maxPerHostMap.keySet());
+    }
+
+    @Override
     public String toString() {
         return this.maxPerHostMap.toString();
     }

http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/389272de/httpclient5/src/test/java/org/apache/hc/client5/http/impl/io/TestPoolingHttpClientConnectionManager.java
----------------------------------------------------------------------
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/io/TestPoolingHttpClientConnectionManager.java b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/io/TestPoolingHttpClientConnectionManager.java
index 0c46b0e..7303701 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/io/TestPoolingHttpClientConnectionManager.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/io/TestPoolingHttpClientConnectionManager.java
@@ -43,6 +43,7 @@ import org.apache.hc.client5.http.io.ManagedHttpClientConnection;
 import org.apache.hc.client5.http.protocol.HttpClientContext;
 import org.apache.hc.client5.http.socket.ConnectionSocketFactory;
 import org.apache.hc.client5.http.socket.LayeredConnectionSocketFactory;
+import org.apache.hc.core5.concurrent.FutureCallback;
 import org.apache.hc.core5.http.HttpHost;
 import org.apache.hc.core5.http.config.Lookup;
 import org.apache.hc.core5.http.config.SocketConfig;
@@ -50,6 +51,7 @@ import org.apache.hc.core5.http.protocol.HttpContext;
 import org.apache.hc.core5.pool.PoolEntry;
 import org.apache.hc.core5.pool.StrictConnPool;
 import org.apache.hc.core5.util.TimeValue;
+import org.apache.hc.core5.util.Timeout;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
@@ -106,7 +108,12 @@ public class TestPoolingHttpClientConnectionManager {
         Mockito.when(conn.isOpen()).thenReturn(true);
         Mockito.when(future.isCancelled()).thenReturn(false);
         Mockito.when(future.get(1, TimeUnit.SECONDS)).thenReturn(entry);
-        Mockito.when(pool.lease(route, null, null)).thenReturn(future);
+        Mockito.when(pool.lease(
+                Mockito.eq(route),
+                Mockito.eq(null),
+                Mockito.<Timeout>any(),
+                Mockito.<FutureCallback<PoolEntry<HttpRoute, ManagedHttpClientConnection>>>eq(null)))
+                .thenReturn(future);
 
         final LeaseRequest connRequest1 = mgr.lease(route, null);
         final ConnectionEndpoint endpoint1 = connRequest1.get(1, TimeUnit.SECONDS);
@@ -133,7 +140,12 @@ public class TestPoolingHttpClientConnectionManager {
         Mockito.when(conn.isOpen()).thenReturn(true);
         Mockito.when(future.isCancelled()).thenReturn(false);
         Mockito.when(future.get(1, TimeUnit.SECONDS)).thenReturn(entry);
-        Mockito.when(pool.lease(route, null, null)).thenReturn(future);
+        Mockito.when(pool.lease(
+                Mockito.eq(route),
+                Mockito.eq(null),
+                Mockito.<Timeout>any(),
+                Mockito.<FutureCallback<PoolEntry<HttpRoute, ManagedHttpClientConnection>>>eq(null)))
+                .thenReturn(future);
 
         final LeaseRequest connRequest1 = mgr.lease(route, null);
         final ConnectionEndpoint endpoint1 = connRequest1.get(1, TimeUnit.SECONDS);
@@ -155,7 +167,12 @@ public class TestPoolingHttpClientConnectionManager {
 
         Mockito.when(future.isCancelled()).thenReturn(Boolean.TRUE);
         Mockito.when(future.get(1, TimeUnit.SECONDS)).thenReturn(entry);
-        Mockito.when(pool.lease(route, null, null)).thenReturn(future);
+        Mockito.when(pool.lease(
+                Mockito.eq(route),
+                Mockito.eq(null),
+                Mockito.<Timeout>any(),
+                Mockito.<FutureCallback<PoolEntry<HttpRoute, ManagedHttpClientConnection>>>eq(null)))
+                .thenReturn(future);
 
         final LeaseRequest connRequest1 = mgr.lease(route, null);
         connRequest1.get(1, TimeUnit.SECONDS);
@@ -168,7 +185,12 @@ public class TestPoolingHttpClientConnectionManager {
 
         Mockito.when(future.isCancelled()).thenReturn(Boolean.TRUE);
         Mockito.when(future.get(1, TimeUnit.SECONDS)).thenThrow(new TimeoutException());
-        Mockito.when(pool.lease(route, null, null)).thenReturn(future);
+        Mockito.when(pool.lease(
+                Mockito.eq(route),
+                Mockito.eq(null),
+                Mockito.<Timeout>any(),
+                Mockito.<FutureCallback<PoolEntry<HttpRoute, ManagedHttpClientConnection>>>eq(null)))
+                .thenReturn(future);
 
         final LeaseRequest connRequest1 = mgr.lease(route, null);
         connRequest1.get(1, TimeUnit.SECONDS);
@@ -184,7 +206,12 @@ public class TestPoolingHttpClientConnectionManager {
 
         Mockito.when(future.isCancelled()).thenReturn(Boolean.FALSE);
         Mockito.when(future.get(1, TimeUnit.SECONDS)).thenReturn(entry);
-        Mockito.when(pool.lease(route, null, null)).thenReturn(future);
+        Mockito.when(pool.lease(
+                Mockito.eq(route),
+                Mockito.eq(null),
+                Mockito.<Timeout>any(),
+                Mockito.<FutureCallback<PoolEntry<HttpRoute, ManagedHttpClientConnection>>>eq(null)))
+                .thenReturn(future);
         Mockito.when(conn.isOpen()).thenReturn(Boolean.TRUE);
 
         final LeaseRequest connRequest1 = mgr.lease(route, null);
@@ -208,7 +235,12 @@ public class TestPoolingHttpClientConnectionManager {
 
         Mockito.when(future.isCancelled()).thenReturn(Boolean.FALSE);
         Mockito.when(future.get(1, TimeUnit.SECONDS)).thenReturn(entry);
-        Mockito.when(pool.lease(route, null, null)).thenReturn(future);
+        Mockito.when(pool.lease(
+                Mockito.eq(route),
+                Mockito.eq(null),
+                Mockito.<Timeout>any(),
+                Mockito.<FutureCallback<PoolEntry<HttpRoute, ManagedHttpClientConnection>>>eq(null)))
+                .thenReturn(future);
         Mockito.when(conn.isOpen()).thenReturn(Boolean.FALSE);
 
         final LeaseRequest connRequest1 = mgr.lease(route, null);
@@ -236,7 +268,12 @@ public class TestPoolingHttpClientConnectionManager {
         Mockito.when(conn.isOpen()).thenReturn(false);
         Mockito.when(future.isCancelled()).thenReturn(false);
         Mockito.when(future.get(1, TimeUnit.SECONDS)).thenReturn(entry);
-        Mockito.when(pool.lease(route, null, null)).thenReturn(future);
+        Mockito.when(pool.lease(
+                Mockito.eq(route),
+                Mockito.eq(null),
+                Mockito.<Timeout>any(),
+                Mockito.<FutureCallback<PoolEntry<HttpRoute, ManagedHttpClientConnection>>>eq(null)))
+                .thenReturn(future);
 
         final LeaseRequest connRequest1 = mgr.lease(route, null);
         final ConnectionEndpoint endpoint1 = connRequest1.get(1, TimeUnit.SECONDS);
@@ -284,7 +321,12 @@ public class TestPoolingHttpClientConnectionManager {
         Mockito.when(conn.isOpen()).thenReturn(false);
         Mockito.when(future.isCancelled()).thenReturn(false);
         Mockito.when(future.get(1, TimeUnit.SECONDS)).thenReturn(entry);
-        Mockito.when(pool.lease(route, null, null)).thenReturn(future);
+        Mockito.when(pool.lease(
+                Mockito.eq(route),
+                Mockito.eq(null),
+                Mockito.<Timeout>any(),
+                Mockito.<FutureCallback<PoolEntry<HttpRoute, ManagedHttpClientConnection>>>eq(null)))
+                .thenReturn(future);
 
         final LeaseRequest connRequest1 = mgr.lease(route, null);
         final ConnectionEndpoint endpoint1 = connRequest1.get(1, TimeUnit.SECONDS);

http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/389272de/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 634a1f6..d867dd5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -68,7 +68,7 @@
   <properties>
     <maven.compiler.source>1.7</maven.compiler.source>
     <maven.compiler.target>1.7</maven.compiler.target>
-    <httpcore.version>5.0-alpha4</httpcore.version>
+    <httpcore.version>5.0-beta1</httpcore.version>
     <log4j.version>2.9.1</log4j.version>
     <commons-codec.version>1.10</commons-codec.version>
     <ehcache.version>3.4.0</ehcache.version>