1

so i'm following this example for retryHandler(), it has the try/finally. My question is: how to do retry for exception ?

public class HttpClientRetryHandlerExample {

    public static void main(String... args) throws IOException {

        CloseableHttpClient httpclient = HttpClients.custom()
                .setRetryHandler(retryHandler())
                .build();

        try {
            HttpGet httpget = new HttpGet("http://localhost:1234");
            System.out.println("Executing request " + httpget.getRequestLine());
            httpclient.execute(httpget);
            System.out.println("----------------------------------------");
            System.out.println("Request finished");
        } finally {
            httpclient.close();
        }
    }

    private static HttpRequestRetryHandler retryHandler(){
        return (exception, executionCount, context) -> {

            System.out.println("try request: " + executionCount);

            if (executionCount >= 5) {
                // Do not retry if over max retry count
                return false;
            }
            if (exception instanceof InterruptedIOException) {
                // Timeout
                return false;
            }
            if (exception instanceof UnknownHostException) {
                // Unknown host
                return false;
            }
            if (exception instanceof SSLException) {
                // SSL handshake exception
                return false;
            }
            HttpClientContext clientContext = HttpClientContext.adapt(context);
            HttpRequest request = clientContext.getRequest();
            boolean idempotent = !(request instanceof HttpEntityEnclosingRequest);
            if (idempotent) {
                // Retry if the request is considered idempotent
                return true;
            }
            return false;
        };
    }
}

The question is, why the example just have try/finally without catch ? Does that mean all exceptions will go to retryHandler() ?

user3552178
  • 2,719
  • 8
  • 40
  • 67

1 Answers1

1
  1. The exception logic is implemented by HttpClient inside the request execution pipeline. HttpRequestRetryHandler is merely a decision strategy used to determine whether or not failed requests would be re-executed. I admit HttpRequestRetryHandler might be a misnomer. It is not actually a handler.

  2. Only I/O exceptions are considered recoverable. Runtime exceptions are propagated to the caller.

ok2c
  • 26,450
  • 5
  • 63
  • 71
  • i saw your other post https://stackoverflow.com/questions/48541329/timeout-between-request-retries-apache-httpclient so my understanding is, the best solution is to use setServiceUnavailableRetryStrategy() to retry on all possible ones that can be retryable. For request timeout, guess it's the I/O exception you mentioned, will fall into the one in setRetryHandler() not setServiceUnavailableRetryStrategy(). Just to confirm. – user3552178 Apr 07 '19 at 13:41
  • The other question is: above example only has try/finally, do you suggest to put "catch" as well for runtime exceptions ? if it's wrong arguments or null pointer, retry won't help, but any other cases worth retrying ? – user3552178 Apr 07 '19 at 14:42
  • No. `UnavailableRetryStrategy` can be used to re-try message exchanges that result in a valid HTTP response message. It cannot be used to recover from exceptional conditions such as runtime exceptions. – ok2c Apr 07 '19 at 15:29
  • The code above is bad in many different ways. Please have a look at the section of HttpClient 5.0 migration guide regarding HttpClient 4.5 best practices https://ok2c.github.io/httpclient-migration-guide/preparation.html – ok2c Apr 07 '19 at 15:32
  • see if i get it this time, step 1 valid http response => UnavailableRetryStrategy, step 2 I/O exceptions => HttpRequestRetryHandler, step 3 runtime exceptions use try/catch block, retryHandler() should skip runtime exceptions. – user3552178 Apr 07 '19 at 20:05
  • 1
    Pretty much. Please make sure 1. to re-use `CloseableHttpClient` instance, 2. close `CloseableHttpResponse` instance with try-with-resources to avoid resource leakage. – ok2c Apr 08 '19 at 09:30