Introduction
In this tutorial, we connect to three different RapidAPI application programming interfaces (APIs) using Spring Boot. First, we explore using HTTP GET to obtain COVID-19 totals from the COVID-19 data API on RapidAPI. Second, we explore using HTTP POST to upload an image and generate a meme using the Meme Generator API on RapidAPI. And Third, we use HTTP POST to send a JSON request to the Microsoft Computer Vision API to generate a thumbnail from an image provided using a URL. The tutorial covers the following topics/tasks.
- We use Spring Initializr to generate a Spring Boot Rest application,
- create a Spring RESTful client that uses Spring’s RestTemplate to call a REST endpoint using a GET request,
- use an online tool, jsonschema2pojo, to create Java objects for serializing/deserializing JSON data in our Spring Boot REST client,
- add a method to our Spring Boot REST client that passes a query parameter to a GET REST endpoint,
- create a Spring Boot RestTemplate client that sends binary data to a REST endpoint using a POST request,
- and add a method to the Spring Boot RestTemplate REST client that requests binary data from an endpoint using an HTTP POST request.
Let’s begin by briefly discussing the REST APIs curated on RapidAPI that we use here.
Tutorial APIs
As this is a tutorial on RapidAPI’s blog, it only makes sense that it uses REST APIs provided by RapidAPI. The three APIs we use are the COVID-19 data API, the Meme Generator API, and the Microsoft Computer Vision API. All three are APIs available on RapidAPI.
RapidAPI
RapidAPI is an online API marketplace with over 10,000 unique APIs. It offers an easy way to find and use RESTful APIs. RapidAPI offers sample code to access the APIs it curates and provides a secure, unified billing for those APIs. If you have ever had to hunt the Internet for a RESTful API that meets your needs, then you will agree that RestAPI provides a much-needed service by aggregating so many APIs in one location.
Getting started with RapidAPI is easy but beyond the scope of this tutorial. But, here’s a video to help you get started. Or if you prefer to read, here’s a link to the getting started instructions. There are also many other blog entries on this site to help you get started using RapidAPI.
You must have a RapidAPI account if you wish to follow along and duplicate the steps in this tutorial. Accessing the tutorial APIs requires a valid credit card; however, unless you exceed a threshold, you are not charged. For example, the COVID-19 data API pricing as of April 2020 is 5000 requests a month free and only five dollars a month for Pro and twenty a month for Ultra, thus making it free for development and nominally priced for production use.

APIs Used In Tutorial
We use three APIs available on RapidAPI in this tutorial: the COVID-19 data API, the Meme Generator API, and the Microsoft Computer Vision API. Let’s briefly explore each in turn.
COVID-19 Data API
The COVID-19 data API provides Coronavirus statistics updated every 15 minutes. In this tutorial, we use this API to demonstrate how to make GET requests and to illustrate converting a JSON object into a simple Java data object, or as developers more frequently referred to them, plain old Java objects (POJOs). We use two COVID-19 data API endpoints, getTotals and GetCountryData. The getTotals endpoint returns worldwide statistics while the getCountryData returns totals limited to an individual country. Both endpoints are HTTP GET requests.

Meme Generator API
The Meme Generator API is a simple API for adding short text to an image. This tutorial uses the API to illustrate posting binary data to a REST endpoint using the HTTP POST method. It also demonstrates using query parameters to pass data to a REST endpoint. We then make a POST request to the API and fetch binary image data.

Microsoft Computer Vision API
The final API we use in this tutorial is the Microsoft Computer Vision API. The Microsoft Computer Vision API is an Azure cloud service that provides image processing algorithms to developers. RapidAPI curates several endpoints to the API, as shown in the following image.

Although there are several more complex endpoints, we limit ourselves to the simple Generate Thumbnail (URL) endpoint. We use this endpoint to illustrate sending POST data (non-binary) to a RESTful web service.
REST and JSON
Before starting, let’s briefly discuss the REST and JSON prerequisites for understanding this tutorial. This tutorial is not an introduction to REST and JSON and assumes you are familiar with both technologies. For more information on both these topics, refer to the article Top 10 Best Java REST and Microservice Frameworks (2020) also published on this website. Also, there are many tutorials and references available for both technologies on the Internet; a cursory Google search will provide you with thousands of sources.
In brief, REST is a technology for intercommunication between different applications via endpoints accessible via HTTP requests over the Internet. JSON is the data format mostly used by these services. As mentioned, you should understand both technologies before completing this tutorial. For more information, a good starting point is the Wikipedia entry on REST and the entry on JSON.
Spring Boot
Spring Boot is an open-source framework that uses the Spring Framework to create microservices. It makes creating production quality stand-alone applications easy by handling most configuration tasks for the developer. It has an embedded Tomcat server and removes the need to generate WAR files. It also combines many common third-party libraries into a convenient “starter” library, thus freeing developers from error-prone POM files with numerous dependencies. And it provides many other features inherent to a production-ready application system. As described on the Spring Boot website, the project’s purpose is to offer a production-grade environment for developing applications that “just run.”
Spring Boot is built using the Spring Framework. If you are unfamiliar with Spring, then as with REST and JSON, you should consult some references before continuing this tutorial. There is ample online and printed documentation available. The obvious place to start is the Spring website at spring.io. The site has numerous tutorials and a quick start guide to help you get started. Spring Boot also has multiple tutorials and a quick-start guide at the Spring Boot website. However, you have no trouble completing this tutorial even with minimal Spring experience. So let’s begin by creating our project using a tool called the Spring Initializr.
Spring seemingly has a library for every task imaginable, from Web Services to LDAP to State machines, but in this tutorial, we limit ourselves to Spring REST. More specifically, Spring Boot using the Spring RestTemplate class to make HTTP GET and HTTP POST requests.
Spring Initializr
Spring Initializr is a tool that quickly generates a Spring Boot application with the necessary dependencies. You can also create and examine the project to be produced online before downloading it. When satisfied after reviewing the project, you can download the project as a zip file. Spring Initializr generates the project structure, dependencies, and the Maven or Gradle build script for you, thus helping you focus on writing your business logic. Let’s start by generating our skeleton project using Spring Initializr.
Creating the Project Scaffolding
- Navigate to start.spring.io, and you see the following screen for Spring Initializr.

- Check Maven Project for the Project and Java for the Language.
- Check 2.2.6 for Spring Boot.
- Name the Group com.rapidapi.example.tutorial and restTutorial for Artifact.
- Assign restTutorial as the Name and check Jar for Packaging and 8 for Java.

- Click ADD DEPENDENCIES and select Spring Web as a dependency.

- After adding the dependency, ensure the settings match the following screenshot.

- Click the EXPLORE button at the page bottom after ensuring the project configuration is correct.
You can explore the project before downloading to ensure you selected the correct settings. The zip is named restTutorial.zip, and the left panel lists the application’s structure. You can view the content of different items in the right panel by clicking the item in the left panel.
- Click pom.xml, and the POM’s content appears in the right panel.
The Initializr created a POM file with the settings entered above. Note the groupId, artifactId, and project name (A). Also, note the Java version as 1.8 (B) and the spring web dependency packaged in the spring-boot-starter-web jar (C).

- Click RestTutorialApplication.java and note the class’s structure.
The @SpringBootApplication annotation marks RestTutorialApplication as the application class. The Spring Boot SpringApplication class bootstraps and launches the RestTutorialApplication from its Java main method. It automatically creates the ApplicationContext from the application’s classpath, scans any configuration classes to configure the application, and then launches the app.

- Click RestTutorialApplicationTests.java and note the generated RestTutorialApplicationTests class.
Spring Initializr created the JUnit testing class for us with the relevant annotations needed to run the unit tests. We will use this unit testing class to exercise the methods we create in our application.

- Click the DOWNLOAD button after reviewing the project online and download the restTutorial.zip file.
- Move the zip file to the desired location and unzip the file.
Building The Project
- Open a terminal and navigate to the top-level project folder and use Maven to build the project.
mvn clean compile package
- After building, navigate to the newly created target folder and notice Maven created the restTutorial-0.0.1-SNAPSHOT.jar file. The generated file is an executable jar file that will call the main method if double-clicked or run from the command-line.
Running the Project
- Start the application by entering the following command.
java -jar .restTutorial-0.0.1-SNAPSHOT.jar
The application should start in the console. Of course, the application does not do anything yet, as we have not added the business logic to the application. Notice that it starts an instance of an embedded Tomcat Web Server, and then runs the application within that Tomcat instance.
. ____ _ __ _ _ / / ___'_ __ _ _(_)_ __ __ _ ( ( )___ | '_ | '_| | '_ / _` | / ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |___, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.2.6.RELEASE) 2020-04-09 19:16:53.760 INFO 18992 --- [ main] c.r.e.t.r.RestTutorialApplication : Starting RestTutorialApplication v0.0.1-SNAPSHOT on ICF2107642 with PID 18992 (C:Users42288Desktoprest_spring_articlerestTutorialtargetrestTutorial-0.0.1-SNAPSHOT.jar started by 42288 in C:Users42288Desktoprest_spring_articlerestTutorialtarget) 2020-04-09 19:16:53.764 INFO 18992 --- [ main] c.r.e.t.r.RestTutorialApplication : No active profile set, falling back to default profiles: default 2020-04-09 19:16:55.698 INFO 18992 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http) 2020-04-09 19:16:55.708 INFO 18992 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2020-04-09 19:16:55.709 INFO 18992 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.33] 2020-04-09 19:16:55.775 INFO 18992 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2020-04-09 19:16:55.775 INFO 18992 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1957 ms 2020-04-09 19:16:55.936 INFO 18992 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor' 2020-04-09 19:16:56.090 INFO 18992 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path '' 2020-04-09 19:16:56.093 INFO 18992 --- [ main] c.r.e.t.r.RestTutorialApplication : Started RestTutorialApplication in 2.723 seconds (JVM running for 3.121)
Now that we have the project’s structure created let’s add the REST client logic to the generated application.
GET Totals COVID-19
The first REST endpoint we write client code for is the GetTotals REST endpoint. Calling this REST endpoint is as easy as navigating to the URL, as there are no parameters passed to the endpoint. We simply construct an HTTP GET request. But I usually follow a set number of steps when creating client code for a REST endpoint. The first, and most important step, is always to get the REST endpoint working in a tool such as Postman or CURL. Although this tutorial does not discuss Postman in-depth, it does illustrate using this powerful tool. For more information on Postman, refer to the Postman Learning Center’s Getting Started documentation.
These are the steps we take in this tutorial when writing our client code.
- Create the Java POJO that corresponds with the JSON payload,
- review the endpoint in Postman,
- add the needed properties to application.properties,
- create the required REST client and GET method,
- create the associated JUnit test,
- and use Maven to build the application and run the unit test.
Create Java POJO
Before working with a REST endpoint, it is a good idea to create the needed POJO. Unless you wish to work with raw JSON string data, you need to create a class that corresponds with the JSON data object returned from the COVID-19 data endpoint. Let’s create that POJO.
- Navigate to the COVID-19 data API.
- Call the endpoint by clicking the test endpoint button.
- In the panel on the lower right, note that the endpoint returns a JSON array containing one JSON object.

Although you can work with the returned data as a String or JSON object, it is easier if converted into a POJO that can be serialized into JSON and deserialized from JSON. Then you can use that POJO more naturally in your application’s business and data logic, and more importantly, keep the REST endpoint logic and format encapsulated and hidden from the remainder of the application. By doing this, you reduce your application’s interdependencies. The following illustrates what you wish to accomplish.

Rather than working with the JSON data returned from the GetTotals endpoint, it would be much easier to have that data converted into an instance of a CovidTotal POJO.
Jackson Library
One library for serializing/deserializing JSON to POJO included in the Spring Web starter that we added to our Spring Boot project is the Jackson library. This library is a powerful tool for serializing and deserializing between Java and JSON. Jackson uses annotations to map a Java class and its properties to JSON. Although you do not require understanding Jackson to complete this tutorial, if unfamiliar with Jackson, you should read the Wikipedia entry to obtain at least a cursory understanding of Jackson (Jackson (API) – Wikipedia).
The jsonschema2pojo Online Tool
Let’s create the POJO by using an online tool called jsonschema2pojo (jsonschema2pojo.org).
- Navigate to the COVID-19 data GetCountryData endpoint.
- Click Schema to show the response’s JSON schema.
- Click the clipboard icon to copy the JSON Schema to your computer’s clipboard buffer.

- Navigate to the jsonschema2pojo website (jsonschema2pojo.org).
- Paste the schema in the textbox, name the package com.rapidapi.example.tutorial.rest, and the class name CovidTotal.
- Ensure JSON Schema is checked for the Source type, the Annotation style is Jackson 2.x, and that Include getters and setters is checked.

- Click the Preview button to preview the generated class.

- After satisfied with the previewed class, click Zip to generate a zip file to download.

- Unzip the file in the desired location.
After creating the data package and adding the CovidTotal file to the package, your project should have the following structure.
src | |--main | | | | | java | | | |---com | | | |--rapidapi | | | |--example | | | |--tutorial | | | |--restTutorial | | | | | |--RestTutorialApplication.java | | | |--data | | | |--CovidTotal.java | |--resources | | | |--static | | | |--templates | | | |--application.properties | | |--test | | java | |--com | |--rapidapi | | |--example | |--restTutorial | |--RestTutorialApplicationTests.java
The tool generated a Java data object with the needed annotations. Each property is annotated with the @JsonProperty annotation, as are the associated getter and setter methods. The @JsonInclude annotation signifies the order of the properties in the corresponding JSON object. The following code is the generated CovidTotal class.
package com.rapidapi.example.tutorial.restTutorial.data; import java.util.HashMap; import java.util.Map; import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; @JsonInclude(JsonInclude.Include.NON_NULL) @JsonPropertyOrder({ "confirmed", "recovered", "critical", "deaths" }) public class CovidTotal { @JsonProperty("confirmed") private String confirmed; @JsonProperty("recovered") private String recovered; @JsonProperty("critical") private Long critical; @JsonProperty("deaths") private Long deaths; @JsonIgnore private Map<String, Object> additionalProperties = new HashMap<String, Object>(); @JsonProperty("confirmed") public String getConfirmed() { return confirmed; } @JsonProperty("confirmed") public void setConfirmed(String confirmed) { this.confirmed = confirmed; } @JsonProperty("recovered") public String getRecovered() { return recovered; } @JsonProperty("recovered") public void setRecovered(String recovered) { this.recovered = recovered; } @JsonProperty("critical") public Long getCritical() { return critical; } @JsonProperty("critical") public void setCritical(Long critical) { this.critical = critical; } @JsonProperty("deaths") public Long getDeaths() { return deaths; } @JsonProperty("deaths") public void setDeaths(Long deaths) { this.deaths = deaths; } @JsonAnyGetter public Map<String, Object> getAdditionalProperties() { return this.additionalProperties; } @JsonAnySetter public void setAdditionalProperty(String name, Object value) { this.additionalProperties.put(name, value); } }
Review endpoint in Postman
Now that we have the POJO let’s analyze the API REST endpoint using Postman. Always use a tool such as Postman or CURL to understand a REST endpoint before beginning coding. I prefer Postman to work with REST endpoints. Postman calls itself as “the collaboration platform for API development,” and is available as a Chrome browser extension or as a stand-alone application. It has both a free and paid version (postman.com); I use the free version. Postman has become an indispensable tool for many developers that work with REST endpoints. In this tutorial, you use Postman to understand the APIs before coding the API REST client.
Let’s create a new GET request in Postman that requests totals from the Get Totals COVID-19 data REST endpoint (https://covid-19-data.p.rapidapi.com/totals).
- Click the plus sign to create a new tab (A).
- Select GET from the dropdown (B) and enter the endpoint URL in the textbox (C).
- Click Headers and create the X-RapidAPI-Host and X-RapidAPI-Key headers with the appropriate data values (D)
- Click Send to make the REST GET request.

The response consists of the confirmed, recovered, critical, and deaths worldwide due to COVID-19. The following shows the fulfilled request in Postman. Note that it returns an array consisting of one JSON object that you created the CovidTotal data object to map. This difference from the generated POJO is important. The endpoint does not return a CovidTotal, but rather, an array of CovidTotal instances, albeit an array containing a single instance.

Now that you understand the REST endpoint return to your Java application source code.
NOTE: Any REST call to any API curated by RapidAPI must include the X-RapidAPI-Host and X-RapidAPI-Key headers, or the request will fail.
Modify application.properties
The application.properties file is a convenient way to keep your application’s configurable properties external to your compiled application. The application.properties file can be anywhere on your application’s classpath or passed to the application via the command-line; for example, the following starts an application. It passes the path to the Spring configuration file.
java -jar MyApplication.jar -Dspring.config.location=/foo/bar/application.properties
Of course, the file need not be named application.properties, but this is the name required if not passing the file via the command-line, as Spring looks for a file with this name on the application’s classpath in addition to the properties file specified on the command-line. For convenience, in this tutorial, you leave the properties file in the application’s resource folder and package it within the created jar file.
Every call to an API curated by RapidAPI requires HTTP headers containing a key identifying your account, X-RapidAPI-Key, and a name identifying the specific API your application is calling, X-RapidAPI-Host. As these could change, a convenient location for these parameters is the application.properties file.
- Add the following parameters to the application.properties file. Replace <snip> with the key provided to you by RapidAPI.
rapidapi.covid.url=https://covid-19-data.p.rapidapi.com/totals rapidapi.host.name=X-RapidAPI-Host rapidapi.host.covid.value=covid-19-data.p.rapidapi.com rapidapi.key.name=X-RapidAPI-Key rapidapi.key.value=<snip>
As you see in the next section, you are parameterizing both the header name and value. For instance, the actual headers are as follows, where <snip> is replaced by your account key.
X-RapidAPI-Host=covid-19-data.p.rapidapi.com X-RapidAPI-Key=<snip>
Create the REST Client and GET Method
Create the REST client class, COVIDRestClient, in the com.rapidapi.example.tutorial.restTutorial.rest.client package. This class will handle making the HTTP requests and responses with the REST endpoint.
- Create a new class named CovidRestClient and annotate it with the @Component annotation.
- Add the properties from application.properties to the class using the @Value annotation.
- Create a constructor that takes a RestTemplateBuilder as a parameter and uses that builder to create a RestTemplate instance.
- Create the getTotals method, as shown below.
package com.rapidapi.example.tutorial.restTutorial.rest.client; import java.net.URI; import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; import com.rapidapi.example.tutorial.restTutorial.data.CovidCountryTotal; import com.rapidapi.example.tutorial.restTutorial.data.CovidTotal; @Component public class CovidRestClient { @Value("${rapidapi.covid.url}") String covidUrl; @Value("${rapidapi.key.name}") String apiKeyName; @Value("${rapidapi.key.value}") String apiKeyValue; @Value("${rapidapi.host.name}") String hostName; @Value("${rapidapi.host.covid.value}") String hostValue; RestTemplate restTemplate; public CovidRestClient(RestTemplateBuilder restTemplateBuilder) { restTemplate = restTemplateBuilder.build(); } public CovidTotal getTotals() { CovidTotal total = null; try { URI uri; uri = new URI(covidUrl); HttpHeaders headers = new HttpHeaders(); headers.set(apiKeyName, apiKeyValue); headers.set(hostName, hostValue); headers.setContentType(MediaType.APPLICATION_JSON); headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); HttpEntity<String> request = new HttpEntity<String>(headers); ResponseEntity<CovidTotal[]> totalEntity = restTemplate.exchange(uri, HttpMethod.GET, request, CovidTotal[].class); total = totalEntity.getBody()[0]; } catch (URISyntaxException e) { e.printStackTrace(); } return total; } }
The @Value annotation is used by Spring to inject values using expressions. For example, Spring replaces the expression ${covid.url} with the value from the application.properties file before compilation. The constructor passes Spring’s auto-configured RestTemplateBuilder bean (Javadoc) as a parameter, which then creates the class’s RestTemplate bean instance. The @Component annotation indicates the CovidTotal class is a component and should be auto-scanned by Spring on application startup (Javadoc).
The HttpHeaders class is a Spring class that holds key/value pairs that are translated into HTTP headers (Javadoc). The HttpHeaders instance is then passed to an HttpEntity class. The HttpEntity class abstracts the HttpRequest, both body and headers (Javadoc). The class type parameter (HttpEntity<T>) indicates the HTTP Request body type. Above, we set the type to String, and omitted the String when constructing the HttpEntity class, although we could have just as easily constructed it with an empty String class.
HttpEntity<String> request = new HttpEntity<String>("", headers)
After creating the HttpEntity, we then passed it to the RestTemplate instance’s exchange method. A RestTemplate has numerous methods for making synchronous HTTP Requests (JavaDoc). For example, above, we used the exchange method and passed a URL as a string, an indicator that we wish the template to make a GET request, and the expected result class. Behind the scenes, exchange creates the RequestEntity from the parameters passed to exchange, makes an HTTP GET request, and then returns a ResponseEntity.
ResponseEntity<CovidTotal[]> totalEntity = restTemplate.exchange(uri, HttpMethod.GET, request, CovidTotal[].class);
The ResponseEntity class type parameter matches the class specified as a parameter in the exchange method. The type parameter, the same as HttpEntity, represents the response’s body type (Javadoc). Remember, from our Postman exploration of the endpoint, we expected the following JSON response.
[ { "confirmed": "2110624", "recovered": "526546", "critical": "51116", "deaths": "137090" } ]
This response is an array, indicated by the opening and closing square braces, containing a generic object with the confirmed, recovered, critical, and deaths properties. However, we created a CovidTotal POJO, not an array. But, this is not a problem, as Jackson automatically converts the JSON object to an array of CovidTotal instances. As this array only contains one CovidTotal instance, we only requested the first element.
total = totalEntity.getBody()[0];
Note: As of Spring 5.0 Spring recommends using the reactive WebClient class (org.springframework.web.reactive.client.WebClient) “which has a more modern API and supports sync, async, and streaming scenarios.” But RestTemplate, as of the time of this tutorial, remains the more common method.
Create the Associated JUnit Test
When we created the application in Spring Initializr, it created our application’s unit-testing framework in addition to our application. Open the RestTutorialApplicationTests class and complete the following steps to add logic needed to test The CovidRestClient class. The test is not extensive, but it prints the results and ensures that the confirmed cases are greater than zero.
- Add the CovidRestClient class to the RestTutorialApplicationTests class using the @Autowired tag.
- Create the testGetTotals method, as shown below.
package com.rapidapi.example.tutorial.restTutorial; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import com.rapidapi.example.tutorial.restTutorial.data.CovidTotal; import com.rapidapi.example.tutorial.restTutorial.rest.client.CovidRestClient; @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) class RestTutorialApplicationTests { @Autowired CovidRestClient covidClient; @Test public void testGetTotals() { CovidTotal totals = covidClient.getTotals(); System.out.println("Confirmed: " + totals.getConfirmed()); System.out.println("Deaths: " + totals.getDeaths()); System.out.println("Recovered: " + totals.getRecovered()); assertTrue(Integer.parseInt(totals.getConfirmed()) > 0); } }
The @SpringBootTest annotation (Javadoc) indicates to Spring that the class is a test class that executes unit tests. The @Test annotation marks the method as a test case for JUnit.
Build the Application Using Maven and Run the Unit Test
Spring Initializr created a Maven POM file when creating our application. We can, therefore, use Maven to build the application and run the unit tests.
- From the command-line, run the following command.
mvn clean compile package
After compiling and packaging the application as a Jar, Maven should run the unit test, and print the following output to the command-line.
Confirmed: 1727588 Deaths: 105725 Recovered: 390599 [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 6.773 s - in com.rapidapi.example.tutorial.restTutorial.RestTutorialApplicationTests
GET Totals by Country Name COVID-19 (Query String)
The getCountryDataByName endpoint returns totals for the country requested by a query string parameter. A query string assigns values to parameters attached to a URL. Query string parameters are an efficient way to send text data as part of a URL; for example, the following is the getCountryDataByName URL with a query string.
https://covid-19-data.p.rapidapi.com/country?format=json&name=italy
The question mark indicates the addition of one or more query string parameters while the ampersand separates multiple parameters. In this example, we are passing to the REST endpoint that we wish to limit the data to Italy and return the data as JSON.
Create POJO
As with the previous endpoint, begin by creating a POJO from the JSON schema provided by the API provider.
- Copy the getCountryDataByName schema to the clipboard.

- Generate the data class at the jsonschema2pojo website.

- Save the class to the project’s data package.
package com.rapidapi.example.tutorial.restTutorial.data; import java.util.HashMap; import java.util.Map; import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; @JsonInclude(JsonInclude.Include.NON_NULL) @JsonPropertyOrder({ "country", "confirmed", "recovered", "critical", "deaths", "latitude", "longitude" }) public class CovidCountryTotal { @JsonProperty("country") private String country; @JsonProperty("confirmed") private Integer confirmed; @JsonProperty("recovered") private Integer recovered; @JsonProperty("critical") private Integer critical; @JsonProperty("deaths") private Integer deaths; @JsonProperty("latitude") private Double latitude; @JsonProperty("longitude") private Double longitude; @JsonIgnore private Map<String, Object> additionalProperties = new HashMap<String, Object>(); @JsonProperty("country") public String getCountry() { return country; } @JsonProperty("country") public void setCountry(String country) { this.country = country; } @JsonProperty("confirmed") public Integer getConfirmed() { return confirmed; } @JsonProperty("confirmed") public void setConfirmed(Integer confirmed) { this.confirmed = confirmed; } @JsonProperty("recovered") public Integer getRecovered() { return recovered; } @JsonProperty("recovered") public void setRecovered(Integer recovered) { this.recovered = recovered; } @JsonProperty("critical") public Integer getCritical() { return critical; } @JsonProperty("critical") public void setCritical(Integer critical) { this.critical = critical; } @JsonProperty("deaths") public Integer getDeaths() { return deaths; } @JsonProperty("deaths") public void setDeaths(Integer deaths) { this.deaths = deaths; } @JsonProperty("latitude") public Double getLatitude() { return latitude; } @JsonProperty("latitude") public void setLatitude(Double latitude) { this.latitude = latitude; } @JsonProperty("longitude") public Double getLongitude() { return longitude; } @JsonProperty("longitude") public void setLongitude(Double longitude) { this.longitude = longitude; } @JsonAnyGetter public Map<String, Object> getAdditionalProperties() { return this.additionalProperties; } @JsonAnySetter public void setAdditionalProperty(String name, Object value) { this.additionalProperties.put(name, value); } }
Notice that the class generated has different data types for confirmed and recovered variables than the class generated in the previous section. In CovidCountryTotal, they are defined as Integers, while in CovidTotal, these variables are defined as Strings. Although in a production application, you should change the types for consistency, in this tutorial, leave the variable types as is.
Review endpoint in Postman
Review the REST endpoint in Postman to ensure you understand the endpoint.
- Create the GET request in Postman.
- Click the Params tab and create the two query parameters, format and name, with the values JSON and Italy, respectively.
- Click Send, and the endpoint should return an array containing a single data object containing the country’s data.

- After satisfied you understand the REST endpoint in Postman, return to the Java project.
Modify application.properties
- Add the getCountryDataByName REST endpoint URL to the application.properties file.
rapidapi.covid.country.url=https://covid-19-data.p.rapidapi.com/country
Add the GET Method
- Add the getCountryTotals method to the CovidRestClient class.
public CovidCountryTotal getCountryTotals(String country) { CovidCountryTotal total = null; try { HttpHeaders headers = new HttpHeaders(); headers.set(apiKeyName, apiKeyValue); headers.set(hostName, hostValue); headers.setContentType(MediaType.APPLICATION_JSON); headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); Map<String, String> params = new HashMap<String, String>(); params.put("format", "json"); params.put("name", country); HttpEntity<String> request = new HttpEntity<String>(headers); covidCountryUrl = covidCountryUrl + "?format={format}&name={name}"; ResponseEntity<CovidCountryTotal[]> totalEntity = restTemplate.exchange(covidCountryUrl, HttpMethod.GET, request, CovidCountryTotal[].class, params); total = totalEntity.getBody()[0]; } catch (Exception ex) { ex.printStackTrace(); } return total; }
One method to add query parameters to a URL/URI is by using what are called UriTemplateVariables. In the URI path template, we add one or more placeholders by using curly braces to surround the variable name. At run-time, the variables are replaced with the appropriate value.
Note: This tutorial uses the terms Universal Resource Indicator (URI) and Universal Resource Locator (URL) interchangeably. There are slight differences; however, they are different Java classes. Be aware of this difference when working with them in Java code.
In the Java code, we created a Map that contained the query variables as key/value pairs, where the key is the variable name, and the value is the variable’s value. The restTemplate exchange method then replaced the variables in the URI path template with the matching keys/value pairs from the Map.
?format={format}&name={name} --- becomes ---> ?format=json&name=italy
The RestTemplate then obtained the data from the REST endpoint and deserialized the JSON data in a CovidCountryTotal instance. The getCountryTotal method then returned the object instance fetched from the REST endpoint.
Create the Associated JUnit Test
The JUnit test prints the values from the CovidCountryTotal object to the console using the System.out.println static method and tests that the endpoint did return data by asserting that the confirmed cases are greater than or equal to zero (there could be zero cases for a country).
- Add the testGetItalyTotals method to the RestTutorialApplicationTests class.
@Test public void testGetItalyTotals() { CovidCountryTotal countryTotals = covidClient.getCountryTotals("italy"); System.out.println("Country: " + countryTotals.getCountry()); System.out.println("Confirmed: " + countryTotals.getConfirmed()); System.out.println("Deaths: " + countryTotals.getDeaths()); System.out.println("Recovered: " + countryTotals.getRecovered()); assertTrue(countryTotals.getConfirmed() >= 0); }
Build the Application Using Maven and Run the Unit Test
- Compile and package the application using Maven and you should see the following output from Maven running the newly added test.
Country: Italy Confirmed: 152271 Deaths: 19468 Recovered: 32534
Meme Generator Upload Images (POST)
The Meme Generator is an API for uploading an image and adding a short caption to the image. We use this API in this tutorial to explore sending binary data using a POST request and receiving binary data using a GET request. The endpoints we wish to use are the Upload Image and Generate meme endpoints; however, the Upload image endpoint generates an error if someone previously uploaded an image of the same name. Therefore, we must ensure an image of the same name does not already exist if we wish to avoid an exception. To ensure image name uniqueness, we first call the Get images REST endpoint and check if the name exists in the returned image name array.
Meme Generator Get images Endpoint
- Navigate to the Meme Generator API and note the Get images endpoint.

It is a simple REST endpoint that returns an array of image names as a String. As with every API curated by RapidAPI, you pass the hostname and your key as headers. There are no query string parameters.
https://ronreiter-meme-generator.p.rapidapi.com/images
The REST call returns a string array containing the image names.
[ "Young-And-Reckless", "Baron-Creater", "You-The-Real-MVP", "MyMeme1555636643784", "Pepperidge-Farm-Remembers", "Chocolate-Spongebob", .... ]
Modify application.properties
- Add the Get images URL and hostname to the application.properties file.
rapidapi.meme.upload.url=https://ronreiter-meme-generator.p.rapidapi.com/images rapidapi.host.meme.value=ronreiter-meme-generator.p.rapidapi.com
Create the REST Client and Add the GET Method
- Create the MemeRestClient class and add the properties to the class using the @Value tag.
- Add the doesImageExist method to the MemeRestClient class.
package com.rapidapi.example.tutorial.restTutorial.rest.client; import java.io.File; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.stream.Stream; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.io.FileSystemResource; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; @Component public class MemeRestClient { @Value("${rapidapi.meme.upload.url}") String uploadUrl; @Value("${rapidapi.meme.generate.url}") String generateUrl; @Value("${rapidapi.key.name}") String apiKeyName; @Value("${rapidapi.key.value}") String apiKeyValue; @Value("${rapidapi.host.name}") String hostName; @Value("${rapidapi.host.meme.value}") String hostValue; @Autowired RestTemplate restTemplate; public boolean doesImageExist(String imageName) { boolean isExists = false; try { HttpHeaders headers = new HttpHeaders(); headers.set(apiKeyName, apiKeyValue); headers.set(hostName, hostValue); headers.setContentType(MediaType.APPLICATION_JSON); headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); HttpEntity<String> request = new HttpEntity<String>(headers); ResponseEntity<String[]> fileNamesResponse = restTemplate.exchange(uploadUrl, HttpMethod.GET, request, String[].class); Stream<String> fileNames = Arrays.stream(fileNamesResponse.getBody()); if (fileNames.filter(String -> imageName.equals(String)).findAny().orElse(null) != null) { isExists = true; } } catch (Exception ex) { ex.printStackTrace(); } return isExists; } }
In the code above, we passed a String array to the RestTemplate exchange method as the class type returned by the endpoint. We then loaded the array into a Stream and filtered the stream for a matching name. If it finds a match, the method returns true, otherwise false. We will use this method to ensure the image name of the image we wish to upload is unique.
Create the Associated JUnit Test
The unit test checks if the image with the name “snoopy” exists and prints the result. Here, I use an image of my dog, Snoopy. Select your image to ensure a unique image.
- Add the testImageExists test to the RestTutorialApplicationTests class. Be certain to replace the name with the name of the image you will upload later in this tutorial.
@Test public void testImageExists() { System.out.println("exists: " + memeClient.doesImageExist("snoopy")); }
Note that if you do not change the name from snoopy to something unique, the method will return true the first time executed.
Now that we have a method to ensure our image name’s uniqueness let’s create the method that uploads our image to the API.
Create the POST Method
Create the POST method that uploads the image. This method makes a POST request that posts binary to the endpoint and returns a JSON success/failure message. You should test the endpoint on the RapidAPI website, but be sure not to use the same image you intend to use in our Spring Boot REST application.

- Find an image you wish to upload and use to create a meme. Be sure it is something you are comfortable with sharing, as the image becomes available to anybody using the Meme Generator API.

Add the endpoint to application.properties
- Add the meme URL to the application.properties file.
rapidapi.meme.generate.url=https://ronreiter-meme-generator.p.rapidapi.com/meme
Add the POST Method to the REST Client
- Add the following method, uploadImage, to the MemeRestClient class.
public String uploadImage(String imagePath) { String name = null; try { HttpHeaders headers = new HttpHeaders(); headers.set(apiKeyName, apiKeyValue); headers.set(hostName, hostValue); headers.setContentType(MediaType.MULTIPART_FORM_DATA); File file = new File(jpgImagePath); FileSystemResource resource = new FileSystemResource(file); MultiValueMap<String, Object> body = new LinkedMultiValueMap<>(); body.add("image", resource); HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers); RestTemplate restTemplate = new RestTemplate(); ResponseEntity<String> response = restTemplate.postForEntity(uploadUrl, requestEntity, String.class); System.out.println(response.getBody()); } catch (Exception ex) { ex.printStackTrace(); } return name; }
We loaded a File passed as a parameter and loaded it into a FileSystemResource. We then loaded the FileSystemResource into a MultiValueMap with the “image” String as the key. The “image” key corresponds to the name expected as a form field.
Create the Associated JUnit Test
- Create a method testUploadImage in the RestTutorialApplicationTests class.
@Test public void testUploadImage() { String filePath = "C:/Users/42288/Desktop/rest_spring_article/snoopy.jpg"; String name = memeClient.uploadJpegImage(filePath); System.out.println("name: " + name); }
Create the GET Method that Adds Text
Now that we have created the method that uploads the image let’s create the method that adds the meme text to the image.
- Add the createMeme method to the MemeRestClient class.
public String createMeme(String top, String bottom, String imageName, String pathToWrite) { String value = null; try { HttpHeaders headers = new HttpHeaders(); headers.set(apiKeyName, apiKeyValue); headers.set(hostName, hostValue); headers.setContentType(MediaType.APPLICATION_JSON); headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); HttpEntity<String> request = new HttpEntity<String>(headers); Map<String, String> params = new HashMap<String, String>(); params.put("meme", imageName); params.put("top", top); params.put("bottom", bottom); params.put("font_size", "30"); String url = generateUrl + "?meme={meme}&top={top}&bottom={bottom}&font_size={font_size}"; ResponseEntity<byte[] > imageResponse = restTemplate.exchange(url, HttpMethod.GET, request,byte[].class, params); Files.write(Paths.get(pathToWrite), imageResponse.getBody()); } catch (Exception ex) { ex.printStackTrace(); } return value; }
We added text to the image by sending the text and font size as query parameters to createMeme and then returning the image with the added text as binary. To accommodate this binary data, we specified the return class in the body as a byte array.
ResponseEntity<byte[] > imageResponse = restTemplate.exchange(url, HttpMethod.GET, request,byte[].class, params);
We then saved the bytes to a file.
Files.write(Paths.get(pathToWrite), imageResponse.getBody());
Create the Associated JUnit Test
- Create the testCreateMeme method in RestApplicationTests class.
@Test public void testCreateMeme() { System.out.println("meme: " + memeClient.createMeme("I am rough.", "I am tough.", "snoop", "C:/Users/42288/Desktop/rest_spring_article/snoopymeme.jpg")); }
- Build the application, and the unit test creates the image with the text specified added to the image.

Microsoft Computer Vision API
Above, we created a POST request that takes binary data as the POST requests body data; however, more commonly, you will send key/value data, or a JSON string, as a POST request’s body. In this last example, we send a JSON string to a POST REST endpoint. We skip creating a POJO, as the input is simple, and the returned data is binary. This example illustrates sending JSON in the body of a POST request. It also uses the UriComponentsBuilder class to add query parameters directly to a URL rather than parameters in a String (Javadoc).
- Navigate to the Microsoft Computer Vision API and click Generate Thumbnail (URL).
- Notice that the POST request body takes a JSON record.

Review endpoint in Postman
- Open Postman and create a new connection to the generateThumbnail endpoint.
- Create a body with the image URL provided on the RapidAPI website (A).
- Create two parameters, height=100 and width=100 (B).
- Add the host and your key as headers (C).
{"url":"https://upload.wikimedia.org/wikipedia/commons/1/11/Kanye_West_at_the_2009_Tribeca_Film_Festival.jpg"}
- Click Send, and a thumbnail appears as the response.

Modify application.properties
After ensuring the request working in Postman, we return to the project and modify the application.properties file to contain the two new parameters.
- Add the host and the URL for the Microsoft Vision API to the application.properties file.
rapidapi.microsoft.image.post.url=https://microsoft-azure-microsoft-computer-vision-v1.p.rapidapi.com/generateThumbnail rapidapi.microsoft.image.host.value=microsoft-azure-microsoft-computer-vision-v1.p.rapidapi.com
Create the REST Client and POST Method
Now create the Rest Client. This client requires query parameters, custom headers, and a request body. The request type is POST. The endpoint returns binary data (the thumbnail image), so the method must accept binary as the response.
- Create a new class called MicrosoftImageRestClient.
- Add the needed @Value annotations and the @Autowired RestTemplate.
- Create the headers, but add Application_OCTET_STREAM as the accepted media type.
- Add the query parameters to the original URL using the UriComponentsBuilder class (Javadoc).
- Add the body (imageUrlJson) to the HttpEntity via its constructor.
- Call the exchange method and set the return class to a byte array.
- Save the byte array to a file.
package com.rapidapi.example.tutorial.restTutorial.rest.client; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; import java.util.Collections; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriComponentsBuilder; @Component public class MicrosoftImageRestClient { @Value("${rapidapi.microsoft.image.post.url}") String postUrl; @Value("${rapidapi.host.name}") String hostKeyName; @Value("${rapidapi.microsoft.image.host.value}") String hostValue; @Value("${rapidapi.key.name}") String apiKeyName; @Value("${rapidapi.key.value}") String apiKeyValue; @Autowired RestTemplate restTemplate; public void generateThumbnail() { String imageUrlJson = "{"url":"https://upload.wikimedia.org/wikipedia/commons/1/11/Kanye_West_at_the_2009_Tribeca_Film_Festival.jpg"}"; try { HttpHeaders headers = new HttpHeaders(); headers.set(apiKeyName, apiKeyValue); headers.set(hostKeyName, hostValue); headers.setContentType(MediaType.APPLICATION_JSON); headers.setAccept(Collections.singletonList(MediaType.APPLICATION_OCTET_STREAM)); UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(this.postUrl).queryParam("width", "100") .queryParam("height", "100"); HttpEntity<String> httpEntity = new HttpEntity<String>(imageUrlJson, headers); ResponseEntity<byte[]> response = restTemplate.exchange(builder.toUriString(), HttpMethod.POST, httpEntity, byte[].class); byte[] data = response.getBody(); File file = new File("./thumbnail.jpg"); OutputStream os = new FileOutputStream(file); os.write(data); os.close(); } catch (Exception ex) { ex.printStackTrace(); } } }
The JSON sent to the REST endpoint is a simple key/value pair of the URL and the value, the same as the template method used earlier in the tutorial. Note that we escaped the double-quotes in the body string.
String imageUrlJson = "{"url":"https://upload.wikimedia.org/wikipedia/commons/1/11/Kanye_West_at_the_2009_Tribeca_Film_Festival.jpg"}";
Creating the headers object is the same as the previous examples, only we add the accept type as APPLICATION_OCTET_STREAM because the endpoint returns the thumbnail as binary data. We then use the UriComponentsBuilder to add the query parameters directly to the URL. This technique is different than how we added the query parameters when requesting total for the country of Italy from the COVID-19 data API. There we added the query parameters to a map and then replaced them using in the String.
Map<String, String> params = new HashMap<String, String>(); params.put("format", "json"); params.put("name", country); ... covidCountryUrl = covidCountryUrl + "?format={format}&name={name}"; ...
Both methods work equally well, choose the way you prefer. I prefer the UriComponentsBuilder method of handling URL query parameters.
Note that the HttpEntity took the POST body directly (the imageUrlJson variable) as a constructor parameter along with the headers.
HttpEntity<String> httpEntity = new HttpEntity<String>(imageUrlJson, headers);
The method then used execute to request the resource and return the response as a byte array, which we then saved as a file.
Create the Associated JUnit Test
- Add a new test method, testThumbnail, to the RestTutorialApplicationTests class.
@Test public void testThumbnail() { microsoftClient.generateThumbnail(); }
Build the Application Using Maven and Run the Unit Test
- Use Maven to compile and create the jar. When Maven executes the unit tests, it should write the thumbnail to the file specified.
Summary
This tutorial covered much material. We used REST APIs available on RapidAPI to illustrate making HTTP GET requests and HTTP POST requests from a client application written using Spring Boot. We used the Spring Framework’s RestTemplate class to write the code that called the REST endpoints and received a result. Moreover, as a bonus, we sent and received binary data from REST endpoints using the application. We also used Postman to explore the APIs before writing the client Java code. A tool like Postman saves considerable time and effort debugging REST client code, as using Postman allows a full understanding of the REST endpoint before coding. Finally, the application used simple unit tests to run the client code, ensuring we coded the methods correctly when compiling the application.
REST is currently the defacto standard for inter-application communication, and there are ample resources available online and in print. Moreover, this tutorial only used the RestTemplate’s exchange method. The RestTemplate also has other methods for calling REST endpoints such as getObject and getEntity.
The RapidAPI blog that you are reading this tutorial on also has many examples demonstrating using REST endpoints in a variety of languages and frameworks. Finally, you should note that every REST API curated by RapidAPI has sample code (code snippets) you can review associated with the API.

You should have no trouble finding ample free REST endpoints to continue your learning, thanks to RapidAPI and its 10,000+ curated APIs.
I can’t find the clipboard logo to copy the schema at all (for the COVID-19 API). Is there a step I must do prior to being eligible to copy the schema?
Thank you!