Я тестировал новый HttpClient
из Java 11 и обнаружил следующее поведение:
Я делаю два асинхронных запроса к общедоступному REST API для тестирования и пробовал его с одним клиентом и двумя отдельнымиЗапросы.Этот процесс не выдавал никаких исключений.
String singleCommentUrl = "https://jsonplaceholder.typicode.com/comments/1";
String commentsUrl = "https://jsonplaceholder.typicode.com/comments";
Consumer<String> handleOneComment = s -> {
Gson gson = new Gson();
Comment comment = gson.fromJson(s, Comment.class);
System.out.println(comment);
};
Consumer<String> handleListOfComments = s -> {
Gson gson = new Gson();
Comment[] comments = gson.fromJson(s, Comment[].class);
List<Comment> commentList = Arrays.asList(comments);
commentList.forEach(System.out::println);
};
HttpClient client = HttpClient.newBuilder().build();
client.sendAsync(HttpRequest.newBuilder(URI.create(singleCommentUrl)).build(), HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(handleOneComment)
.join();
client.sendAsync(HttpRequest.newBuilder(URI.create(commentsUrl)).build(), HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(handleListOfComments)
.join();
Затем я попытался рефакторинг HttpClient
в метод, и я получил следующее исключение при попытке сделать второй запрос:
public void run() {
String singleCommentUrl = "https://jsonplaceholder.typicode.com/comments/1";
String commentsUrl = "https://jsonplaceholder.typicode.com/comments";
Consumer<String> handleOneComment = s -> {
Gson gson = new Gson();
Comment comment = gson.fromJson(s, Comment.class);
System.out.println(comment);
};
Consumer<String> handleListOfComments = s -> {
Gson gson = new Gson();
Comment[] comments = gson.fromJson(s, Comment[].class);
List<Comment> commentList = Arrays.asList(comments);
commentList.forEach(System.out::println);
};
sendRequest(handleOneComment, singleCommentUrl);
sendRequest(handleListOfComments, commentsUrl);
}
private void sendRequest(Consumer<String> onSucces, String url) {
HttpClient client = HttpClient.newBuilder().build();
HttpRequest request = HttpRequest.newBuilder(URI.create(url)).build();
client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(onSucces)
.join();
}
Это приводит к следующему исключению после успешного выполнения первого запроса и сбоя во втором:
Exception in thread "main" java.util.concurrent.CompletionException: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at java.base/java.util.concurrent.CompletableFuture.encodeRelay(CompletableFuture.java:367)
at java.base/java.util.concurrent.CompletableFuture.completeRelay(CompletableFuture.java:376)
at java.base/java.util.concurrent.CompletableFuture$UniCompose.tryFire(CompletableFuture.java:1074)
at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:506)
at java.base/java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:2088)
at java.net.http/jdk.internal.net.http.common.SSLFlowDelegate.handleError(SSLFlowDelegate.java:904)
at java.net.http/jdk.internal.net.http.common.SSLFlowDelegate$Reader.processData(SSLFlowDelegate.java:450)
at java.net.http/jdk.internal.net.http.common.SSLFlowDelegate$Reader$ReaderDownstreamPusher.run(SSLFlowDelegate.java:263)
at java.net.http/jdk.internal.net.http.common.SequentialScheduler$SynchronizedRestartableTask.run(SequentialScheduler.java:175)
at java.net.http/jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run(SequentialScheduler.java:147)
at java.net.http/jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run(SequentialScheduler.java:198)
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:834)
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:128)
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:308)
at java.base/sun.security.ssl.Alert$AlertConsumer.consume(Alert.java:279)
at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:181)
at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:164)
at java.base/sun.security.ssl.SSLEngineImpl.decode(SSLEngineImpl.java:672)
at java.base/sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:627)
at java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:443)
at java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:422)
at java.base/javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:634)
at java.net.http/jdk.internal.net.http.common.SSLFlowDelegate$Reader.unwrapBuffer(SSLFlowDelegate.java:480)
at java.net.http/jdk.internal.net.http.common.SSLFlowDelegate$Reader.processData(SSLFlowDelegate.java:389)
... 7 more
Я также пытался передавать отдельные клиенты и запросы через параметры в методе, но это приводило к тому же результату.,Что здесь происходит?