"java.io.IOException: Connection timed out" VS HttpTimeoutException On java 11 HTTP Client

Viewed 757

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?
1 Answers
@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.

Related