How to make API calls in Java

Nowadays, RESTful APIs are used everywhere for fetching data from an external resource. Frankly speaking, the approaches of fetching remote data will not work for all RESTful resources. In other words, the decision to use any approaches is dependent on how the external resources are built. In this writing, we want to summarise common ways for calling APIs in Java and draw the limitations we should take into account. In this post, we’ll cover:

Core Java:

  • HttpUrlConnection
  • HttpClient

Third-party Java HTTP client libraries:

  • Spring RestTemplate
  • Spring WebClient
  • Spring OpenFeign
  • ApacheHttpClient
  • OkHttp
  • Retrofit

All examples are published in the repository https://github.com/ITersDesktop/java-test-everything/tree/callapis. To keep the demonstration for approaches consistent, we use the endpoint https://www.ebi.ac.uk/biostudies/api/v1/arrayexpress/search?page=10&pageSize=20 to fetch 20 records from BioStudies database.

In the snippets, we call Helpers.extracted() to loop over the results to print out some properties.

Using core Java libraries

We don’t need to declare any external libraries as well as dependencies to use the following libraries. To compile and run the example codes, you can consult our other post about compiling and running Java programmes.

Old School HttpUrlConnection from Java 1.1

The first implementation is with HttpURLConnection. This implementation is the oldest and has been present since JDK 1.1. Below is an example of a method that displays a list of records of the BioStudies database using the GET method:

public static String getUrlContents(String theUrl) {
        StringBuilder content = new StringBuilder();
        // Use try and catch to avoid the exceptions
        try {
            URL url = new URL(theUrl); // creating a url object
            HttpUrlConnection conn = url.openConnection(); // creating an HttpUrlConnection object

            // wrapping the HttpUrlConnection in a bufferedreader
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
            String line;
            // reading from the urlconnection using the bufferedreader
            while ((line = bufferedReader.readLine()) != null) {
                content.append(line + "\n");
            }
            bufferedReader.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return content.toString();
    }

Here, an InputStream is obtained and looped over to convert the data to a string. There are no methods to obtain the JSON directly as a string.

The java.net.http.* from Java 11

JDK 11, released in September 2018, brought a new HTTP client that is simpler and easier to use. Let’s take a look at how to use the library.
package com.itersdesktop.javatechs.callapis;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

import static com.itersdesktop.javatechs.callapis.Helpers.extracted;

public class HttpClientDemo {

    public static void main(String[] args) {
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(Helpers.API_URL))
                .method("GET", HttpRequest.BodyPublishers.noBody())
                .build();
        doWithStringHandler(request);
        doWithInputStreamHandler(request);
    }

    private static void doWithStringHandler(final HttpRequest request) {
        HttpResponse<String> response = null;

        try {
            response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            assert response != null;
            extracted(response.body());
        }
    }

    private static void doWithInputStreamHandler(final HttpRequest request) {
        HttpResponse<InputStream> response = null;

        try {
            response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofInputStream());
            int statusCode = response.statusCode();
            System.out.println("HTTP status: " + statusCode);
            System.out.println("Headers:");
            response.headers().map().forEach((header, value) ->
                System.out.println(header + " = " + String.join(", ", value)));
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            assert response != null;
            System.out.println(response.body());
        }
    }
}

You can see that we have created a builder, giving it the API endpoint by passing it as a parameter to the uri method. Now we need to create a simple HttpResponse variable to save the response we will receive from the API. Finally, we need to send the API call.

Using third-party HTTP client libraries

If you use build tools such as Maven or Gradle, please check the dependencies for these libraries.

We need to add the dependencies to the  pom.xml file to use WebClient and RestTemplate.

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webflux -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webflux</artifactId>
    <version>7.0.0-M6</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.17.0</version>
</dependency>

Spring RestTemplate

public static void searchWithRestTemplate() {
    System.out.println("\nListing all search hits using Spring RestTemplate:");
    RestTemplate restTemplate = new RestTemplate();
    ResponseEntity<String> response = restTemplate.getForEntity(API_URL, String.class);
    extracted(response.getBody());
}

The extracted and API_URL are defined in Helpers.java.

Spring WebClient

public static void searchWithWebClient() throws JsonProcessingException {
    System.out.println("\nListing all search hits using Spring WebFlux:");

    WebClient webClient = WebClient.create(API_URL);
    String response = webClient.get()
        .retrieve()
        .bodyToMono(String.class)
        .block();

    extracted(response);
}

The extracted and API_URL are defined in Helpers.java.

Spring OpenFeign

I found this tutorial very good for learning OpenFeign.

Apache HttpClient

static String executePostRequest(final String serviceURI, final String requestBody) {
    CloseableHttpClient httpClient
    String hostName = System.getenv("HTTP_PROXY_HOST")
    int hostPort = System.getenv("HTTP_PROXY_PORT") as int
    HttpHost host = new HttpHost(hostName, hostPort)
    if (host) {
        httpClient = HttpClientBuilder.create().setProxy(host).build()
    } else {
        httpClient = HttpClientBuilder.create().build()
    }
    String result = null
    try {
        HttpPost request = new HttpPost(serviceURI)
        StringEntity params = new StringEntity(requestBody, "UTF-8")
        request.addHeader("content-type", "application/json")
        request.setEntity(params)

        CloseableHttpResponse response = httpClient.execute(request)
        try {
            HttpEntity entity = response.getEntity()
            if (entity != null) {
                result = EntityUtils.toString(entity)
            }
        } finally {
            response.close()
        }
    } catch (Exception ignored) {
        // handle exception here
        ignored.printStackTrace()
    } finally {
        httpClient.close()
    }

    return result
}

The snippet above is written in Groovy; however, the implementation logic is the same. How to use the function?

import net.biomodels.jummp.utils.WebServiceFetcher as WSF

private String doGenerateOmexMetadataRDF(final String modelId, final Integer revisionId) {
    final String DEFAULT_FS_SVR = "http://localhost:8090/biomodels/services/file-format/api/v1.0"
    final String FS_SVR_URL = System.getenv().getOrDefault("FS_SVR_URL", DEFAULT_FS_SVR)
    String identifier = modelId + (revisionId != null ? ".${revisionId}" : "")
    String rdfContent = "Cannot generate metadata.rdf file for this model revision $identifier"
    try {
        JSONObject object = new JSONObject()
        object.put("revisionId", identifier)
        JSONArray array = new JSONArray()
        array.put(object)
        String uri = "${FS_SVR_URL}/create-omex-metadata-rdf/${identifier}"
        rdfContent = WSF.executePostRequest(uri, array.toString())
    } catch (Exception ignored) {
        // handle exception here
        ignored.printStackTrace()
    } finally {
    }
    return rdfContent
}

Conclusion

This article is not intended to be conclusive, but rather a quick reference guide to the libraries I use in my projects. There are still many more resources to explore within these libraries. I also didn’t mention other interesting libraries, such as Micronaut’s HTTP Client or Apache Commons, but I’ll leave some links for those interested.

As mentioned above, all these examples, including their configurations and additional classes, are available on the GitHub repository associated with this blog.

References

[1] 5 ways to make HTTP requests in Java, https://www.twilio.com/en-us/blog/developers/tutorials/building-blocks/5-ways-to-make-http-requests-in-java, accessed on July 10th, 2025

[2] How to make API calls in Java?, https://rapidapi.com/guides/make-api-call-java, accessed on July 10th, 2025

[3] Do a Simple HTTP Request in Java, https://www.baeldung.com/java-http-request, accessed on July 10th, 2025

[4] 5 ways to call an API in Java, https://medium.com/@archimedes.fagundes/5-ways-to-call-an-api-in-java-b3de65fb2022, accessed on July 10th, 2025

[5] Exploring the New HTTP Client in Java, https://www.baeldung.com/java-9-http-client, accessed on July 10th, 2025

Nguyen Vu Ngoc Tung

I love making new professional acquaintances. Don't hesitate to contact me via nguyenvungoctung@gmail.com if you want to talk about information technology, education, and research on complex networks analysis (i.e., metabolic networks analysis), data analysis, and applications of graph theory. Specialties: researching and proposing innovative business approaches to organizations, evaluating and consulting about usability engineering, training and employee development, web technologies, software architecture.

https://www.itersdesktop.com/author/nvntung/

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.