http-client-branch: remove remaining vestiges of MultiSubscriber and minor doc cleanup http-client-branch
authorchegar
Tue, 06 Feb 2018 19:26:38 +0000
branchhttp-client-branch
changeset 56085 544869ae0b16
parent 56084 6146d87993db
child 56086 ba42a59d3072
http-client-branch: remove remaining vestiges of MultiSubscriber and minor doc cleanup
src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/HttpClient.java
src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/HttpRequest.java
--- a/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/HttpClient.java	Tue Feb 06 17:26:49 2018 +0000
+++ b/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/HttpClient.java	Tue Feb 06 19:26:38 2018 +0000
@@ -43,15 +43,40 @@
 import jdk.incubator.http.internal.HttpClientBuilderImpl;
 
 /**
- * A container for configuration information common to multiple {@link
- * HttpRequest}s. All requests are sent through a {@code HttpClient}.
+ * An HTTP Client.
  * {@Incubating}
  *
- * <p> {@code HttpClient}s are immutable and created from a builder returned
- * from {@link HttpClient#newBuilder()}. Request builders are created by calling
- * {@link HttpRequest#newBuilder() }.
- * <p>
- * See {@link HttpRequest} for examples of usage of this API.
+ * <p> An {@code HttpClient} can be used to send requests and retrieve their
+ * responses. An {@code HttpClient} is created through a {@link
+ * HttpClient#newBuilder() builder}. The builder can be used to configure
+ * per-client state, like: the preferred protocol version ( HTTP/1.1 or HTTP/2 ),
+ * whether to follow redirects, a proxy, an authenticator, etc. Once built, an
+ * {@code HttpClient} is immutable, and can be used to send multiple requests.
+ *
+ * <p> An {@code HttpClient} provides configuration information, and resource
+ * sharing, for all requests send through it.
+ *
+ * <p>For Example:
+ * <pre>{@code    HttpClient client = HttpClient.newBuilder()
+ *        .version(Version.HTTP_2)
+ *        .followRedirects(Redirect.SAME_PROTOCOL)
+ *        .proxy(ProxySelector.of(new InetSocketAddress("proxy.com", 8080)))
+ *        .authenticator(Authenticator.getDefault())
+ *        .build();
+ *
+ *   HttpRequest request = HttpRequest.newBuilder()
+ *        .uri(URI.create("http://foo.com/"))
+ *        .timeout(Duration.ofMinutes(1))
+ *        .header("Content-Type", "application/json")
+ *        .POST(BodyPublisher.fromFile(Paths.get("file.json")))
+ *        .build();
+ *
+ *   client.sendAsync(request, BodyHandler.asString())
+ *        .thenApply(HttpResponse::body)
+ *        .thenAccept(System.out::println)
+ *        .join();  }</pre>
+ *
+ * <p> See {@link HttpRequest} for further examples of usage of this API.
  *
  * @since 9
  */
--- a/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/HttpRequest.java	Tue Feb 06 17:26:49 2018 +0000
+++ b/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/HttpRequest.java	Tue Feb 06 19:26:38 2018 +0000
@@ -44,84 +44,69 @@
 import java.util.concurrent.Executor;
 import java.util.concurrent.Flow;
 import java.util.function.Supplier;
+import jdk.incubator.http.HttpResponse.BodyHandler;
 import jdk.incubator.http.internal.HttpRequestBuilderImpl;
 import jdk.incubator.http.internal.RequestPublishers;
 import static java.nio.charset.StandardCharsets.UTF_8;
 
 /**
- * Represents one HTTP request which can be sent to a server.
+ * An HTTP request.
  * {@Incubating }
  *
- * <p> {@code HttpRequest} instances are built from {@code HttpRequest}
- * {@linkplain HttpRequest.Builder builders}. {@code HttpRequest} builders
- * are obtained by calling {@link HttpRequest#newBuilder(URI) HttpRequest.newBuilder}.
- * A request's {@linkplain URI}, headers and body can be set. Request bodies are
- * provided through a {@link BodyPublisher} object supplied to the
+ * <p> An {@code HttpRequest} instance is built through a {@code HttpRequest}
+ * {@linkplain HttpRequest.Builder builder}. An {@code HttpRequest} builder
+ * is obtained from one of the {@link HttpRequest#newBuilder(URI) newBuilder}
+ * methods. A request's {@linkplain URI}, headers, and body can be set. Request
+ * bodies are provided through a {@link BodyPublisher} object supplied to the
  * {@link Builder#DELETE(BodyPublisher) DELETE},
  * {@link Builder#POST(BodyPublisher) POST} or
  * {@link Builder#PUT(BodyPublisher) PUT} methods.
- * {@link Builder#GET() GET} does not take a body. Once all required
- * parameters have been set in the builder, {@link Builder#build() } is called
- * to return the {@code HttpRequest}. Builders can also be copied and modified
- * multiple times in order to build multiple related requests that differ in
- * some parameters.
- *
- * <p> Two simple, example HTTP interactions are shown below:
- * <pre>
- * {@code
- *      HttpClient client = HttpClient.newHttpClient();
+ * Once all required parameters have been set in the builder, {@link
+ * Builder#build() build} will return the {@code HttpRequest}. Builders can be
+ * copied and modified many times in order to build multiple related requests
+ * that differ in some parameters.
  *
- *      // GET
- *      HttpResponse<String> response = client.send(
- *          HttpRequest
- *              .newBuilder(new URI("http://www.foo.com/"))
- *              .headers("Foo", "foovalue", "Bar", "barvalue")
- *              .GET()
- *              .build(),
+ * <p> <b>Example HTTP interactions:</b>
+ * <pre>{@code    // GET
+ *    HttpResponse<String> response = client.send(
+ *          HttpRequest.newBuilder(new URI("http://www.foo.com/"))
+ *                     .headers("Foo", "foovalue", "Bar", "barvalue")
+ *                     .GET()
+ *                     .build(),
  *          BodyHandler.asString()
- *      );
- *      int statusCode = response.statusCode();
- *      String body = response.body();
+ *    );
+ *    int statusCode = response.statusCode();
+ *    String body = response.body();
  *
- *      // POST
- *      HttpResponse<Path> response = client.send(
- *          HttpRequest
- *              .newBuilder(new URI("http://www.foo.com/"))
- *              .headers("Foo", "foovalue", "Bar", "barvalue")
- *              .POST(BodyPublisher.fromString("Hello world"))
- *              .build(),
+ *    // POST
+ *    HttpResponse<Path> response = client.send(
+ *          HttpRequest.newBuilder(new URI("http://www.foo.com/"))
+ *                     .headers("Foo", "foovalue", "Bar", "barvalue")
+ *                     .POST(BodyPublisher.fromString("Hello world"))
+ *                     .build(),
  *          BodyHandler.asFile(Paths.get("/path"))
- *      );
- *      int statusCode = response.statusCode();
- *      Path body = response.body(); // should be "/path"
- * }
- * </pre>
+ *    );
+ *    int statusCode = response.statusCode();
+ *    Path body = response.body(); // should be "/path" }</pre>
  *
- * <p> The request is sent and the response obtained by calling one of the
+ * <p> The request is sent and the response obtained by invoking one of the
  * following methods in {@link HttpClient}.
- * <ul><li>{@link HttpClient#send(HttpRequest, HttpResponse.BodyHandler)} blocks
+ * <ul><li>{@link HttpClient#send(HttpRequest, BodyHandler)} blocks
  * until the entire request has been sent and the response has been received.</li>
- * <li>{@link HttpClient#sendAsync(HttpRequest,HttpResponse.BodyHandler)} sends the
+ * <li>{@link HttpClient#sendAsync(HttpRequest, BodyHandler)} sends the
  * request and receives the response asynchronously. Returns immediately with a
- * {@link java.util.concurrent.CompletableFuture CompletableFuture}&lt;{@link
- * HttpResponse}&gt;.</li>
- * <li>{@link HttpClient#sendAsync(HttpRequest, HttpResponse.MultiSubscriber) }
- * sends the request asynchronously, expecting multiple responses. This
- * capability is of most relevance to HTTP/2 server push, but can be used for
- * single responses (HTTP/1.1 or HTTP/2) also.</li>
+ * {@linkplain CompletableFuture CompletableFuture}&lt;{@linkplain HttpResponse}&gt;.</li>
  * </ul>
  *
- * <p> Once a {@link HttpResponse} is received, the headers, response code
- * and body (typically) are available. Whether the body has been read or not
- * depends on the type {@code <T>} of the response body. See below.
- *
- * <p> See below for discussion of synchronous versus asynchronous usage.
+ * <p> Once a {@link HttpResponse} is received, the headers, response code,
+ * and body (typically) are available. Whether the response body bytes has been
+ * read or not depends on the type {@code <T>} of the response body. See below.
  *
  * <p> <b>Request bodies</b>
  *
  * <p> Request bodies can be sent using one of the convenience request publisher
- * implementations below, provided in {@link BodyPublisher}. Alternatively, a
- * custom Publisher implementation can be used.
+ * implementations, provided in {@link BodyPublisher}. Alternatively, a custom
+ * Publisher implementation can be used.
  * <ul>
  * <li>{@link BodyPublisher#fromByteArray(byte[]) fromByteArray(byte[])} from byte array</li>
  * <li>{@link BodyPublisher#fromByteArrays(Iterable) fromByteArrays(Iterable)}
@@ -131,42 +116,35 @@
  * <li>{@link BodyPublisher#fromString(java.lang.String) fromString(String)} from a String </li>
  * <li>{@link BodyPublisher#fromInputStream(Supplier) fromInputStream}({@link Supplier}&lt;
  *      {@link InputStream}&gt;) from an InputStream obtained from a Supplier</li>
- * <li>{@link BodyPublisher#noBody() } no request body is sent</li>
+ * <li>{@link BodyPublisher#noBody() noBody()} no request body is sent</li>
  * </ul>
  *
  * <p> <b>Response bodies</b>
  *
  * <p> Responses bodies are handled at two levels. When sending the request,
- * a response body handler is specified. This is a function ({@linkplain
- * HttpResponse.BodyHandler}) which will be called with the response status code
- * and headers, once they are received. This function is then expected to return
- * a {@link HttpResponse.BodySubscriber}{@code <T>} which is then used to read
- * the response body, converting it into an instance of T. After this occurs,
- * the response becomes available in a {@link HttpResponse}, and {@link
- * HttpResponse#body()} can then be called to obtain the actual body. Some
+ * a response {@linkplain BodyHandler body handler} is specified. This is a
+ * function that will be called with the response status code and headers, once
+ * they are received. This function must to return a {@link
+ * HttpResponse.BodySubscriber}{@code <T>} which is used to read the response
+ * body bytes, converting them into an instance of {@code T}. After this occurs,
+ * the response becomes available in a {@link HttpResponse}, and the {@link
+ * HttpResponse#body()} can be invoked to obtain the actual body. Some
  * implementations and examples of usage of both {@link
  * HttpResponse.BodySubscriber} and {@link HttpResponse.BodyHandler} are
  * provided in {@link HttpResponse}:
  *
  * <p> <b>Some of the pre-defined body handlers</b><br>
  * <ul>
- * <li>{@link HttpResponse.BodyHandler#asByteArray() BodyHandler.asByteArray()}
+ * <li>{@link BodyHandler#asByteArray() BodyHandler.asByteArray()}
  * stores the body in a byte array</li>
- * <li>{@link HttpResponse.BodyHandler#asString() BodyHandler.asString()}
+ * <li>{@link BodyHandler#asString() BodyHandler.asString()}
  * stores the body as a String </li>
- * <li>{@link HttpResponse.BodyHandler#asFile(java.nio.file.Path)
+ * <li>{@link BodyHandler#asFile(java.nio.file.Path)
  * BodyHandler.asFile(Path)} stores the body in a named file</li>
- * <li>{@link HttpResponse.BodyHandler#discard(Object) BodyHandler.discard()}
- * discards the response body and returns the given value instead.</li>
+ * <li>{@link BodyHandler#replace(Object) BodyHandler.replace(Objectt)}
+ * discards the response body and returns the given replacement value instead.</li>
  * </ul>
  *
- * <p> <b>Multi responses</b>
- *
- * <p> With HTTP/2 it is possible for a server to return a main response and zero
- * or more additional responses (known as server pushes) to a client-initiated
- * request. These are handled using a special response subscriber called {@link
- * HttpResponse.MultiSubscriber}.
- *
  * <p> <b>Blocking/asynchronous behavior and thread usage</b>
  *
  * <p> There are two styles of request sending: <i>synchronous</i> and
@@ -178,9 +156,6 @@
  * HttpResponse}&gt; and when this object completes (possibly in a different
  * thread) the response has been received.
  *
- * <p> {@link HttpClient#sendAsync(HttpRequest, HttpResponse.MultiSubscriber)}
- * is the variant for multi responses and is also asynchronous.
- *
  * <p> Instances of {@code CompletableFuture} can be combined in different ways
  * to declare the dependencies among several asynchronous tasks, while allowing
  * for the maximum level of parallelism to be utilized.
@@ -207,21 +182,17 @@
  * {@linkplain AccessController#doPrivileged(PrivilegedAction) privileged context}.
  *
  * <p> <b>Examples</b>
- * <pre>{@code
- *      HttpClient client = HttpClient
- *              .newBuilder()
- *              .build();
+ * <pre>{@code    HttpClient client = HttpClient.newHttpClient();
  *
- *      HttpRequest request = HttpRequest
- *              .newBuilder(new URI("http://www.foo.com/"))
- *              .POST(BodyPublisher.fromString("Hello world"))
- *              .build();
+ *    HttpRequest request = HttpRequest
+ *            .newBuilder(URI.create("http://www.foo.com/"))
+ *            .POST(BodyPublisher.fromString("Hello world"))
+ *            .build();
  *
- *      HttpResponse<Path> response =
- *          client.send(request, BodyHandler.asFile(Paths.get("/path")));
+ *    HttpResponse<Path> response =
+ *        client.send(request, BodyHandler.asFile(Paths.get("/path")));
  *
- *      Path body = response.body();
- * }</pre>
+ *    Path body = response.body(); }</pre>
  *
  * <p><b>Asynchronous Example</b>
  *
@@ -233,36 +204,29 @@
  * can be sent asynchronously. It also shows how dependent asynchronous operations
  * (receiving response, and receiving response body) can be chained easily using
  * one of the many methods in {@code CompletableFuture}.
- * <pre>
- * {@code
- *  // fetch a list of target URIs asynchronously and store them in Files.
+ * <pre>{@code     // fetch a list of target URIs asynchronously and store them in Files.
  *
- *      List<URI> targets = ...
+ *    List<URI> targets = ...
  *
- *      List<CompletableFuture<File>> futures = targets
- *          .stream()
- *          .map(target -> client
- *                  .sendAsync(
- *                      HttpRequest.newBuilder(target)
- *                                 .GET()
- *                                 .build(),
- *                      BodyHandler.asFile(Paths.get("base", target.getPath())))
- *                  .thenApply(response -> response.body())
- *                  .thenApply(path -> path.toFile()))
- *          .collect(Collectors.toList());
+ *    List<CompletableFuture<File>> futures = targets
+ *        .stream()
+ *        .map(target -> client
+ *                .sendAsync(
+ *                    HttpRequest.newBuilder(target)
+ *                               .GET()
+ *                               .build(),
+ *                    BodyHandler.asFile(Paths.get("base", target.getPath())))
+ *                .thenApply(response -> response.body())
+ *                .thenApply(path -> path.toFile()))
+ *        .collect(Collectors.toList());
  *
- *      // all async operations waited for here
- *
- *      CompletableFuture.allOf(futures.toArray(new CompletableFuture<?>[0]))
- *          .join();
+ *    // all async operations waited for here
  *
- *      // all elements of futures have completed and can be examined.
- *      // Use File.exists() to check whether file was successfully downloaded
- * }
- * </pre>
+ *    CompletableFuture.allOf(futures.toArray(new CompletableFuture<?>[0]))
+ *        .join();
  *
- * <p> Unless otherwise stated, {@code null} parameter values will cause methods
- * of this class to throw {@code NullPointerException}.
+ *    // all elements of futures have completed and can be examined.
+ *    // Use File.exists() to check whether file was successfully downloaded }</pre>
  *
  * @since 9
  */