Consider the following code:

public class HttpClientTest {
    public static void main(final String[] args) {
        final HttpClient httpClient = HttpClient.newBuilder().build();
        final String targetURL = "http://unknown.host.foo.bar.com.nowhere";;
        final HttpRequest request = HttpRequest.newBuilder().uri(URI.create(targetURL))                                 .method("HEAD", HttpRequest.BodyPublishers.noBody())
                                .build();
        try {
            httpClient.send(request, HttpResponse.BodyHandlers.discarding());
        } catch(IOException | InterruptedException e) {
            // intentionally ignore
            System.out.println("Caught an intentionally ignored exception");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

which tries to send a request to (in this case an intentional) non-existent address. The exception that gets thrown is:


java.nio.channels.UnresolvedAddressException
    at java.base/sun.nio.ch.Net.checkAddress(Net.java:130)
    at java.base/sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:674)     at java.net.http/jdk.internal.net.http.PlainHttpConnection.lambda$connectAsync$0(PlainHttpConnection.java:113)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.net.http/jdk.internal.net.http.PlainHttpConnection.connectAsync(PlainHttpConnection.java:115)     at java.net.http/jdk.internal.net.http.Http1Exchange.sendHeadersAsync(Http1Exchange.java:261)     at java.net.http/jdk.internal.net.http.Exchange.lambda$responseAsyncImpl0$8(Exchange.java:385)     at java.net.http/jdk.internal.net.http.Exchange.checkFor407(Exchange.java:320)     at java.net.http/jdk.internal.net.http.Exchange.lambda$responseAsyncImpl0$9(Exchange.java:389)     at java.base/java.util.concurrent.CompletableFuture.uniHandle(CompletableFuture.java:930)     at java.base/java.util.concurrent.CompletableFuture.uniHandleStage(CompletableFuture.java:946)     at java.base/java.util.concurrent.CompletableFuture.handle(CompletableFuture.java:2266)     at java.net.http/jdk.internal.net.http.Exchange.responseAsyncImpl0(Exchange.java:389)     at java.net.http/jdk.internal.net.http.Exchange.responseAsyncImpl(Exchange.java:299)     at java.net.http/jdk.internal.net.http.Exchange.responseAsync(Exchange.java:291)     at java.net.http/jdk.internal.net.http.MultiExchange.responseAsyncImpl(MultiExchange.java:240)     at java.net.http/jdk.internal.net.http.MultiExchange.lambda$responseAsync0$1(MultiExchange.java:205)     at java.base/java.util.concurrent.CompletableFuture$UniCompose.tryFire(CompletableFuture.java:1072)     at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:506)     at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1705)     at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)     at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at java.base/java.lang.Thread.run(Thread.java:832)


It's a different matter that this stacktrace is missing the caller's stack frames and that's being tracked in [1]. The javadoc of send method doesn't mention anything about what specific exception gets thrown in case of connection failures. It does say:

     * @throws IllegalArgumentException if the {@code request} argument is not      *         a request that could have been validly built as specified by {@link
     *         HttpRequest.Builder HttpRequest.Builder}.

and the thrown java.nio.channels.UnresolvedAddressException indeed extends IllegalArgumentException. However, given that the API itself doesn't say anything about exceptions that get thrown on connection failures, adding a catch block specifically for java.nio.channels.UnresolvedAddressException seems like relying on the implementation detail. Can these APIs make it explicit what exception(s) can be expected to be thrown in case of connection failures, so that it's part of the contract?

[1] https://bugs.openjdk.java.net/browse/JDK-8203298

-Jaikiran

Reply via email to