Making synchronous network requests means sending an HTTP request to a remote server and waiting for a response before continuing with the next task. In contrast, asynchronous network requests allow for multiple requests to be made at the same time, and the application can continue with other tasks as it waits for a response.
The use of synchronous network requests is common in many applications because they are simpler and easier to understand, especially for small and straightforward requests. In these cases, using synchronous requests is a good choice as they provide a direct and straightforward way to interact with a RESTful API.
RestTemplate is a tool designed to make synchronous network requests in Spring. It provides a simple and convenient way to send HTTP requests to a RESTful API, and it automatically handles the details of converting the request and response data into the appropriate format, such as JSON or XML.
In this topic, we will work with JsonPlaceholder. This is a free fake API for testing and prototyping.
Response handling
RestTemplate provides two main methods for handling responses from a REST endpoint: getForObject and getForEntity. The difference between the two is that getForObject returns the response body as an object, while getForEntity returns a ResponseEntity object, which contains not only the response body, but also the information about the status code, headers, and so on.
For example, when handling a collection of objects, you might use the following code:
RestTemplate restTemplate = new RestTemplate();
String url = "https://jsonplaceholder.typicode.com/posts";
ResponseEntity<List<Post>> response = restTemplate.exchange(url, HttpMethod.GET, null, new ParameterizedTypeReference<List<Post>>() {});
List<Post> posts = response.getBody();The first line creates a new instance of the RestTemplate class, which will be used to make the API call.
The second line defines the API URL, that retrieves a list of posts.
The exchange method returns a ResponseEntity object that holds information about the response, including the status code and headers, as well as the response body, which is retrieved using the getBody method. In this example, the response body is assigned to a List<Post> variable named posts. Here are the rest of the exchange method arguments:
HttpMethod: the HTTP method to use for the request, in this case,HttpMethod.GET.HttpEntity: a request body, if applicable. In this case,nullis passed since it's a GET.ParameterizedTypeReference: a helper class to extract the response body. In this case, we created an object, which tells theRestTemplateto expect a response body containing a list ofPostobjects.
If we enter this URL into the browser, we can see the structure of the response in JSON format:
[
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia...eveniet architecto"
},
{
"userId": 1,
"id": 2,
"title": "qui est esse",
"body": "est...aperiam non debitis possimus qui neque nisi nulla"
}
]So, the structure of our Post class should look like this:
public class Post {
private long userId;
private long id;
private String title;
private String body;
public Post(long userId, String title, String body) {
this.userId = userId;
this.title = title;
this.body = body;
}
public Post(long userId, long id, String title, String body) {
this.userId = userId;
this.id = id;
this.title = title;
this.body = body;
}
}Getting status code
In addition to getting the response body, RestTemplate provides a method to get the status code:
RestTemplate restTemplate = new RestTemplate();
String apiUrl = "https://jsonplaceholder.typicode.com/posts/{id}";
Map<String, String> params = new HashMap<>();
params.put("id", "1");
ResponseEntity<Post> response = restTemplate.getForEntity(apiUrl, Post.class, params);
HttpStatus statusCode = response.getStatusCode();In this example, after making the GET request, we retrieve the ResponseEntity object that contains the response.
The second line defines the API URL, with a placeholder {id} that represents the post's id we want to retrieve. Then a params map is created to hold parameter keys and values. To get a post by id, we use getForEntity method with url, object type and id parameter.
We then use the getStatusCode method to get the HTTP status code of the response, which is stored in the HttpStatus object statusCode.
Headers
RestTemplate restTemplate = new RestTemplate();
String apiUrl = "https://jsonplaceholder.typicode.com/posts/{id}";
Map<String, String> params = new HashMap<>();
params.put("id", "1");
ResponseEntity<Post> response = restTemplate.getForEntity(apiUrl, Post.class, params);
HttpHeaders headers = response.getHeaders();
String headerValue = headers.getFirst("header-name");In the following example, we retrieve the ResponseEntity object that contains the response. We then use the getHeaders method to get the HTTP headers of the response, which are stored in the HttpHeaders object headers. We can then use the getFirst method of the HttpHeaders object to retrieve the value of a specific header, such as the header with the name header-name, which is stored in the String object headerValue.
Request bodies
Request bodies contain the data that is sent in the payload of an HTTP request. In RESTful APIs, request bodies are often used to provide input to create or update a resource. For example, when creating a new post in a RESTful API, a request body would contain the data for the new post, such as the title and description.
To convert the data in a request body from an object to another format, you can use a class that implements the HttpMessageConverter interface. The RestTemplate class uses a list of HttpMessageConverters to convert the request body and response body to and from the desired format.
For example, if you want to send a request body in JSON format, you can add the following code:
RestTemplate restTemplate = new RestTemplate();
String url = "https://jsonplaceholder.typicode.com/posts";
Post post = new Post(0, "Title", "Description");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<Post> request = new HttpEntity<>(post, headers);
ResponseEntity<Post> response = restTemplate.postForEntity(url, request, Post.class);
Post createdPost = response.getBody();In this example, we set the Content-Type header to MediaType.APPLICATION_JSON to indicate that the request body is in JSON format. The RestTemplate class will then use the appropriate HttpMessageConverter to convert the Post object to JSON format.
Note that you must have a HttpMessageConverter implementation for the desired format (like XML) on the classpath, or you can provide your own implementation. By default, the RestTemplate class includes HttpMessageConverter for JSON and XML formats.
Request headers
Request headers are used to send additional information about the request, such as the format of the request body, authentication credentials, or preferred response format. For example, when sending a request to create a new post, the request header may include the Content-Type header, which indicates the format of the request body (such as JSON or XML).
In RestTemplate, request bodies and headers can be easily added to an HTTP request. When sending a request with a request body, you can create an HttpEntity object, which combines the request body and headers, and pass it as an argument to the RestTemplate method. You can see how it works in the previous example.
GET requests
RestTemplate also provides convenient methods for performing the most common REST verbs, including GET, POST, PUT, and DELETE, making it easy to interact with a RESTful API.
GET is used to retrieve a resource or a collection of resources from the API. For example, you might use a GET request to retrieve information about a specific post.
RestTemplate restTemplate = new RestTemplate();
String apiUrl = "https://jsonplaceholder.typicode.com/posts/{id}";
Map<String, String> params = new HashMap<>();
params.put("id", "1");
Post post = restTemplate.getForObject(apiUrl, Post.class, params);The third line creates a new HashMap object called params, which will be used to store the placeholder values that we want to substitute into the API URL.
The fourth line adds the id parameter with the value 1 to the params map.
The getForObject method is used to send the request, which takes in three arguments:
apiUrl: the URL of the endpoint we want to send the request to, including the placeholder values.Post.class: the type of response we expect to receive from the API.params: the values to substitute into the URL placeholders.
The method returns an object of type Post, which represents the post retrieved from the API. The post variable will now contain the post object returned by the API.
POST requests
POST is used to create a new resource. For example, you might use a POST request to create a new post.
RestTemplate restTemplate = new RestTemplate();
String url = "https://jsonplaceholder.typicode.com/posts";
Post post = new Post(1, "Title", "Description");
ResponseEntity<Post> response = restTemplate.postForEntity(url, post, Post.class);
Post createdPost = response.getBody(); In this example the postForEntity method is used to send the request, which takes in three arguments:
url: the URL of the endpoint we want to send the request to.post: the post object that we want to send in the request body.Post.class: the type of response we expect to receive from the API.
The method returns a ResponseEntity object, which represents the response received from the API. This object has information about the response status code, headers, and the body.
We can access the body of the response using the getBody method, which returns the created post object in this case. The createdPost variable will now contain the post object returned by the API.
PUT requests
PUT is used to update a resource. For example, you might use a PUT request to update a post.
String url = "https://jsonplaceholder.typicode.com/posts/{id}";
Map<String, String> params = new HashMap<>();
params.put("id", "1");
Post updatedPost = new Post(2, "Food", "I like beef");
restTemplate.put(url, updatedPost, params); In this example, the put method is used to send the request, which takes in three arguments:
url: the URL of the endpoint we want to send the request to, including the placeholder values.updatedPost: the updated post data we want to send in the request body.params: the values to substitute into the URL placeholders.
The put method doesn't return a value, but it will update the post in the API with the data in updatedPost.
It's important to note that this example assumes that the API is correctly configured to handle PUT requests to update posts, and that the Post class correctly represents the structure of the post data being sent and received.
DELETE requests
DELETE is used to delete a resource.
String url = "https://jsonplaceholder.typicode.com/posts/{id}";
Map<String, String> params = new HashMap<>();
params.put("id", "2");
restTemplate.delete(url, params);This example demonstrates how to use the delete method in the RestTemplate class to make a DELETE request to the API.
The delete method is used to send the request, which takes in two arguments:
url: The URL of the endpoint we want to send the request to, including the placeholder values.params: The values to substitute into the URL placeholders.
The delete method does not return a value, but it will delete the post with the specified id in the API.
Conclusion
The RestTemplate class is a powerful tool for making synchronous network requests in Java. It supports the four main REST verbs (GET, POST, PUT, and DELETE) and provides a convenient and flexible API for handling responses. With its "for object" and "for entity" methods, the RestTemplate class makes it easy to handle responses as either a single object or a collection of objects. Additionally, the RestTemplate class supports request bodies and headers, allowing you to send data in the desired format and include any necessary headers in your request.
Overall, the RestTemplate class is a widely used and well-documented library that makes it easy to make RESTful API calls in Java. Whether you are building a simple client application or a more complex system, the RestTemplate class provides the functionality you need to send and receive data from remote APIs.