REST-styled APIs are all around us. Many applications need to invoke REST APIs for some or all of their functions. Hence for applications to function gracefully, they need to consume APIs elegantly and consistently.
RestTemplate
is a class within the Spring framework that helps us to do just that. In this tutorial, we will understand how to use RestTemplate
for invoking REST APIs of different shapes.
Example Code
This article is accompanied by a working code example on GitHub.
What is Spring RestTemplate
?
According to the official documentation, RestTemplate
is a synchronous client to perform HTTP requests.
It is a higher-order API since it performs HTTP requests by using an HTTP client library like the JDK HttpURLConnection, Apache HttpClient, and others.
The HTTP client library takes care of all the low-level details of communication over HTTP while the RestTemplate
adds the capability of transforming the request and response in JSON or XML to Java objects.
By default, RestTemplate
uses the class java.net.HttpURLConnection
as the HTTP client. However, we can switch to another HTTP client library which we will see in a later section.
Some Useful Methods of RestTemplate
Before looking at the examples, it will be helpful to take a look at the important methods of the RestTemplate
class.
RestTemplate
provides higher-level methods for each of the HTTP methods which make it easy to invoke RESTful services.
The names of most of the methods are based on a naming convention:
- the first part in the name indicates the HTTP method being invoked
- the second part in the name indicates returned element.
For example, the method getForObject()
will perform a GET and return an object.
getForEntity()
: executes a GET request and returns an object ofResponseEntity
class that contains both the status code and the resource as an object.getForObject()
: similar togetForEntity()
, but returns the resource directly.exchange()
: executes a specified HTTP method, such as GET, POST, PUT, etc, and returns aResponseEntity
containing both the HTTP status code and the resource as an object.execute()
: similar to theexchange()
method, but takes additional parameters:RequestCallback
andResultSetExtractor
.headForHeaders()
: executes a HEAD request and returns all HTTP headers for the specified URL.optionsForAllow()
: executes an OPTIONS request and uses the Allow header to return the HTTP methods that are allowed under the specified URL.delete()
: deletes the resources at the given URL using the HTTP DELETE method.put()
: updates a resource for a given URL using the HTTP PUT method.postForObject()
: creates a new resource using HTTP POST method and returns an entity.postForLocation()
: creates a new resource using the HTTP POST method and returns the location of the newly created resource.
For additional information on the methods of RestTemplate
, please refer to the Javadoc.
We will see how to use the above methods of RestTemplate
with the help of some examples in subsequent sections.
Project Setup for Running the Examples
To work with the examples of using RestTemplate
, let us first create a Spring Boot project with the help of the Spring boot Initializr, and then open the project in our favorite IDE. We have added the web
dependency to the Maven pom.xml.
.
The dependency spring-boot-starter-web
is a starter for building web applications. This dependency contains a dependency to the RestTemplate
class.
We will use this POJO class Product
in most of the examples:
|
|
We also have built a minimal REST web service with the following @RestController
:
|
|
The REST web service contains the methods to create, read, update, and delete product
resources and supports the HTTP verbs GET, POST, PUT, and DELETE.
When we run our example, this web service will be available at the endpoint http://localhost:8080/products
.
We will consume all these APIs using RestTemplate
in the following sections.
Making an HTTP GET Request to Obtain the JSON Response
The simplest form of using RestTemplate
is to invoke an HTTP GET request to fetch the response body as a raw JSON string as shown in this example:
|
|
Here we are using the getForEntity()
method of the RestTemplate
class to invoke the API and get the response as a JSON string. We need to further work with the JSON response to extract the individual fields with the help of JSON parsing libraries like Jackson.
We prefer to work with raw JSON responses when we are interested only in a small subset of an HTTP response composed of many fields.
Making an HTTP GET Request to Obtain the Response as a POJO
A variation of the earlier method is to get the response as a POJO class. In this case, we need to create a POJO class to map with the API response.
|
|
Here also we are calling the getForEntity()
method for receiving the response as a List
of Product
objects.
Instead of using getForEntity()
method, we could have used the getForObject()
method as shown below:
|
|
Instead of the ResponseEntity
object, we are directly getting back the response object.
While getForObject()
looks better at first glance, getForEntity()
returns additional important metadata like the response headers and the HTTP status code in the ResponseEntity
object.
Making an HTTP POST Request
After the GET methods, let us look at an example of making a POST request with the RestTemplate
.
We are invoking an HTTP POST method on a REST API with the postForObject()
method:
|
|
Here the postForObject()
method takes the request body in the form of an HttpEntity
class. The HttpEntity
is constructed with the Product
class which is the POJO class representing the HTTP request.
Using exchange()
for POST
In the earlier examples, we saw separate methods for making API calls like postForObject()
for HTTP POST and getForEntity()
for GET. RestTemplate
class has similar methods for other HTTP verbs like PUT, DELETE, and PATCH.
The exchange()
method in contrast is more generalized and can be used for different HTTP verbs. The HTTP verb is sent as a parameter as shown in this example:
|
|
Here we are making the POST request by sending HttpMethod.POST
as a parameter in addition to the request body and the response type POJO.
Using exchange()
for PUT with an Empty Response Body
Here is another example of using the exchange()
for making a PUT request which returns an empty response body:
|
|
Here we are sending HttpMethod.PUT
as a parameter to the exchange()
method. Since the REST API returns an empty body, we are using the Void
class to represent the same.
Using execute()
for Downloading Large Files
The execute()
in contrast to the exchange()
method is the most generalized way to perform a request, with full control over request preparation and response extraction via callback interfaces.
We will use the execute()
method for downloading large files.
The execute()
method takes a callback parameter for creating the request and a response extractor callback for processing the response as shown in this example:
|
|
Here we are sending a request callback and a response callback to the execute()
method. The request callback is used to prepare the HTTP request by setting different HTTP headers like Content-Type
and Authorization
.
The responseExtractor
used here extracts the response and creates a file in a folder in the server.
Invoking APIs with application/form
Type Input
Another class of APIs takes HTTP form
as an input. To call these APIs, we need to set the Content-Type
header to application/x-www-form-urlencoded
in addition to setting the request body. This allows us to send a large query string containing name and value pairs separated by &
to the server.
We send the request in form variables by wrapping them in a LinkedMultiValueMap
object and use this to create the HttpEntity
class as shown in this example:
|
|
Here we have sent three form variables sku
, name
, and brand
in the request by first adding them to a MultiValueMap
and then wrapping the map in HttpEntity
. After that, we are invoking the postForEntity()
method to get the response in a ResponseEntity
object.
Configuring the HTTP Client in RestTemplate
The simplest form of RestTemplate
is created as a new instance of the class with an empty constructor as seen in the examples so far.
As explained earlier, RestTemplate
uses the class java.net.HttpURLConnection
as the HTTP client by default. However, we can switch to a different HTTP client library like Apache HttpComponents, Netty, OkHttp, etc. We do this by calling the setRequestFactory()
method on the class.
In the example below , we are configuring the RestTemplate
to use Apache HttpClient library. For this, we first need to add the client library as a dependency.
Let us add a dependency on the httpclient
module from the Apache HttpComponents project:
Here we can see the dependency on httpclient
added in Our Maven pom.xml
.
Next we will configure the HTTP client with settings like connect timeout, socket read timeout, pooled connection limit, idle connection timeout, etc as shown below:
|
|
In this example, we have specified the HTTP connection timeout and socket read timeout intervals to 5 seconds. This allows us to fine-tune the behavior of the HTTP connection.
Other than the default HttpURLConnection
and Apache HttpClient, Spring also supports Netty and OkHttp client libraries through the ClientHttpRequestFactory
abstraction.
Attaching an ErrorHandler to RestTemplate
RestTemplate
is associated with a default error handler which throws the following exceptions:
- HTTP status 4xx :
HttpClientErrorException
- HTTP status 5xx :
HttpServerErrorException
- unknown HTTP status :
UnknownHttpStatusCodeException
These exceptions are subclasses of RestClientResponseException
which is a subclass of RuntimeException
. So if we do not catch them they will bubble up to the top layer.
The following is a sample of an error produced by the default error handler when the service responds with an HTTP status of 404:
|
|
RestTemplate
allows us to attach a custom error handler. Our custom error handler looks like this:
|
|
The CustomErrorHandler
class implements the ResponseErrorHandler
interface. It also uses an error POJO: RestTemplateError
and a runtime exception class RestServiceException
.
We override two methods of the ResponseErrorHandler
interface: hasError()
and handleError()
. The error handling logic is in the handleError()
method. In this method, we are extracting the service path and error message from the error response body returned as a JSON with the Jackson ObjectMapper.
The response with our custom error handler looks like this:
|
|
The output is more elegant and can be produced in a format compatible with our logging systems for further diagnosis.
When using RestTemplate
in Spring Boot applications, we can use an auto-configured RestTemplateBuilder
to create RestTemplate
instances as shown in this code snippet:
Here the RestTemplateBuilder
autoconfigured by Spring is injected in the class and used to attach the CustomErrorHandler
class we created earlier.
Attaching MessageConverters
to the RestTemplate
REST APIs can serve resources in multiple formats (XML, JSON, etc) to the same URI following a principle called content negotiation. REST clients request for the format they can support by sending the accept
header in the request. Similarly, the Content-Type
header is used to specify the format of the request.
The conversion of objects passed to the methods of RestTemplate
is converted to HTTP requests by instances of HttpMessageConverter
interface. This converter also converts HTTP responses to Java objects.
We can write our converter and register it with RestTemplate
to request specific representations of a resource. In this example, we are requesting the XML representation of the Product
resource:
|
|
Here we have set up the RestTemplate
with a message converter XStreamMarshaller
since we are consuming XML representation of the Product
resource.
Comparison with Other HTTP Clients
As briefly mentioned in the beginning RestTemplate
is a higher-level construct which makes use of a lower-level HTTP client.
Starting with Spring 5, the RestTemplate
class is in maintenance mode. The non-blocking WebClient
is provided by the Spring framework as a modern alternative to the RestTemplate
.
WebClient
offers support for both synchronous and asynchronous HTTP requests and streaming scenarios. Therefore, RestTemplate
will be marked as deprecated in a future version of the Spring Framework and will not contain any new functionalities.
RestTemplate
is based on a thread-per-request model. Every request to RestTemplate
blocks until the response is received. As a result, applications using RestTemplate
will not scale well with an increasing number of concurrent users.
The official Spring documentation also advocates using WebClient
instead of RestTemplate
.
However, RestTemplate
is still the preferred choice for applications stuck with an older version(< 5.0) of Spring or those evolving from a substantial legacy codebase.
Conclusion
Here is a list of the major points for a quick reference:
RestTemplate
is a synchronous client for making REST API calls over HTTPRestTemplate
has generalized methods likeexecute()
andexchange()
which take the HTTP method as a parameter.execute()
method is most generalized since it takes request and response callbacks which can be used to add more customizations to the request and response processing.RestTemplate
also has separate methods for making different HTTP methods likegetForObject()
andgetForEntity()
.- We have the option of getting the response body in raw JSON format which needs to be further processed with a JSON parser or a structured POJO that can be directly used in the application.
- Request body is sent by wrapping the POJOs in a
HttpEntity
class. RestTemplate
can be customized with an HTTP client library, error handler, and message converter.- Lastly, calling
RestTemplate
methods results in blocking the request thread till the response is received. ReactiveWebClient
is advised to be used for new applications.
You can refer to all the source code used in the article on Github.