DEV Community

A N M Bazlur Rahman
A N M Bazlur Rahman

Posted on • Originally published at bazlur.com on

1

Let's use the new HTTP Client that java 11 brought

100DaysOfProgramming_Day011

Java 11 brought an inbuilt HTTP client. As a result, we don’t need a third-party library anymore to invoke an HTTP request.

Let’s call a chuck Norris api to fetch a random joke.

package com.bazlur;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;

public class Day011 {
  public static final String CHUCK_NORRIS_RANDOM_JOKES_API = "https://api.chucknorris.io/jokes/random";

  public static void main(String[] args) throws URISyntaxException, IOException, InterruptedException {
    var client = HttpClient.newBuilder()
            .version(HttpClient.Version.HTTP_2)
            .connectTimeout(Duration.ofSeconds(20))
            .build();

    var request = HttpRequest.newBuilder()
            .uri(new URI(CHUCK_NORRIS_RANDOM_JOKES_API))
            .header("Accept", "application/json")
            .GET()
            .build();

    var response = client.send(request, HttpResponse.BodyHandlers.ofString());
    var body = response.body();
    System.out.println("body = " + body);
  }
}

Enter fullscreen mode Exit fullscreen mode

We can even fetch it asynchronously; we just have to change the method send() to sendAsync()

 var completableFuture = client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
            .thenApply(HttpResponse::body);

Enter fullscreen mode Exit fullscreen mode

It will return a CompletableFuture.

We can certainly go further to tie any serializer to serialize the JSON body into an object. However, Jackson is my favourite JSON library that I use in all my projects.

Let’s add its dependency:

implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.12.3'

Enter fullscreen mode Exit fullscreen mode

I will use the sendAsync() method so that I can use the lambda chain. The readValue() of ObjectMapper’s method throws a checked exception that I don’t want to put into my lambda expression. It makes code ugly. Thus I will extend ObjectMapper’s behaviour a little to accommodate my need.

  static class UncheckedObjectMapper extends ObjectMapper {
    Joke readValue(String content) {
      try {
        return this.readValue(content, new TypeReference<>() {
        });
      } catch (JsonProcessingException e) {
        throw new CompletionException(e);
      }
    }
  }

Enter fullscreen mode Exit fullscreen mode

I wouldn’t recommend this sort of the change in your production code unless you are willing to maintain it. So careful!

We usually get this JSON response from the api-

{
  "categories": [],
  "created_at": "2020-01-05 13:42:28.420821",
  "icon_url": "https://assets.chucknorris.host/img/avatar/chuck-norris.png",
  "id": "Kqck_igkQNCw6Y0ADR2iyA",
  "updated_at": "2020-01-05 13:42:28.420821",
  "url": "https://api.chucknorris.io/jokes/Kqck_igkQNCw6Y0ADR2iyA",
  "value": "The Terminator wears a Chuck Norris tee shirt. ."
}

Enter fullscreen mode Exit fullscreen mode

Let’s create a POJO for this. I will use record for this.


  @JsonIgnoreProperties(ignoreUnknown = true)
  record Joke(
          @JsonProperty("created_at")
          String createdAt,
          @JsonProperty("icon_url")
          String iconUrl,
          @JsonProperty("id")
          String id,
          @JsonProperty("updated_at")
          String updatedAt,
          @JsonProperty("url")
          String url,
          @JsonProperty("value")
          String value
  ) { }

Enter fullscreen mode Exit fullscreen mode

Let’s put everything together.

package com.bazlur;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutionException;

public class Day011_1 {

  public static final String CHUCKNORRIS_RANDOM_JOKES_API = "https://api.chucknorris.io/jokes/random";

  public static void main(String[] args) throws URISyntaxException, IOException, InterruptedException, ExecutionException {

    var objectMapper = new UncheckedObjectMapper();
    objectMapper.enable(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT);

    var httpClient = HttpClient.newHttpClient();
    var request = HttpRequest.newBuilder()
            .uri(new URI(CHUCKNORRIS_RANDOM_JOKES_API))
            .header("Accept", "application/json")
            .GET()
            .build();

    var joke = httpClient.sendAsync(request, BodyHandlers.ofString())
            .thenApply(HttpResponse::body)
            .thenApply(objectMapper::readValue)
            .get();
    System.out.println("joke = " + joke.value());
  }

  @JsonIgnoreProperties(ignoreUnknown = true)
  record Joke(
          @JsonProperty("created_at")
          String createdAt,
          @JsonProperty("icon_url")
          String iconUrl,
          @JsonProperty("id")
          String id,
          @JsonProperty("updated_at")
          String updatedAt,
          @JsonProperty("url")
          String url,
          @JsonProperty("value")
          String value
  ) { }

  static class UncheckedObjectMapper extends ObjectMapper {
    Joke readValue(String content) {
      try {
        return this.readValue(content, new TypeReference<>() {
        });
      } catch (JsonProcessingException e) {
        throw new CompletionException(e);
      }
    }
  }
}

Enter fullscreen mode Exit fullscreen mode

for copy/paste pleasure: https://github.com/rokon12/100DaysOfJava/blob/main/src/main/java/com/bazlur/Day011.java

Heroku

Simplify your DevOps and maximize your time.

Since 2007, Heroku has been the go-to platform for developers as it monitors uptime, performance, and infrastructure concerns, allowing you to focus on writing code.

Learn More

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay