src/main/java/openjdk/http/tutorial/exercise1/Retrievals.java
branchhttp-client-tutorial
changeset 56018 40e766eb611b
parent 56017 fc030486080e
equal deleted inserted replaced
56017:fc030486080e 56018:40e766eb611b
    68 
    68 
    69     /**
    69     /**
    70      * Exercise 1.
    70      * Exercise 1.
    71      *
    71      *
    72      * Retrieve the response status code from a request to the given
    72      * Retrieve the response status code from a request to the given
    73      * URI. The returned response code will be a int.
    73      * URI. Return the response code, which is an integer.
    74      *
    74      *
    75      * Hint: use the discard BodyHandler since the response body is not
    75      * Hint: use the {@link BodyHandler#discard(Object)BodyHandler} since
    76      * interesting.
    76      * the response body is not interesting.
    77      *
    77      *
    78      * Hint: static imports reduce boilerplate when using BodyHandlers
    78      * Hint: static imports reduce boilerplate when using BodyHandlers
    79      * and BodyProcessors, e.g. import static
    79      * and BodyProcessors, e.g. import static
    80      * jdk.incubator.http.HttpResponse.BodyHandler.discard
    80      * jdk.incubator.http.HttpResponse.BodyHandler.discard
    81      */
    81      */
    88 
    88 
    89         return response.statusCode();
    89         return response.statusCode();
    90     }
    90     }
    91 
    91 
    92     /**
    92     /**
    93      * Exercise 1.
    93      * Exercise 2.
    94      *
    94      *
    95      * Retrieve the response body from a given URI. Return the response
    95      * Retrieve the response body from a given URI. Return the response
    96      * body as a String.
    96      * body as a String.
    97      *
    97      *
    98      * Hint: use the asString BodyHandler to convert the HTTP response
    98      * Hint: use the {@link BodyHandler#asString()} BodyHandler to convert
    99      * body to a String.
    99      * the HTTP response body to a String.
   100      *
   100      *
   101      * Hint: static imports reduce boilerplate when using BodyHandlers
   101      * Hint: static imports reduce boilerplate when using BodyHandlers
   102      * and BodyProcessors, e.g. import static
   102      * and BodyProcessors, e.g. import static
   103      * jdk.incubator.http.HttpResponse.BodyHandler.asString
   103      * jdk.incubator.http.HttpResponse.BodyHandler.asString
   104      */
   104      */
   111 
   111 
   112         return response.body();
   112         return response.body();
   113     }
   113     }
   114 
   114 
   115     /**
   115     /**
   116      * Exercise 2.
   116      * Exercise 3.
   117      *
   117      *
   118      * Retrieve the response body from a given URI, streaming teh body
   118      * Retrieve the response body from a given URI, streaming the body
   119      * out to a file. Return the file's Path.
   119      * out to a file. Return the file's Path.
   120      *
   120      *
   121      * Hint: use {@linkplain BodyHandler#asFile} to stream the HTTP
   121      * Hint: use {@linkplain BodyHandler#asFile} to stream the HTTP
   122      * response body to a file.
   122      * response body to a file.
       
   123      *
       
   124      * Hint: if a file already exists from a previous test run, either
       
   125      * remove it or use the {@link java.nio.file.StandardOpenOption#CREATE}
       
   126      * along with the {@link java.nio.file.StandardOpenOption#TRUNCATE_EXISTING}
       
   127      * to create or truncate as needed.
   123      */
   128      */
   124     public static Path retrieveResourceAsFile(URI uri)
   129     public static Path retrieveResourceAsFile(URI uri)
   125         throws IOException, InterruptedException
   130         throws IOException, InterruptedException
   126     {
   131     {
   127         HttpClient client = HttpClient.newBuilder().build();
   132         HttpClient client = HttpClient.newBuilder().build();
   129                 .uri(uri)
   134                 .uri(uri)
   130                 .version(HTTP_1_1)
   135                 .version(HTTP_1_1)
   131                 .GET()
   136                 .GET()
   132                 .build();
   137                 .build();
   133         HttpResponse<Path> response = client.send(request,
   138         HttpResponse<Path> response = client.send(request,
   134                 asFile(Paths.get("retrieveResourceAsFile.txt"), StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE));
   139                 asFile(Paths.get("retrieveResourceAsFile.txt"),
   135 
   140                        StandardOpenOption.CREATE,
   136         System.out.println("CHEGAR:   sc=" + response.statusCode());
   141                        StandardOpenOption.TRUNCATE_EXISTING,
   137         System.out.println("CHEGAR:   by=" + Files.readAllLines(response.body()).stream().collect(joining()));
   142                        StandardOpenOption.WRITE));
   138 
       
   139         return response.body();
   143         return response.body();
   140     }
   144     }
   141 
   145 
   142 
   146 
   143     /**
   147     /**
   144      * Asserts that the response code is 200 ( OK ).
   148      * A helper method, NOT an exercise.
       
   149      *
       
   150      * Asserts that the response code is 200 ( OK ). Throws IOException if
       
   151      * the response code is not 200.
   145      *
   152      *
   146      * Can be used in CompletableFuture pipelines when checking the
   153      * Can be used in CompletableFuture pipelines when checking the
   147      * response of an {@linkplain HttpClient#sendAsync} call. For
   154      * response of an {@linkplain HttpClient#sendAsync} call. For
   148      * example:
   155      * example:
   149      *    client.sendAsync(request, bodyHandler)
   156      *    client.sendAsync(request, bodyHandler)
   159         }
   166         }
   160         return response;
   167         return response;
   161     }
   168     }
   162 
   169 
   163     /**
   170     /**
   164      *  Exercise 3.
   171      * Exercise 4.
   165      *
   172      *
   166      * Retrieve the response body from a given URI, using the
   173      * Retrieve the response body from a given URI, using thea synchronous
   167      * asynchronous send API, sendAsync. Return a CompletableFuture that
   174      * send API, {@link HttpClient#sendAsync(HttpRequest, BodyHandler)}.
   168      * completes with the response body as a String.
   175      * Return a CompletableFuture that completes with the response body
       
   176      * as a String.
   169      *
   177      *
   170      * Hint: The {@linkplain CompletableFuture#thenApply(Function)}
   178      * Hint: The {@linkplain CompletableFuture#thenApply(Function)}
   171      * method can be used to map the HttpResponse to a String.
   179      * method can be used to map the HttpResponse to a String.
   172      */
   180      */
   173     public static CompletableFuture<String> retrieveResourceAsStringUsingAsyncAPI(URI uri) {
   181     public static CompletableFuture<String> retrieveResourceAsStringUsingAsyncAPI(URI uri) {
       
   182         // TODO: why version needed?
       
   183 
   174         return HttpClient.newHttpClient()
   184         return HttpClient.newHttpClient()
   175                 .sendAsync(HttpRequest.newBuilder(uri).version(HTTP_1_1).build(), asString())  // TODO: why version needed?
   185                 .sendAsync(HttpRequest.newBuilder(uri).version(HTTP_1_1).build(), asString())
   176                 .thenApply(Retrievals::require200StatusCode)
   186                 .thenApply(Retrievals::require200StatusCode)
   177                 .thenApply(HttpResponse::body);
   187                 .thenApply(HttpResponse::body);
   178     }
   188     }
   179 
   189 
   180 
   190 
   181     /**
   191     /**
       
   192      * A helper method, NOT an exercise.
       
   193      *
   182      * Wrapper around Jackson's ObjectMapper that provides an unchecked
   194      * Wrapper around Jackson's ObjectMapper that provides an unchecked
   183      * {@code readValue}, what can be used to help solve the next
   195      * {@code readValue}, what can be used to help solve the next
   184      * exercise, 4.
   196      * exercise, 5.
   185      */
   197      */
   186     public static class UncheckedObjectMapper extends ObjectMapper {
   198     public static class UncheckedObjectMapper extends ObjectMapper {
   187 
   199 
   188         /** Parses the given JSON string into a Map. */
   200         /** Parses the given JSON string into a Map. */
   189         Map<String,String> readValue(String content) {
   201         Map<String,String> readValue(String content) {
   194             }
   206             }
   195         }
   207         }
   196     }
   208     }
   197 
   209 
   198     /**
   210     /**
   199      * Exercise 4.
   211      * Exercise 5.
   200      *
   212      *
   201      * Retrieve the response body from a given URI. The response body
   213      * Retrieve the response body from a given URI. The response body
   202      * will be in the JSON format. The Jackson based UncheckedObjectMapper
   214      * will be in the JSON format. The Jackson based UncheckedObjectMapper
   203      * ( above ) can be used to parse the String response body into a
   215      * ( above ) can be used to parse the String response body into a
   204      * Map.
   216      * Map. Return the response body as a Map.
   205      *
   217      *
   206      * Hint: The asynchronous send API will allow construction of a
   218      * Hint: The asynchronous send API will allow construction of a
   207      * pipeline of CompletableFutures.
   219      * pipeline of CompletableFutures.
   208      *
   220      *
   209      * Hint: The {@linkplain CompletableFuture#thenApply(Function)}
   221      * Hint: The {@linkplain CompletableFuture#thenApply(Function)}
   210      * method can be used to map the HttpResponse to a String, and then
   222      * method can be used to map the HttpResponse to a String, and then
   211      * again from a Sting to a Map ( via the object mapper ).
   223      * again from a String ( of JSON ) to a Map ( via the object mapper ).
   212      */
   224      */
   213     public CompletableFuture<Map<String,String>> JSONBodyAsMap(URI uri) {
   225     public CompletableFuture<Map<String,String>> JSONBodyAsMap(URI uri) {
   214         UncheckedObjectMapper objectMapper = new UncheckedObjectMapper();
   226         UncheckedObjectMapper objectMapper = new UncheckedObjectMapper();
   215         return HttpClient.newHttpClient()
   227         return HttpClient.newHttpClient()
   216                 .sendAsync(HttpRequest.newBuilder(uri).version(HTTP_1_1).build(), asString())
   228                 .sendAsync(HttpRequest.newBuilder(uri).version(HTTP_1_1).build(), asString())
   219     }
   231     }
   220 
   232 
   221 
   233 
   222 
   234 
   223     /**
   235     /**
       
   236      * Exercise 6.
       
   237      *
   224      * Post the given {@code data}, and receive the same data in
   238      * Post the given {@code data}, and receive the same data in
   225      * response. Return the response body data as a String.
   239      * response. Return the response body data as a String.
   226      */
   240      */
   227     public static String postData(URI uri, String data)
   241     public static String postData(URI uri, String data)
   228         throws IOException, InterruptedException
   242         throws IOException, InterruptedException
   236         HttpResponse<String> response = client.send(request, asString());
   250         HttpResponse<String> response = client.send(request, asString());
   237 
   251 
   238         return response.body();
   252         return response.body();
   239     }
   253     }
   240 
   254 
   241 
       
   242      // JSON processor
       
   243 }
   255 }