Building Simple Http Client in Java 

  • Post last modified:December 15, 2022
  • Reading time:5 mins read

Introduction

  • Connecting to API is very natural steps to build complex systems. Java has not provided good utility for connecting to API until Java 11. Before Java 11 Java had HttpURLConnection which is not feature rich & verbose.
  • In this article we will discuss HttpURLConnection ( Java 8 and Before ) and HttpClient( Java 11 and beyond) to connect API endpoints.

Using HttpClient 

  • HttpClient was Introduced in Java 11, which is feature rich in building HttpClient to consume Rest API’s.

Step 1: Building HttpRequest

  • Very first step is to build HttpRequest object. HttpRequest object is builder pattern.
  • Our target endpoint is to get todos from https://jsonplaceholder.typicode.com/guide/. It’s good start to test rest endpoint.
    private static final String TARGET_URL = "https://jsonplaceholder.typicode.com/todos/";
    public static void main(String[] args) throws URISyntaxException, IOException, InterruptedException {

        URI targetURI = new URI(TARGET_URL);
        HttpRequest httpRequest = HttpRequest.newBuilder()
                .uri(targetURI)
                .GET()
                .build();
   }

Step 2: HttpClient Execution

  • As a next step, we create httpClient object and then execute send operation.
  • We also needs to pass BodyHandlers , in this case we are expecting String.
HttpClient httpClient = HttpClient.newHttpClient();
HttpResponse<String> response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());

Step 3: Mapping Json To Java Object

  • Java doesn’t provide any utility to parse JSON string to Java Object. We either have to build our own serializer or use third party library.
  • In our case we are using jackson-databind to map Json to Java Object.
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.4</version>
</dependency>
  • Jackson provides ObjectMapper class to map Json to Custom Object type.
  • In below code we are reading response and mapping todo array because our endpoint return list of todos.
// Reading response
ObjectMapper objectMapper = new ObjectMapper();
Todo[] todos = objectMapper.readValue(response.body(), Todo[].class);

System.out.println("total tasks : "+todos.length);
        
long count = Arrays.stream(todos).filter(a -> a.isCompleted()).count();
System.out.println("Total completed tasks : " + count);
        
List<Integer> completedTaskIds = Arrays.stream(todos).filter(a -> a.isCompleted()).map(a -> a.getId()).collect(Collectors.toList());
completedTaskIds.forEach(a-> System.out.println(a));
public class Todo {

    private int id;
    private int userId;
    private String title;
    private boolean isCompleted;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public boolean isCompleted() {
        return isCompleted;
    }

    public void setCompleted(boolean completed) {
        isCompleted = completed;
    }
}
  • We can use POST/PUT/DELETE operation. One of the example of using POST operation is below.
// url connection
URL url1 = new URL("https://jsonplaceholder.typicode.com/posts");
HttpURLConnection postConnect = (HttpURLConnection) url1.openConnection();
postConnect.setRequestMethod("POST");
postConnect.setDoOutput(true);


// writing post body content
String postBody = " title: 'foo',\n" +
                "    body: 'bar',\n" +
                "    userId: 1,";
byte[] input = postBody.getBytes(StandardCharsets.UTF_8);
postConnect.getOutputStream().write(input, 0, input.length);

// response reader
StringBuilder response = new StringBuilder();
BufferedReader reader1 = new BufferedReader(new InputStreamReader(postConnect.getInputStream()));
reader1.lines().forEach(a->response.append(a));
System.out.println("response : "+response);

Using HttpURLConnection

  • HttpClient provides most robust way to build client to consume rest api’s. But It’s not available until Java 11. Before that HttpURLConnection was the only way to build the rest client , of course we can use third party libraries such as apache commons or google-http-client but we are talking about java inbuilt features.
  • Using HttpURLConnection is legacy and not so nice way to build the http client. It’s very verbose and require lots of configuration and type conversion.

Step 1: URL Connection

  • We first build url connection object. and set the request method, in this case GET.
URL url = new URL("https://jsonplaceholder.typicode.com/todos/");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET")

Step 2: BufferedReader Object 

  • In order to read from connection stream we need to open InputStreamReader and parse it to BufferedReader.
  • The we read each line and append it to string. 
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder stringBuilder = new StringBuilder();

reader.lines().forEach(a->stringBuilder.append(a));
System.out.println(stringBuilder);

Step 3: Mapping to Java Object

  • Response type is json string here which can be mapped to Custom Java object, here todo array type.
  • Once we have response in Java Object we can read or perform any operation on it.
ObjectMapper objectMapper = new ObjectMapper();
Todo[] todos = objectMapper.readValue(stringBuilder.toString(), Todo[].class);
System.out.println("total tasks : "+todos.length);
  • We can also perform POST/DELETE/PUT method , for example here we are using POST method.
// url connection
URL url1 = new URL("https://jsonplaceholder.typicode.com/posts");
HttpURLConnection postConnect = (HttpURLConnection) url1.openConnection();
postConnect.setRequestMethod("POST");
postConnect.setDoOutput(true);


// writing post body content
String postBody = " title: 'foo',\n" +
                "    body: 'bar',\n" +
                "    userId: 1,";
byte[] input = postBody.getBytes(StandardCharsets.UTF_8);
postConnect.getOutputStream().write(input, 0, input.length);

// response reader
StringBuilder response = new StringBuilder();
BufferedReader reader1 = new BufferedReader(new InputStreamReader(postConnect.getInputStream()));
reader1.lines().forEach(a->response.append(a

Conclusion

  • In this article we explored two very popular utilities to build http connection in Java. HttpClient should be used for Java11 and beyond projects while for Java 8 and before projects, HttpURLConnection should be avoided and we should use third party libraries such as Apache Commons , Google Http Client.
  • Java doesn’t provide out of the box Json to Java mapper hence we need to use third party libraries such as Jackson ObjectMapper or we have to build our own parser.

Bonus Tip

Leave a Reply