Before Java 11, consuming a Rest API without using a third party library was definitetly a nightmare. The option provided by Java out of the box was the very old fashion and extremely verbose HttpURLConnection. Then third party libraries were the alternative, but with Java 11 we have a new HttpClient API that simplifies the task using the out of the box Java features.
Http URL Connection
As we mentioned, the problem with it is that it works at a low level, then we need to indicate the http method, headers, and interact with Output and Input Streams in order to send and receive a message. Then, we need to parse the message manually.
//Message to send String jsonInputString = "{'name': 'Adam', 'job': 'Programmer'}"; //Creating the connection HttpURLConnection con = (HttpURLConnection)url.openConnection(); con.setRequestMethod("POST"); con.setRequestProperty("Content-Type", "application/json; utf-8"); con.setRequestProperty("Accept", "application/json"); con.setDoOutput(true); //Sending the message try(OutputStream os = con.getOutputStream()) { byte[] input = jsonInputString.getBytes("utf-8"); os.write(input, 0, input.length); } //Getting the response try(BufferedReader br = new BufferedReader( new InputStreamReader(con.getInputStream(), "utf-8"))) { StringBuilder response = new StringBuilder(); String responseLine = null; while ((responseLine = br.readLine()) != null) { response.append(responseLine.trim()); } System.out.println(response.toString()); } int responseCode = con.getResponseCode();
All those lines are only to send a receive a message, and we haven´t parse it to a JSON object or other object to use the response easily.
Using Third party libraries
Well, we have seen how tedious is using the HttpURLConnection class to consume a Rest API. That´s why Java Developers rarely use it, and a third party library is prefered. Some examples are:
- Apache Http Connection: This is still a low level http client, but is more flexible and simpler than HttpURLConnection. If we want to know more about it, see this examples.
- Jersey Client: Jersey is the reference implementation for JAX-RS (Restful API) in Java. It provides its client library to consume restful service easily. One of its advantages is that provides support to JSON and XML binding , then it takes care of transforming the message to Java Objects for us. See more…
- Rest Easy Client: Rest Easy is also an implementation for JAX-RS, and its client module provides also JSON and XML binding as Jersey. But it has a very nice feature where it generates the client from an interface with JaxRS annotations. I recommend you to see this page.
- OkHttp: Extensively used in the mobile (android) world. It provides a lot of nice features, support to secured connections, http2, and it´s very simple to use. View more…
HttpClient Java 11+
Actually the new HttpClient API is present from Java9, but as part of the incubator. In other words, it was available, but not officialy released, and changes could happend in further versions.
The goal behind this new HttpClient API is to provide a standardized way consume REST API, using modern patterns and the best practices applied in some of the previous third party options. It has support to secured connections, HTTP2, websockets, and asynchronous requests out of the box. Let´s see and example:
//Message to send String jsonInputString = "{'name': 'Adam', 'job': 'Programmer'}"; HttpClient httpClient = HttpClient.newBuilder().build(); HttpRequest request = HttpRequest.newBuilder() .POST(BodyProcessor.fromString(jsonInputString)) .uri(URI.create("https://mydomain.com/api/books")) .build(); HttpResponse<String> response = httpClient .send(request, BodyHandlers.ofString());
In comparison to the old HttpURLConnection, this code looks simpler and clearer. We can see how there are 3 basic concepts in this API:
- HttpClient: In charge of creating the connection and configuration. Proxies, Authenticators, executors pools, cookie manager, etc.
- HttpRequest: Is the request to an URI. We can indicate here, timeout, headers, in the request is asynchronous or not.
- HttpResponse: Object to handle the response of the request. From here we can see the status code, body response, headers, and more.
In order to simplify the way we send or receive objects from this code, BodyPublishers and BodyHandlers have been introduced.
Body Publishers and Body Handlers
BodyPublisher is in charge of sending the content in the request. The API provides processors for String, InputStreams, Files, and ByteArray. If for some reason we have a POST/PUT/DELETE method that doesn’t require a body, we can use HttpRequest.noBody
.
In the other hand, BodyHandlers are in charge of the response. The API also provides some processors for String, Streams and others.
We can create ours owns BodyHandlers and BodyPublisher, for example to Serialize or Deserialize an object in a JSON directly, by implementing the classes HttpResponse.BodyHandler
and HttpRequest.BodyPublisher
.
Asynchronous Request
This feature is very useful, there are some cases where we don’t have our request to be blocking the main thread. For example, in event driven applications or mobile application. The new HttpClient provides two possibilities for sending a request to a server:
- send(…) – synchronously (blocks until the response comes)
- sendAsync(…) – asynchronously (doesn’t wait for the response, non-blocking)
As we can see, now, we can use sendAsync(...) method – which returns CompletableFeature<HttpResponse> – to process a request asynchronously.
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("http://openjdk.java.net/")) .build(); client.sendAsync(request, BodyHandlers.ofString()) .thenApply(response -> {/* do something here */ return response;}) .thenAccept(System.out::println);
We can use the methods thenApply and thenAccept of the CompletableFuture returned by the sendAsync method. If you are wondering the difference between those methods, thenApply is a Supplier which expects to return the response, and thenAccept is a Consumer which doesn’t return.
In addition, we can use the method whenComplete, to capture any result Object or Exception.
Conclusion
Well, I think there is no much to say about the new HttpClient, if you are using Java 11+, don’t hesitate to give it a chance. Using third party libraries is still valid for newer java version but in my opinion, the API provides the features for most of the use cases.
References
- https://mkyong.com/java/apache-httpclient-examples/
- https://www.baeldung.com/jersey-jax-rs-client
- https://www.baeldung.com/resteasy-client-tutorial
- https://www.baeldung.com/java-9-http-client