You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by mi...@apache.org on 2019/12/12 07:49:25 UTC

[httpcomponents-client] branch master updated: HTTPCLIENT-2035: Remove HttpRequestRetryHandler in favor of HttpRequestRetryStrategy

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

michaelo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/httpcomponents-client.git


The following commit(s) were added to refs/heads/master by this push:
     new 52c6cf7  HTTPCLIENT-2035: Remove HttpRequestRetryHandler in favor of HttpRequestRetryStrategy
52c6cf7 is described below

commit 52c6cf70370205b55e6eaef1b03c341366d59916
Author: Michael Osipov <mi...@apache.org>
AuthorDate: Tue Dec 10 22:24:17 2019 +0100

    HTTPCLIENT-2035: Remove HttpRequestRetryHandler in favor of HttpRequestRetryStrategy
    
    This closes #183
---
 .../hc/client5/http/HttpRequestRetryHandler.java   |  65 -------
 .../apache/hc/client5/http/impl/ChainElement.java  |   3 +-
 .../http/impl/DefaultHttpRequestRetryHandler.java  | 169 -------------------
 .../hc/client5/http/impl/async/AsyncRetryExec.java | 151 -----------------
 .../http/impl/async/H2AsyncClientBuilder.java      |  32 +---
 .../http/impl/async/HttpAsyncClientBuilder.java    |  32 +---
 .../http/impl/classic/HttpClientBuilder.java       |  33 +---
 .../hc/client5/http/impl/classic/RetryExec.java    | 122 --------------
 .../impl/TestDefaultHttpRequestRetryHandler.java   |  88 ----------
 .../client5/http/impl/classic/TestRetryExec.java   | 186 ---------------------
 10 files changed, 19 insertions(+), 862 deletions(-)

diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/HttpRequestRetryHandler.java b/httpclient5/src/main/java/org/apache/hc/client5/http/HttpRequestRetryHandler.java
deleted file mode 100644
index e1573b4..0000000
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/HttpRequestRetryHandler.java
+++ /dev/null
@@ -1,65 +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;
-
-import java.io.IOException;
-
-import org.apache.hc.core5.annotation.Contract;
-import org.apache.hc.core5.annotation.ThreadingBehavior;
-import org.apache.hc.core5.http.HttpRequest;
-import org.apache.hc.core5.http.protocol.HttpContext;
-
-/**
- * A handler for determining if an HttpRequest should be retried after a
- * recoverable exception during execution.
- * <p>
- * Implementations of this interface must be thread-safe. Access to shared
- * data must be synchronized as methods of this interface may be executed
- * from multiple threads.
- *
- * @since 4.0
- */
-@Contract(threading = ThreadingBehavior.STATELESS)
-public interface HttpRequestRetryHandler {
-
-    /**
-     * Determines if a method should be retried after an IOException
-     * occurs during execution.
-     *
-     * @param request request failed die to an I/O exception.
-     * @param exception the exception that occurred
-     * @param executionCount the number of times this method has been
-     * unsuccessfully executed
-     * @param context the context for the request execution
-     *
-     * @return {@code true} if the method should be retried, {@code false}
-     * otherwise
-     */
-    boolean retryRequest(HttpRequest request, IOException exception, int executionCount, HttpContext context);
-
-}
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/ChainElement.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/ChainElement.java
index 43c8dfb..0c34f83 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/ChainElement.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/ChainElement.java
@@ -34,7 +34,6 @@ package org.apache.hc.client5.http.impl;
  */
 public enum ChainElement {
 
-    REDIRECT, BACK_OFF, RETRY, RETRY_IO_ERROR, CACHING, PROTOCOL,
-    CONNECT, MAIN_TRANSPORT
+    REDIRECT, BACK_OFF, RETRY, CACHING, PROTOCOL, CONNECT, MAIN_TRANSPORT
 
 }
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/DefaultHttpRequestRetryHandler.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/DefaultHttpRequestRetryHandler.java
deleted file mode 100644
index 2591aa9..0000000
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/DefaultHttpRequestRetryHandler.java
+++ /dev/null
@@ -1,169 +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;
-
-import java.io.IOException;
-import java.io.InterruptedIOException;
-import java.net.ConnectException;
-import java.net.UnknownHostException;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-
-import javax.net.ssl.SSLException;
-
-import org.apache.hc.client5.http.HttpRequestRetryHandler;
-import org.apache.hc.core5.annotation.Contract;
-import org.apache.hc.core5.annotation.ThreadingBehavior;
-import org.apache.hc.core5.concurrent.CancellableDependency;
-import org.apache.hc.core5.http.ConnectionClosedException;
-import org.apache.hc.core5.http.HttpRequest;
-import org.apache.hc.core5.http.Methods;
-import org.apache.hc.core5.http.protocol.HttpContext;
-import org.apache.hc.core5.util.Args;
-
-/**
- * The default {@link HttpRequestRetryHandler} used by request executors.
- *
- * @since 4.0
- */
-@Contract(threading = ThreadingBehavior.STATELESS)
-public class DefaultHttpRequestRetryHandler implements HttpRequestRetryHandler {
-
-    public static final DefaultHttpRequestRetryHandler INSTANCE = new DefaultHttpRequestRetryHandler();
-
-    /**
-     * the number of times a method will be retried
-     */
-    private final int retryCount;
-
-    private final Set<Class<? extends IOException>> nonRetriableClasses;
-
-    /**
-     * Create the request retry handler using the specified IOException classes
-     *
-     * @param retryCount how many times to retry; 0 means no retries
-     * @param clazzes    the IOException types that should not be retried
-     * @since 5.0
-     */
-    @SafeVarargs
-    protected DefaultHttpRequestRetryHandler(
-            final int retryCount,
-            final Class<? extends IOException>... clazzes) {
-        super();
-        this.retryCount = retryCount;
-        this.nonRetriableClasses = new HashSet<>();
-        this.nonRetriableClasses.addAll(Arrays.asList(clazzes));
-    }
-
-    /**
-     * Create the request retry handler using the following list of
-     * non-retriable IOException classes: <br>
-     * <ul>
-     * <li>InterruptedIOException</li>
-     * <li>UnknownHostException</li>
-     * <li>ConnectException</li>
-     * <li>ConnectionClosedException</li>
-     * <li>SSLException</li>
-     * </ul>
-     *
-     * @param retryCount how many times to retry; 0 means no retries
-     * @since 5.0
-     */
-    public DefaultHttpRequestRetryHandler(final int retryCount) {
-        this(retryCount,
-                InterruptedIOException.class,
-                UnknownHostException.class,
-                ConnectException.class,
-                ConnectionClosedException.class,
-                SSLException.class);
-    }
-
-    /**
-     * Create the request retry handler with a retry count of 3, requestSentRetryEnabled false
-     * and using the following list of non-retriable IOException classes: <br>
-     * <ul>
-     * <li>InterruptedIOException</li>
-     * <li>UnknownHostException</li>
-     * <li>ConnectException</li>
-     * <li>SSLException</li>
-     * </ul>
-     */
-    public DefaultHttpRequestRetryHandler() {
-        this(3);
-    }
-
-    /**
-     * Used {@code retryCount} and {@code requestSentRetryEnabled} to determine
-     * if the given method should be retried.
-     */
-    @Override
-    public boolean retryRequest(
-            final HttpRequest request,
-            final IOException exception,
-            final int executionCount,
-            final HttpContext context) {
-        Args.notNull(request, "HTTP request");
-        Args.notNull(exception, "I/O exception");
-
-        if (executionCount > this.retryCount) {
-            // Do not retry if over max retry count
-            return false;
-        }
-        if (this.nonRetriableClasses.contains(exception.getClass())) {
-            return false;
-        } else {
-            for (final Class<? extends IOException> rejectException : this.nonRetriableClasses) {
-                if (rejectException.isInstance(exception)) {
-                    return false;
-                }
-            }
-        }
-        if (request instanceof CancellableDependency && ((CancellableDependency) request).isCancelled()) {
-            return false;
-        }
-
-        // Retry if the request is considered idempotent
-        return handleAsIdempotent(request);
-    }
-
-    /**
-     * @return the maximum number of times a method will be retried
-     */
-    public int getRetryCount() {
-        return retryCount;
-    }
-
-    /**
-     * @since 4.2
-     */
-    protected boolean handleAsIdempotent(final HttpRequest request) {
-        return Methods.isIdempotent(request.getMethod());
-    }
-
-}
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/AsyncRetryExec.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/AsyncRetryExec.java
deleted file mode 100644
index d301cf0..0000000
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/AsyncRetryExec.java
+++ /dev/null
@@ -1,151 +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 org.apache.hc.client5.http.HttpRequestRetryHandler;
-import org.apache.hc.client5.http.HttpRoute;
-import org.apache.hc.client5.http.async.AsyncExecCallback;
-import org.apache.hc.client5.http.async.AsyncExecChain;
-import org.apache.hc.client5.http.async.AsyncExecChainHandler;
-import org.apache.hc.client5.http.impl.RequestCopier;
-import org.apache.hc.client5.http.protocol.HttpClientContext;
-import org.apache.hc.core5.annotation.Contract;
-import org.apache.hc.core5.annotation.Internal;
-import org.apache.hc.core5.annotation.ThreadingBehavior;
-import org.apache.hc.core5.http.EntityDetails;
-import org.apache.hc.core5.http.HttpException;
-import org.apache.hc.core5.http.HttpRequest;
-import org.apache.hc.core5.http.HttpResponse;
-import org.apache.hc.core5.http.nio.AsyncDataConsumer;
-import org.apache.hc.core5.http.nio.AsyncEntityProducer;
-import org.apache.hc.core5.util.Args;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Request execution handler in the asynchronous request execution chain
- * responsbile for making a decision whether a request failed due to
- * an I/O error should be re-executed.
- * <p>
- * Further responsibilities such as communication with the opposite
- * endpoint is delegated to the next executor in the request execution
- * chain.
- * </p>
- *
- * @since 5.0
- */
-@Contract(threading = ThreadingBehavior.STATELESS)
-@Internal
-public final class AsyncRetryExec implements AsyncExecChainHandler {
-
-    private final Logger log = LoggerFactory.getLogger(getClass());
-
-    private final HttpRequestRetryHandler retryHandler;
-
-    public AsyncRetryExec(final HttpRequestRetryHandler retryHandler) {
-        Args.notNull(retryHandler, "HTTP request retry handler");
-        this.retryHandler = retryHandler;
-    }
-
-    private void internalExecute(
-            final int execCount,
-            final HttpRequest request,
-            final AsyncEntityProducer entityProducer,
-            final AsyncExecChain.Scope scope,
-            final AsyncExecChain chain,
-            final AsyncExecCallback asyncExecCallback) throws HttpException, IOException {
-
-        final String exchangeId = scope.exchangeId;
-
-        chain.proceed(RequestCopier.INSTANCE.copy(request), entityProducer, scope, new AsyncExecCallback() {
-
-            @Override
-            public AsyncDataConsumer handleResponse(
-                    final HttpResponse response,
-                    final EntityDetails entityDetails) throws HttpException, IOException {
-                return asyncExecCallback.handleResponse(response, entityDetails);
-            }
-
-            @Override
-            public void handleInformationResponse(final HttpResponse response) throws HttpException, IOException {
-                asyncExecCallback.handleInformationResponse(response);
-            }
-
-            @Override
-            public void completed() {
-                asyncExecCallback.completed();
-            }
-
-            @Override
-            public void failed(final Exception cause) {
-                if (cause instanceof IOException) {
-                    final HttpRoute route = scope.route;
-                    final HttpClientContext clientContext = scope.clientContext;
-                    if (entityProducer != null && !entityProducer.isRepeatable()) {
-                        if (log.isDebugEnabled()) {
-                            log.debug(exchangeId + ": cannot retry non-repeatable request");
-                        }
-                    } else if (retryHandler.retryRequest(request, (IOException) cause, execCount, clientContext)) {
-                        if (log.isDebugEnabled()) {
-                            log.debug(exchangeId + ": " + cause.getMessage(), cause);
-                        }
-                        if (log.isInfoEnabled()) {
-                            log.info("Recoverable I/O exception ("+ cause.getClass().getName() + ") " +
-                                    "caught when processing request to " + route);
-                        }
-                        scope.execRuntime.discardEndpoint();
-                        if (entityProducer != null) {
-                            entityProducer.releaseResources();
-                        }
-                        try {
-                            internalExecute(execCount + 1, request, entityProducer, scope, chain, asyncExecCallback);
-                        } catch (final IOException | HttpException ex) {
-                            asyncExecCallback.failed(ex);
-                        }
-                        return;
-                    }
-                }
-                asyncExecCallback.failed(cause);
-            }
-
-        });
-
-    }
-
-    @Override
-    public void execute(
-            final HttpRequest request,
-            final AsyncEntityProducer entityProducer,
-            final AsyncExecChain.Scope scope,
-            final AsyncExecChain chain,
-            final AsyncExecCallback asyncExecCallback) throws HttpException, IOException {
-        internalExecute(1, request, entityProducer, scope, chain, asyncExecCallback);
-    }
-
-}
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/H2AsyncClientBuilder.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/H2AsyncClientBuilder.java
index 501ece7..13ddb63 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/H2AsyncClientBuilder.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/H2AsyncClientBuilder.java
@@ -40,7 +40,6 @@ import java.util.concurrent.ThreadFactory;
 
 import org.apache.hc.client5.http.AuthenticationStrategy;
 import org.apache.hc.client5.http.DnsResolver;
-import org.apache.hc.client5.http.HttpRequestRetryHandler;
 import org.apache.hc.client5.http.HttpRequestRetryStrategy;
 import org.apache.hc.client5.http.SchemePortResolver;
 import org.apache.hc.client5.http.SystemDefaultDnsResolver;
@@ -192,7 +191,6 @@ public class H2AsyncClientBuilder {
 
     private HttpRoutePlanner routePlanner;
     private RedirectStrategy redirectStrategy;
-    private HttpRequestRetryHandler retryHandler;
     private HttpRequestRetryStrategy retryStrategy;
 
     private Lookup<AuthSchemeProvider> authSchemeRegistry;
@@ -381,17 +379,6 @@ public class H2AsyncClientBuilder {
     }
 
     /**
-     * Assigns {@link HttpRequestRetryHandler} instance.
-     * <p>
-     * Please note this value can be overridden by the {@link #disableAutomaticRetries()}
-     * method.
-     */
-    public final H2AsyncClientBuilder setRetryHandler(final HttpRequestRetryHandler retryHandler) {
-        this.retryHandler = retryHandler;
-        return this;
-    }
-
-    /**
      * Assigns {@link HttpRequestRetryStrategy} instance.
      * <p>
      * Please note this value can be overridden by the {@link #disableAutomaticRetries()}
@@ -687,20 +674,13 @@ public class H2AsyncClientBuilder {
 
         // Add request retry executor, if not disabled
         if (!automaticRetriesDisabled) {
-            final HttpRequestRetryHandler retryHandlerCopy = this.retryHandler;
-            if (retryHandlerCopy != null) {
-                execChainDefinition.addFirst(
-                        new AsyncRetryExec(retryHandlerCopy),
-                        ChainElement.RETRY_IO_ERROR.name());
-            } else {
-                HttpRequestRetryStrategy retryStrategyCopy = this.retryStrategy;
-                if (retryStrategyCopy == null) {
-                    retryStrategyCopy = DefaultHttpRequestRetryStrategy.INSTANCE;
-                }
-                execChainDefinition.addFirst(
-                        new AsyncHttpRequestRetryExec(retryStrategyCopy),
-                        ChainElement.RETRY.name());
+            HttpRequestRetryStrategy retryStrategyCopy = this.retryStrategy;
+            if (retryStrategyCopy == null) {
+                retryStrategyCopy = DefaultHttpRequestRetryStrategy.INSTANCE;
             }
+            execChainDefinition.addFirst(
+                    new AsyncHttpRequestRetryExec(retryStrategyCopy),
+                    ChainElement.RETRY.name());
         }
 
         HttpRoutePlanner routePlannerCopy = this.routePlanner;
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClientBuilder.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClientBuilder.java
index 97784b8..3a724f9 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClientBuilder.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClientBuilder.java
@@ -40,7 +40,6 @@ import java.util.concurrent.ThreadFactory;
 
 import org.apache.hc.client5.http.AuthenticationStrategy;
 import org.apache.hc.client5.http.ConnectionKeepAliveStrategy;
-import org.apache.hc.client5.http.HttpRequestRetryHandler;
 import org.apache.hc.client5.http.HttpRequestRetryStrategy;
 import org.apache.hc.client5.http.SchemePortResolver;
 import org.apache.hc.client5.http.SystemDefaultDnsResolver;
@@ -227,7 +226,6 @@ public class HttpAsyncClientBuilder {
 
     private HttpRoutePlanner routePlanner;
     private RedirectStrategy redirectStrategy;
-    private HttpRequestRetryHandler retryHandler;
     private HttpRequestRetryStrategy retryStrategy;
 
     private ConnectionReuseStrategy reuseStrategy;
@@ -488,17 +486,6 @@ public class HttpAsyncClientBuilder {
     }
 
     /**
-     * Assigns {@link HttpRequestRetryHandler} instance.
-     * <p>
-     * Please note this value can be overridden by the {@link #disableAutomaticRetries()}
-     * method.
-     */
-    public final HttpAsyncClientBuilder setRetryHandler(final HttpRequestRetryHandler retryHandler) {
-        this.retryHandler = retryHandler;
-        return this;
-    }
-
-    /**
      * Assigns {@link HttpRequestRetryStrategy} instance.
      * <p>
      * Please note this value can be overridden by the {@link #disableAutomaticRetries()}
@@ -837,20 +824,13 @@ public class HttpAsyncClientBuilder {
 
         // Add request retry executor, if not disabled
         if (!automaticRetriesDisabled) {
-            final HttpRequestRetryHandler retryHandlerCopy = this.retryHandler;
-            if (retryHandlerCopy != null) {
-                execChainDefinition.addFirst(
-                        new AsyncRetryExec(retryHandlerCopy),
-                        ChainElement.RETRY_IO_ERROR.name());
-            } else {
-                HttpRequestRetryStrategy retryStrategyCopy = this.retryStrategy;
-                if (retryStrategyCopy == null) {
-                    retryStrategyCopy = DefaultHttpRequestRetryStrategy.INSTANCE;
-                }
-                execChainDefinition.addFirst(
-                        new AsyncHttpRequestRetryExec(retryStrategyCopy),
-                        ChainElement.RETRY.name());
+            HttpRequestRetryStrategy retryStrategyCopy = this.retryStrategy;
+            if (retryStrategyCopy == null) {
+                retryStrategyCopy = DefaultHttpRequestRetryStrategy.INSTANCE;
             }
+            execChainDefinition.addFirst(
+                    new AsyncHttpRequestRetryExec(retryStrategyCopy),
+                    ChainElement.RETRY.name());
         }
 
         HttpRoutePlanner routePlannerCopy = this.routePlanner;
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/HttpClientBuilder.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/HttpClientBuilder.java
index c0c4a9c..b1d8a6b 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/HttpClientBuilder.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/HttpClientBuilder.java
@@ -39,7 +39,6 @@ import java.util.Map;
 
 import org.apache.hc.client5.http.AuthenticationStrategy;
 import org.apache.hc.client5.http.ConnectionKeepAliveStrategy;
-import org.apache.hc.client5.http.HttpRequestRetryHandler;
 import org.apache.hc.client5.http.HttpRequestRetryStrategy;
 import org.apache.hc.client5.http.SchemePortResolver;
 import org.apache.hc.client5.http.SystemDefaultDnsResolver;
@@ -203,7 +202,6 @@ public class HttpClientBuilder {
     private LinkedList<ResponseInterceptorEntry> responseInterceptors;
     private LinkedList<ExecInterceptorEntry> execInterceptors;
 
-    private HttpRequestRetryHandler retryHandler;
     private HttpRequestRetryStrategy retryStrategy;
     private HttpRoutePlanner routePlanner;
     private RedirectStrategy redirectStrategy;
@@ -495,17 +493,6 @@ public class HttpClientBuilder {
     }
 
     /**
-     * Assigns {@link HttpRequestRetryHandler} instance.
-     * <p>
-     * Please note this value can be overridden by the {@link #disableAutomaticRetries()}
-     * method.
-     */
-    public final HttpClientBuilder setRetryHandler(final HttpRequestRetryHandler retryHandler) {
-        this.retryHandler = retryHandler;
-        return this;
-    }
-
-    /**
      * Assigns {@link HttpRequestRetryStrategy} instance.
      * <p>
      * Please note this value can be overridden by the {@link #disableAutomaticRetries()}
@@ -861,21 +848,13 @@ public class HttpClientBuilder {
 
         // Add request retry executor, if not disabled
         if (!automaticRetriesDisabled) {
-            // This needs to be cleaned up as soon as HttpRequestRetryHandler will be removed
-            final HttpRequestRetryHandler retryHandlerCopy = this.retryHandler;
-            if (retryHandlerCopy != null) {
-                execChainDefinition.addFirst(
-                        new RetryExec(retryHandlerCopy),
-                        ChainElement.RETRY_IO_ERROR.name());
-            } else {
-                HttpRequestRetryStrategy retryStrategyCopy = this.retryStrategy;
-                if (retryStrategyCopy == null) {
-                    retryStrategyCopy = DefaultHttpRequestRetryStrategy.INSTANCE;
-                }
-                execChainDefinition.addFirst(
-                        new HttpRequestRetryExec(retryStrategyCopy),
-                        ChainElement.RETRY.name());
+            HttpRequestRetryStrategy retryStrategyCopy = this.retryStrategy;
+            if (retryStrategyCopy == null) {
+                retryStrategyCopy = DefaultHttpRequestRetryStrategy.INSTANCE;
             }
+            execChainDefinition.addFirst(
+                    new HttpRequestRetryExec(retryStrategyCopy),
+                    ChainElement.RETRY.name());
         }
 
         HttpRoutePlanner routePlannerCopy = this.routePlanner;
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/RetryExec.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/RetryExec.java
deleted file mode 100644
index 2e89f4a..0000000
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/RetryExec.java
+++ /dev/null
@@ -1,122 +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.classic;
-
-import java.io.IOException;
-
-import org.apache.hc.client5.http.HttpRequestRetryHandler;
-import org.apache.hc.client5.http.HttpRoute;
-import org.apache.hc.client5.http.classic.ExecChain;
-import org.apache.hc.client5.http.classic.ExecChainHandler;
-import org.apache.hc.client5.http.protocol.HttpClientContext;
-import org.apache.hc.core5.annotation.Contract;
-import org.apache.hc.core5.annotation.Internal;
-import org.apache.hc.core5.annotation.ThreadingBehavior;
-import org.apache.hc.core5.http.ClassicHttpRequest;
-import org.apache.hc.core5.http.ClassicHttpResponse;
-import org.apache.hc.core5.http.HttpEntity;
-import org.apache.hc.core5.http.HttpException;
-import org.apache.hc.core5.http.NoHttpResponseException;
-import org.apache.hc.core5.util.Args;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Request execution handler in the classic request execution chain
- * responsible for making a decision whether a request failed due to
- * an I/O error should be re-executed.
- * <p>
- * Further responsibilities such as communication with the opposite
- * endpoint is delegated to the next executor in the request execution
- * chain.
- * </p>
- *
- * @since 4.3
- */
-@Contract(threading = ThreadingBehavior.STATELESS)
-@Internal
-public final class RetryExec implements ExecChainHandler {
-
-    private final Logger log = LoggerFactory.getLogger(getClass());
-
-    private final HttpRequestRetryHandler retryHandler;
-
-    public RetryExec(
-            final HttpRequestRetryHandler retryHandler) {
-        Args.notNull(retryHandler, "HTTP request retry handler");
-        this.retryHandler = retryHandler;
-    }
-
-    @Override
-    public ClassicHttpResponse execute(
-            final ClassicHttpRequest request,
-            final ExecChain.Scope scope,
-            final ExecChain chain) throws IOException, HttpException {
-        Args.notNull(request, "HTTP request");
-        Args.notNull(scope, "Scope");
-        final String exchangeId = scope.exchangeId;
-        final HttpRoute route = scope.route;
-        final HttpClientContext context = scope.clientContext;
-        ClassicHttpRequest currentRequest = request;
-        for (int execCount = 1;; execCount++) {
-            try {
-                return chain.proceed(currentRequest, scope);
-            } catch (final IOException ex) {
-                if (scope.execRuntime.isExecutionAborted()) {
-                    throw new RequestFailedException("Request aborted");
-                }
-                final HttpEntity requestEntity = request.getEntity();
-                if (requestEntity != null && !requestEntity.isRepeatable()) {
-                    if (log.isDebugEnabled()) {
-                        log.debug(exchangeId + ": cannot retry non-repeatable request");
-                    }
-                    throw ex;
-                }
-                if (retryHandler.retryRequest(request, ex, execCount, context)) {
-                    if (log.isDebugEnabled()) {
-                        log.debug(exchangeId + ": " + ex.getMessage(), ex);
-                    }
-                    if (log.isInfoEnabled()) {
-                        log.info("Recoverable I/O exception ("+ ex.getClass().getName() + ") " +
-                                "caught when processing request to " + route);
-                    }
-                    currentRequest = ClassicRequestCopier.INSTANCE.copy(scope.originalRequest);
-                } else {
-                    if (ex instanceof NoHttpResponseException) {
-                        final NoHttpResponseException updatedex = new NoHttpResponseException(
-                                route.getTargetHost().toHostString() + " failed to respond");
-                        updatedex.setStackTrace(ex.getStackTrace());
-                        throw updatedex;
-                    }
-                    throw ex;
-                }
-            }
-        }
-    }
-
-}
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/TestDefaultHttpRequestRetryHandler.java b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/TestDefaultHttpRequestRetryHandler.java
deleted file mode 100644
index faf13af..0000000
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/TestDefaultHttpRequestRetryHandler.java
+++ /dev/null
@@ -1,88 +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;
-
-import java.io.IOException;
-import java.net.SocketTimeoutException;
-import java.net.UnknownHostException;
-
-import org.apache.hc.client5.http.classic.methods.HttpGet;
-import org.junit.Assert;
-import org.junit.Test;
-
-
-@SuppressWarnings("boxing") // test class
-public class TestDefaultHttpRequestRetryHandler {
-
-    @Test
-    public void noRetryOnConnectTimeout() throws Exception {
-        final HttpGet request = new HttpGet("/");
-
-        final DefaultHttpRequestRetryHandler retryHandler = new DefaultHttpRequestRetryHandler();
-        Assert.assertEquals(3, retryHandler.getRetryCount());
-
-        Assert.assertFalse(retryHandler.retryRequest(request, new SocketTimeoutException(), 1, null));
-    }
-
-    @Test
-    public void noRetryOnUnknownHost() throws Exception {
-        final HttpGet request = new HttpGet("/");
-
-        final DefaultHttpRequestRetryHandler retryHandler = new DefaultHttpRequestRetryHandler();
-
-        Assert.assertFalse(retryHandler.retryRequest(request, new UnknownHostException(), 1, null));
-    }
-
-    @Test
-    public void noRetryOnAbortedRequests() throws Exception{
-        final HttpGet request = new HttpGet("/");
-        request.cancel();
-
-        final DefaultHttpRequestRetryHandler retryHandler = new DefaultHttpRequestRetryHandler();
-
-        Assert.assertFalse(retryHandler.retryRequest(request, new IOException(), 3, null));
-    }
-
-    @Test
-    public void retryOnNonAbortedRequests() throws Exception{
-        final HttpGet request = new HttpGet("/");
-
-        final DefaultHttpRequestRetryHandler retryHandler = new DefaultHttpRequestRetryHandler();
-
-        Assert.assertTrue(retryHandler.retryRequest(request, new IOException(), 3, null));
-    }
-
-    @Test
-    public void noRetryOnConnectionTimeout() throws Exception{
-        final HttpGet request = new HttpGet("/");
-
-        final DefaultHttpRequestRetryHandler retryHandler = new DefaultHttpRequestRetryHandler();
-
-        Assert.assertFalse(retryHandler.retryRequest(request, new SocketTimeoutException(), 3, null));
-    }
-
-}
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestRetryExec.java b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestRetryExec.java
deleted file mode 100644
index 955753b..0000000
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestRetryExec.java
+++ /dev/null
@@ -1,186 +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.classic;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-import org.apache.hc.client5.http.HttpRequestRetryHandler;
-import org.apache.hc.client5.http.HttpRoute;
-import org.apache.hc.client5.http.classic.ExecChain;
-import org.apache.hc.client5.http.classic.ExecRuntime;
-import org.apache.hc.client5.http.classic.methods.HttpGet;
-import org.apache.hc.client5.http.classic.methods.HttpPost;
-import org.apache.hc.client5.http.entity.EntityBuilder;
-import org.apache.hc.client5.http.protocol.HttpClientContext;
-import org.apache.hc.core5.http.ClassicHttpRequest;
-import org.apache.hc.core5.http.Header;
-import org.apache.hc.core5.http.HttpHost;
-import org.apache.hc.core5.http.HttpRequest;
-import org.apache.hc.core5.http.protocol.HttpContext;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-
-@SuppressWarnings({"boxing","static-access"}) // test code
-public class TestRetryExec {
-
-    @Mock
-    private HttpRequestRetryHandler retryHandler;
-    @Mock
-    private ExecRuntime endpoint;
-    @Mock
-    private ExecChain chain;
-
-    private RetryExec retryExec;
-    private HttpHost target;
-
-    @Before
-    public void setup() throws Exception {
-        MockitoAnnotations.initMocks(this);
-        retryExec = new RetryExec(retryHandler);
-        target = new HttpHost("localhost", 80);
-    }
-
-    @Test(expected = IOException.class)
-    public void testFundamentals() throws Exception {
-        final HttpRoute route = new HttpRoute(target);
-        final HttpGet originalRequest = new HttpGet("/test");
-        originalRequest.addHeader("header", "this");
-        originalRequest.addHeader("header", "that");
-        final HttpClientContext context = HttpClientContext.create();
-
-        Mockito.when(chain.proceed(
-                Mockito.<ClassicHttpRequest>any(),
-                Mockito.<ExecChain.Scope>any())).thenAnswer(new Answer<Object>() {
-
-            @Override
-            public Object answer(final InvocationOnMock invocationOnMock) throws Throwable {
-                final Object[] args = invocationOnMock.getArguments();
-                final ClassicHttpRequest wrapper = (ClassicHttpRequest) args[0];
-                final Header[] headers = wrapper.getHeaders();
-                Assert.assertEquals(2, headers.length);
-                Assert.assertEquals("this", headers[0].getValue());
-                Assert.assertEquals("that", headers[1].getValue());
-                wrapper.addHeader("Cookie", "monster");
-                throw new IOException("Ka-boom");
-            }
-
-        });
-        Mockito.when(retryHandler.retryRequest(
-                Mockito.<HttpRequest>any(),
-                Mockito.<IOException>any(),
-                Mockito.eq(1),
-                Mockito.<HttpContext>any())).thenReturn(Boolean.TRUE);
-        final ExecChain.Scope scope = new ExecChain.Scope("test", route, originalRequest, endpoint, context);
-        final ClassicHttpRequest request = ClassicRequestCopier.INSTANCE.copy(originalRequest);
-        try {
-            retryExec.execute(request, scope, chain);
-        } catch (final IOException ex) {
-            Mockito.verify(chain, Mockito.times(2)).proceed(
-                    Mockito.<ClassicHttpRequest>any(),
-                    Mockito.same(scope));
-            throw ex;
-        }
-    }
-
-    @Test(expected = IOException.class)
-    public void testAbortedRequest() throws Exception {
-        final HttpRoute route = new HttpRoute(target);
-        final HttpGet originalRequest = new HttpGet("/test");
-        final HttpClientContext context = HttpClientContext.create();
-
-        Mockito.when(chain.proceed(
-                Mockito.<ClassicHttpRequest>any(),
-                Mockito.<ExecChain.Scope>any())).thenThrow(new IOException("Ka-boom"));
-        Mockito.when(endpoint.isExecutionAborted()).thenReturn(true);
-
-        final ExecChain.Scope scope = new ExecChain.Scope("test", route, originalRequest, endpoint, context);
-        final ClassicHttpRequest request = ClassicRequestCopier.INSTANCE.copy(originalRequest);
-        try {
-            retryExec.execute(request, scope, chain);
-        } catch (final IOException ex) {
-            Mockito.verify(chain, Mockito.times(1)).proceed(
-                    Mockito.same(request),
-                    Mockito.same(scope));
-            Mockito.verify(retryHandler, Mockito.never()).retryRequest(
-                    Mockito.<HttpRequest>any(),
-                    Mockito.<IOException>any(),
-                    Mockito.anyInt(),
-                    Mockito.<HttpContext>any());
-
-            throw ex;
-        }
-    }
-
-    @Test(expected = IOException.class)
-    public void testNonRepeatableRequest() throws Exception {
-        final HttpRoute route = new HttpRoute(target);
-        final HttpPost originalRequest = new HttpPost("/test");
-        originalRequest.setEntity(EntityBuilder.create()
-                .setStream(new ByteArrayInputStream(new byte[]{}))
-                .build());
-        final HttpClientContext context = HttpClientContext.create();
-
-        Mockito.when(chain.proceed(
-                Mockito.<ClassicHttpRequest>any(),
-                Mockito.<ExecChain.Scope>any())).thenAnswer(new Answer<Object>() {
-
-            @Override
-            public Object answer(final InvocationOnMock invocationOnMock) throws Throwable {
-                final Object[] args = invocationOnMock.getArguments();
-                final ClassicHttpRequest req = (ClassicHttpRequest) args[0];
-                req.getEntity().writeTo(new ByteArrayOutputStream());
-                throw new IOException("Ka-boom");
-            }
-
-        });
-        Mockito.when(retryHandler.retryRequest(
-                Mockito.<HttpRequest>any(),
-                Mockito.<IOException>any(),
-                Mockito.eq(1),
-                Mockito.<HttpContext>any())).thenReturn(Boolean.TRUE);
-        final ExecChain.Scope scope = new ExecChain.Scope("test", route, originalRequest, endpoint, context);
-        final ClassicHttpRequest request = ClassicRequestCopier.INSTANCE.copy(originalRequest);
-        try {
-            retryExec.execute(request, scope, chain);
-        } catch (final IOException ex) {
-            Mockito.verify(chain, Mockito.times(1)).proceed(
-                    Mockito.same(request),
-                    Mockito.same(scope));
-
-            throw ex;
-        }
-    }
-
-}