5

I'm using Java 11 http-client (java.net.http).

The send() method declares these exceptions:

@throws IOException
@throws InterruptedException
@throws IllegalArgumentException
@throws SecurityException

I am interested in catching exceptions caused by timeout. I thought the best way of doing it is by catching HttpTimeoutException (extends IOException)

However, I sometimes see that when a timeout occurs the exception that is thrown is:

java.io.IOException: Connection timed out

Now I wonder:

  1. Why does the more general exception thrown?
  2. How should the catch be written to make sure all possible time-out related exceptions are caught?
ernest_k
  • 44,416
  • 5
  • 53
  • 99
user12396421
  • 175
  • 1
  • 10
  • Your catch clause can consider IOException|HttpTimeoutException| InterruptedByTimeoutException|TransportTimeoutException - those are the inherited timeout exceptions from IOExceptions, there might be more inherited exceptions of InterruptedException https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/IOException.html – planben Aug 31 '20 at 08:14

1 Answers1

0
@Override
public <T> HttpResponse<T>
send(HttpRequest req, BodyHandler<T> responseHandler)
    throws IOException, InterruptedException
{
    CompletableFuture<HttpResponse<T>> cf = null;
    try {
        cf = sendAsync(req, responseHandler, null, null);
        return cf.get();
    } catch (InterruptedException ie) {
        if (cf != null )
            cf.cancel(true);
        throw ie;
    } catch (ExecutionException e) {
        final Throwable throwable = e.getCause();
        final String msg = throwable.getMessage();

        if (throwable instanceof IllegalArgumentException) {
            throw new IllegalArgumentException(msg, throwable);
        } else if (throwable instanceof SecurityException) {
            throw new SecurityException(msg, throwable);
        } else if (throwable instanceof HttpConnectTimeoutException) {
            HttpConnectTimeoutException hcte = new HttpConnectTimeoutException(msg);
            hcte.initCause(throwable);
            throw hcte;
        } else if (throwable instanceof HttpTimeoutException) {
            throw new HttpTimeoutException(msg);
        } else if (throwable instanceof ConnectException) {
            ConnectException ce = new ConnectException(msg);
            ce.initCause(throwable);
            throw ce;
        } else if (throwable instanceof SSLHandshakeException) {
            // special case for SSLHandshakeException
            SSLHandshakeException he = new SSLHandshakeException(msg);
            he.initCause(throwable);
            throw he;
        } else if (throwable instanceof SSLException) {
            // any other SSLException is wrapped in a plain
            // SSLException
            throw new SSLException(msg, throwable);
        } else if (throwable instanceof IOException) {
            throw new IOException(msg, throwable);
        } else {
            throw new IOException(msg, throwable);
        }
    }
}

Please see method below which is an internal method of HttpClientImpl.java. Handle all the exceptions which you want to manage and accordingly you can implement your code.

If you handle HttpConnectTimeoutException, IOException, HttpTimeoutException then you are covered.

omkarjoshi
  • 86
  • 10
  • You mean catch IOException and search in the message if it contains "Connection timed out"? – user12396421 Aug 31 '20 at 10:56
  • That would be poor design as you can building your exception handling based on some message which could change in future. Implement only IOException catch block and internally check using instanceOf operator and implement your exception logic there(All other exceptions as far as I can see are extending IOException. This way you need to implement only single catch block). – omkarjoshi Aug 31 '20 at 12:08
  • Agree, but i still don't understand how you are planing to identify time out when it comes in the form of "java.io.IOException: Connection timed out", catching IOException is not good enough since there are many reasons for it to be thrown – user12396421 Aug 31 '20 at 12:32
  • You are right when IOException is thrown the only way you can identify as of now is based on message. – omkarjoshi Aug 31 '20 at 12:41