From 306134dcf9db6c44adf919fac29f5b227534bdee Mon Sep 17 00:00:00 2001 From: Darragh Clarke Date: Mon, 27 Feb 2023 09:18:56 +0000 Subject: [PATCH] 8300792: Refactor examples in java.net.http to use @snippet Reviewed-by: dfuchs, jpai --- .../classes/java/net/http/HttpClient.java | 23 +++--- .../classes/java/net/http/HttpRequest.java | 29 ++++--- .../classes/java/net/http/HttpResponse.java | 77 +++++++++++-------- .../classes/java/net/http/WebSocket.java | 60 ++++++++------- 4 files changed, 113 insertions(+), 76 deletions(-) diff --git a/src/java.net.http/share/classes/java/net/http/HttpClient.java b/src/java.net.http/share/classes/java/net/http/HttpClient.java index 2cb2a5d21de..dadadc6cc79 100644 --- a/src/java.net.http/share/classes/java/net/http/HttpClient.java +++ b/src/java.net.http/share/classes/java/net/http/HttpClient.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -85,7 +85,8 @@ import jdk.internal.net.http.HttpClientBuilderImpl; * * *

Synchronous Example - *

{@code    HttpClient client = HttpClient.newBuilder()
+ * {@snippet :
+ *   HttpClient client = HttpClient.newBuilder()
  *        .version(Version.HTTP_1_1)
  *        .followRedirects(Redirect.NORMAL)
  *        .connectTimeout(Duration.ofSeconds(20))
@@ -94,10 +95,11 @@ import jdk.internal.net.http.HttpClientBuilderImpl;
  *        .build();
  *   HttpResponse response = client.send(request, BodyHandlers.ofString());
  *   System.out.println(response.statusCode());
- *   System.out.println(response.body());  }
+ * System.out.println(response.body()); } * *

Asynchronous Example - *

{@code    HttpRequest request = HttpRequest.newBuilder()
+ * {@snippet :
+ *    HttpRequest request = HttpRequest.newBuilder()
  *        .uri(URI.create("https://foo.com/"))
  *        .timeout(Duration.ofMinutes(2))
  *        .header("Content-Type", "application/json")
@@ -105,7 +107,7 @@ import jdk.internal.net.http.HttpClientBuilderImpl;
  *        .build();
  *   client.sendAsync(request, BodyHandlers.ofString())
  *        .thenApply(HttpResponse::body)
- *        .thenAccept(System.out::println);  }
+ * .thenAccept(System.out::println); } * *

Security checks * @@ -688,20 +690,23 @@ public abstract class HttpClient { * Creates a new {@code WebSocket} builder (optional operation). * *

Example - *

{@code    HttpClient client = HttpClient.newHttpClient();
+     * {@snippet :
+     *   HttpClient client = HttpClient.newHttpClient();
      *   CompletableFuture ws = client.newWebSocketBuilder()
-     *           .buildAsync(URI.create("ws://websocket.example.com"), listener); }
+ * .buildAsync(URI.create("ws://websocket.example.com"), listener); } * *

Finer control over the WebSocket Opening Handshake can be achieved * by using a custom {@code HttpClient}. * *

Example - *

{@code    InetSocketAddress addr = new InetSocketAddress("proxy.example.com", 80);
+     * {@snippet :
+     *   InetSocketAddress addr = new InetSocketAddress("proxy.example.com", 80);
      *   HttpClient client = HttpClient.newBuilder()
      *           .proxy(ProxySelector.of(addr))
      *           .build();
+     *
      *   CompletableFuture ws = client.newWebSocketBuilder()
-     *           .buildAsync(URI.create("ws://websocket.example.com"), listener); }
+ * .buildAsync(URI.create("ws://websocket.example.com"), listener); } * * @implSpec The default implementation of this method throws * {@code UnsupportedOperationException}. Clients obtained through diff --git a/src/java.net.http/share/classes/java/net/http/HttpRequest.java b/src/java.net.http/share/classes/java/net/http/HttpRequest.java index 974ea54717e..a91cb935dc8 100644 --- a/src/java.net.http/share/classes/java/net/http/HttpRequest.java +++ b/src/java.net.http/share/classes/java/net/http/HttpRequest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,14 +66,17 @@ import static java.nio.charset.StandardCharsets.UTF_8; *

The following is an example of a GET request that prints the response * body as a String: * - *

{@code    HttpClient client = HttpClient.newHttpClient();
+ * {@snippet :
+ *   HttpClient client = HttpClient.newHttpClient();
+ *
  *   HttpRequest request = HttpRequest.newBuilder()
  *         .uri(URI.create("http://foo.com/"))
  *         .build();
+ *
  *   client.sendAsync(request, BodyHandlers.ofString())
  *         .thenApply(HttpResponse::body)
  *         .thenAccept(System.out::println)
- *         .join(); }
+ * .join(); } * *

The class {@link BodyPublishers BodyPublishers} provides implementations * of many common publishers. Alternatively, a custom {@code BodyPublisher} @@ -341,13 +344,16 @@ public abstract class HttpRequest { *

*

* * @param request the original request @@ -561,25 +567,28 @@ public abstract class HttpRequest { * convert common high-level Java objects into a flow of data suitable for * sending as a request body: * - *
{@code    // Request body from a String
+     * {@snippet :
+     *   // Request body from a String
      *   HttpRequest request = HttpRequest.newBuilder()
      *        .uri(URI.create("https://foo.com/"))
      *        .header("Content-Type", "text/plain; charset=UTF-8")
      *        .POST(BodyPublishers.ofString("some body text"))
-     *        .build();
+     *        .build(); }
      *
+     * {@snippet :
      *   // Request body from a File
      *   HttpRequest request = HttpRequest.newBuilder()
      *        .uri(URI.create("https://foo.com/"))
      *        .header("Content-Type", "application/json")
      *        .POST(BodyPublishers.ofFile(Paths.get("file.json")))
-     *        .build();
+     *        .build(); }
      *
+     * {@snippet :
      *   // Request body from a byte array
      *   HttpRequest request = HttpRequest.newBuilder()
      *        .uri(URI.create("https://foo.com/"))
      *        .POST(BodyPublishers.ofByteArray(new byte[] { ... }))
-     *        .build(); }
+ * .build(); } * * @since 11 */ diff --git a/src/java.net.http/share/classes/java/net/http/HttpResponse.java b/src/java.net.http/share/classes/java/net/http/HttpResponse.java index f518d86eae1..47f7da46d76 100644 --- a/src/java.net.http/share/classes/java/net/http/HttpResponse.java +++ b/src/java.net.http/share/classes/java/net/http/HttpResponse.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -77,8 +77,9 @@ import static jdk.internal.net.http.common.Utils.charsetFrom; * *

The following is an example of retrieving a response as a String: * - *

{@code    HttpResponse response = client
- *     .send(request, BodyHandlers.ofString()); }
+ * {@snippet : + * HttpResponse response = client + * .send(request, BodyHandlers.ofString()); } * *

The class {@link BodyHandlers BodyHandlers} provides implementations * of many common response handlers. Alternatively, a custom {@code BodyHandler} @@ -211,12 +212,14 @@ public interface HttpResponse { * predefined body handlers} that always process the response body in the * same way ( streams the response body to a file ). * - *

{@code   HttpRequest request = HttpRequest.newBuilder()
+     * {@snippet :
+     *    HttpRequest request = HttpRequest.newBuilder()
      *        .uri(URI.create("http://www.foo.com/"))
      *        .build();
+     *
      *  client.sendAsync(request, BodyHandlers.ofFile(Paths.get("/tmp/f")))
      *        .thenApply(HttpResponse::body)
-     *        .thenAccept(System.out::println); }
+ * .thenAccept(System.out::println); } * * Note, that even though the pre-defined handlers do not examine the * response code, the response code and headers are always retrievable from @@ -224,7 +227,8 @@ public interface HttpResponse { * *

In the second example, the function returns a different subscriber * depending on the status code. - *

{@code   HttpRequest request = HttpRequest.newBuilder()
+     * {@snippet :
+     *    HttpRequest request = HttpRequest.newBuilder()
      *        .uri(URI.create("http://www.foo.com/"))
      *        .build();
      *  BodyHandler bodyHandler = (rspInfo) -> rspInfo.statusCode() == 200
@@ -232,7 +236,7 @@ public interface HttpResponse {
      *                      : BodySubscribers.replacing(Paths.get("/NULL"));
      *  client.sendAsync(request, bodyHandler)
      *        .thenApply(HttpResponse::body)
-     *        .thenAccept(System.out::println); }
+ * .thenAccept(System.out::println); } * * @param the response body type * @see BodyHandlers @@ -272,21 +276,25 @@ public interface HttpResponse { *

The following are examples of using the predefined body handlers to * convert a flow of response body data into common high-level Java objects: * - *

{@code    // Receives the response body as a String
+     * {@snippet :
+     *   // Receives the response body as a String
      *   HttpResponse response = client
-     *     .send(request, BodyHandlers.ofString());
+     *     .send(request, BodyHandlers.ofString()); }
      *
+     * {@snippet :
      *   // Receives the response body as a file
      *   HttpResponse response = client
-     *     .send(request, BodyHandlers.ofFile(Paths.get("example.html")));
+     *     .send(request, BodyHandlers.ofFile(Paths.get("example.html"))); }
      *
+     * {@snippet :
      *   // Receives the response body as an InputStream
      *   HttpResponse response = client
-     *     .send(request, BodyHandlers.ofInputStream());
+     *     .send(request, BodyHandlers.ofInputStream()); }
      *
+     * {@snippet :
      *   // Discards the response body
      *   HttpResponse response = client
-     *     .send(request, BodyHandlers.discarding());  }
+ * .send(request, BodyHandlers.discarding()); } * * @since 11 */ @@ -310,10 +318,11 @@ public interface HttpResponse { * BodySubscriber} and {@code Flow.Subscriber}. * *

For example: - *

 {@code  TextSubscriber subscriber = new TextSubscriber();
+         * {@snippet :
+         *  TextSubscriber subscriber = new TextSubscriber();
          *  HttpResponse response = client.sendAsync(request,
          *      BodyHandlers.fromSubscriber(subscriber)).join();
-         *  System.out.println(response.statusCode()); }
+ * System.out.println(response.statusCode()); } * * @param subscriber the subscriber * @return a response body handler @@ -340,10 +349,11 @@ public interface HttpResponse { * BodySubscriber} and {@code Flow.Subscriber}. * *

For example: - *

 {@code  TextSubscriber subscriber = ...;  // accumulates bytes and transforms them into a String
+         * {@snippet :
+         *  TextSubscriber subscriber = ...;  // accumulates bytes and transforms them into a String
          *  HttpResponse response = client.sendAsync(request,
          *      BodyHandlers.fromSubscriber(subscriber, TextSubscriber::getTextResult)).join();
-         *  String text = response.body(); }
+ * String text = response.body(); } * * @param the type of the Subscriber * @param the type of the response body @@ -380,7 +390,8 @@ public interface HttpResponse { * text line by line. * *

For example: - *

 {@code  // A PrintSubscriber that implements Flow.Subscriber
+         * {@snippet :
+         *  // A PrintSubscriber that implements Flow.Subscriber
          *  // and print lines received by onNext() on System.out
          *  PrintSubscriber subscriber = new PrintSubscriber(System.out);
          *  client.sendAsync(request, BodyHandlers.fromLineSubscriber(subscriber))
@@ -389,7 +400,7 @@ public interface HttpResponse {
          *          if (status != 200) {
          *              System.err.printf("ERROR: %d status received%n", status);
          *          }
-         *      }); }
+ * }); } * * @param subscriber the subscriber * @return a response body handler @@ -423,7 +434,8 @@ public interface HttpResponse { * text line by line. * *

For example: - *

 {@code  // A LineParserSubscriber that implements Flow.Subscriber
+         * {@snippet :
+         *  // A LineParserSubscriber that implements Flow.Subscriber
          *  // and accumulates lines that match a particular pattern
          *  Pattern pattern = ...;
          *  LineParserSubscriber subscriber = new LineParserSubscriber(pattern);
@@ -431,7 +443,7 @@ public interface HttpResponse {
          *      BodyHandlers.fromLineSubscriber(subscriber, s -> s.getMatchingLines(), "\n"));
          *  if (response.statusCode() != 200) {
          *      System.err.printf("ERROR: %d status received%n", response.statusCode());
-         *  } }
+ * } } * * * @param the type of the Subscriber @@ -904,23 +916,26 @@ public interface HttpResponse { * to convert a flow of response body data into common high-level Java * objects: * - *
{@code    // Streams the response body to a File
+     * {@snippet :
+     *   // Streams the response body to a File
      *   HttpResponse response = client
-     *     .send(request, responseInfo -> BodySubscribers.ofFile(Paths.get("example.html"));
+     *     .send(request, responseInfo -> BodySubscribers.ofFile(Paths.get("example.html")); }
      *
+     * {@snippet :
      *   // Accumulates the response body and returns it as a byte[]
      *   HttpResponse response = client
-     *     .send(request, responseInfo -> BodySubscribers.ofByteArray());
+     *     .send(request, responseInfo -> BodySubscribers.ofByteArray()); }
      *
+     * {@snippet :
      *   // Discards the response body
      *   HttpResponse response = client
-     *     .send(request, responseInfo -> BodySubscribers.discarding());
+     *     .send(request, responseInfo -> BodySubscribers.discarding()); }
      *
+     * {@snippet :
      *   // Accumulates the response body as a String then maps it to its bytes
      *   HttpResponse response = client
      *     .send(request, responseInfo ->
-     *        BodySubscribers.mapping(BodySubscribers.ofString(UTF_8), String::getBytes));
-     * }
+ * BodySubscribers.mapping(BodySubscribers.ofString(UTF_8), String::getBytes)); } * * @since 11 */ @@ -988,9 +1003,8 @@ public interface HttpResponse { * @apiNote This method can be used as an adapter between {@code * BodySubscriber} and {@code Flow.Subscriber}. * - * @implNote This is equivalent to calling
{@code
-         *      fromLineSubscriber(subscriber, s -> null, StandardCharsets.UTF_8, null)
-         * }
+ * @implNote This is equivalent to calling {@snippet : + * fromLineSubscriber(subscriber, s -> null, StandardCharsets.UTF_8, null) } * * @param subscriber the subscriber * @return a body subscriber @@ -1330,7 +1344,8 @@ public interface HttpResponse { * convert an {@code InputStream} into any annotated Java type. * *

For example: - *

 {@code  public static  BodySubscriber> asJSON(Class targetType) {
+         * {@snippet :
+         *   public static  BodySubscriber> asJSON(Class targetType) {
          *     BodySubscriber upstream = BodySubscribers.ofInputStream();
          *
          *     BodySubscriber> downstream = BodySubscribers.mapping(
@@ -1344,7 +1359,7 @@ public interface HttpResponse {
          *               }
          *           });
          *    return downstream;
-         *  } }
+ * } } * * @param the upstream body type * @param the type of the body subscriber returned diff --git a/src/java.net.http/share/classes/java/net/http/WebSocket.java b/src/java.net.http/share/classes/java/net/http/WebSocket.java index 9833ba5edc4..83b0bf000a7 100644 --- a/src/java.net.http/share/classes/java/net/http/WebSocket.java +++ b/src/java.net.http/share/classes/java/net/http/WebSocket.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -258,7 +258,8 @@ public interface WebSocket { * Here is an example of a listener that requests invocations, one at a * time, until a complete message has been accumulated, then processes * the result, and completes the {@code CompletionStage}: - *
{@code     WebSocket.Listener listener = new WebSocket.Listener() {
+     * {@snippet :
+     *        WebSocket.Listener listener = new WebSocket.Listener() {
      *
      *        List parts = new ArrayList<>();
      *        CompletableFuture accumulatedMessage = new CompletableFuture<>();
@@ -278,8 +279,7 @@ public interface WebSocket {
      *            }
      *            return accumulatedMessage;
      *        }
-     *    ...
-     *    } } 
+ * }; } * * @since 11 */ @@ -292,7 +292,8 @@ public interface WebSocket { * typically used to make a request for more invocations. * * @implSpec The default implementation is equivalent to: - *
{@code     webSocket.request(1); }
+ * {@snippet : + * webSocket.request(1); } * * @param webSocket * the WebSocket that has been connected @@ -308,8 +309,9 @@ public interface WebSocket { * this {@code CompletionStage} has completed. * * @implSpec The default implementation is equivalent to: - *
{@code     webSocket.request(1);
-         *    return null; }
+ * {@snippet : + * webSocket.request(1); + * return null; } * * @implNote The {@code data} is always a legal UTF-16 sequence. * @@ -343,8 +345,9 @@ public interface WebSocket { * this {@code CompletionStage} has completed. * * @implSpec The default implementation is equivalent to: - *
{@code     webSocket.request(1);
-         *    return null; }
+ * {@snippet : + * webSocket.request(1); + * return null; } * * @param webSocket * the WebSocket on which the data has been received @@ -381,8 +384,9 @@ public interface WebSocket { * this {@code CompletionStage} has completed. * * @implSpec The default implementation is equivalent to: - *
{@code     webSocket.request(1);
-         *    return null; }
+ * {@snippet : + * webSocket.request(1); + * return null; } * * @param webSocket * the WebSocket on which the message has been received @@ -412,8 +416,9 @@ public interface WebSocket { * this {@code CompletionStage} has completed. * * @implSpec The default implementation is equivalent to: - *
{@code     webSocket.request(1);
-         *    return null; }
+ * {@snippet : + * webSocket.request(1); + * return null; } * * @param webSocket * the WebSocket on which the message has been received @@ -456,12 +461,13 @@ public interface WebSocket { *

To specify a custom closure code or reason code the * {@code sendClose} method may be invoked from inside the * {@code onClose} invocation: - *

{@code     public CompletionStage onClose(WebSocket webSocket,
-         *                                      int statusCode,
-         *                                      String reason) {
+         * {@snippet :
+         *       public CompletionStage onClose(WebSocket webSocket,
+         *                            int statusCode,
+         *                            String reason) {
          *        webSocket.sendClose(CUSTOM_STATUS_CODE, CUSTOM_REASON);
          *        return new CompletableFuture();
-         *    } } 
+ * } } * * @implSpec The default implementation of this method returns * {@code null}, indicating that the output should be closed @@ -654,11 +660,13 @@ public interface WebSocket { * * @apiNote Use the provided integer constant {@link #NORMAL_CLOSURE} as a * status code and an empty string as a reason in a typical case: - *
{@code     CompletableFuture webSocket = ...
-     *    webSocket.thenCompose(ws -> ws.sendText("Hello, ", false))
+     * {@snippet :
+     *      CompletableFuture webSocket = ...
+     *      webSocket.thenCompose(ws -> ws.sendText("Hello, ", false))
      *             .thenCompose(ws -> ws.sendText("world!", true))
      *             .thenCompose(ws -> ws.sendClose(WebSocket.NORMAL_CLOSURE, ""))
-     *             .join(); }
+ * .join(); + * } * * The {@code sendClose} method does not close this WebSocket's input. It * merely closes this WebSocket's output by sending a Close message. To @@ -666,7 +674,8 @@ public interface WebSocket { * example of an application that sends a Close message, and then starts a * timer. Once no data has been received within the specified timeout, the * timer goes off and the alarm aborts {@code WebSocket}: - *
{@code     MyAlarm alarm = new MyAlarm(webSocket::abort);
+     * {@snippet :
+     *    MyAlarm alarm = new MyAlarm(webSocket::abort);
      *    WebSocket.Listener listener = new WebSocket.Listener() {
      *
      *        public CompletionStage onText(WebSocket webSocket,
@@ -682,8 +691,7 @@ public interface WebSocket {
      *        MyTimer idleTimer = new MyTimer();
      *        idleTimer.add(alarm, 30, TimeUnit.SECONDS);
      *    };
-     *    webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "ok").thenRun(startTimer);
-     * } 
+ * webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "ok").thenRun(startTimer); } * * @param statusCode * the status code @@ -717,7 +725,8 @@ public interface WebSocket { *

Here is an example of a listener that requests invocations, one at a * time, until a complete message has been accumulated, and then processes * the result: - *

{@code     WebSocket.Listener listener = new WebSocket.Listener() {
+     * {@snippet :
+     *        WebSocket.Listener listener = new WebSocket.Listener() {
      *
      *        StringBuilder text = new StringBuilder();
      *
@@ -732,8 +741,7 @@ public interface WebSocket {
      *            webSocket.request(1);
      *            return null;
      *        }
-     *    ...
-     *    } } 
+ * }; } * * @param n * the number of invocations