Using RestTemplate in Spring
3 CommentsLast Updated on May 30, 2019 by jt
1. RestTemplate Introduction
In today’s blog post we will have a look at Springs well-known rest client – the RestTemplate
. The RestTemplate
is the central class within the Spring framework for executing synchronous HTTP requests on the client side.
Like Spring JdbcTemplate, RestTemplate
is also a high-level API, which in turn is based on an HTTP client. By default, the class java.net.HttpURLConnection
from the Java SDK is used in RestTemplate
. However, the Spring Framework makes it possible to easily switch to another HTTP client API. How to do this is described in another blog post.
Most of us surely have experience with HttpURLConnection
or another HTTP client API. When using it we noticed that for each request the same boilerplate code is generated again and again:
- Creating a URL object and opening the connection
- Configuring the HTTP request
- Executing the HTTP request
- Interpretation of the HTTP response
- Converting the HTTP response into a Java object
- Exception handling
When using RestTemplate
all these things happen in the background and the developer doesn’t have to bother with it.
Starting with Spring 5, the non-blocking and reactive WebClient offers a modern alternative to 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.
2. Project Setup
Before we really get started, I would like to take a closer look at the following points of the project setup:
- Used dependencies
- POJO class
Employee
- REST web service for testing
2.1 Used Dependencies
For the RestTemplate
demo project we need the following dependencies in our Spring Boot based application:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies>
The Dependency spring-boot-starter-web
is a starter for building web applications. This dependency contains the class RestTemplate
, the option to publish REST web services and many other web-related things.
As HTTP client API we use Apache HttpComponents for the following examples. Lombok generates e.g. Getter and Setter and helps us to avoid repeating code.
2.2 POJO Class Employee
Our POJO class, which will accompany us through the example, looks like this:
@Data @NoArgsConstructor @AllArgsConstructor public class Employee { private long id; private String firstName; private String lastName; private long yearlyIncome; }
Thanks to Lombok and @Data
Annotation we get the getter and setter methods for free. Furthermore, @Data
generates the following methods automatically:
equals()
hashCode()
toString()
- Constructor with all fields that are annotated with
@NonNull
@NoArgsConstructor
generates a parameterless constructor and @AllArgsConstructor
generates a constructor with all parameters.
2.3 REST Web Service For Testing
In order to better understand the following examples, the demo project includes a very handy REST web service. The corresponding RestController is guru.springframework.resttemplate.web.EmployeeRestController. The code for the controller is kept very simple and functional.
The REST web service provides the possibility to create, read, update and delete employee resources and supports the HTTP verbs GET
, POST
, PUT
and DELETE
. As soon as the application is stopped, all changes made to the resources are lost. The Web service is available at the endpoint http://localhost:8080/rest/employees
.
3. RestTemplate Methods
Before we look at the first source code together, we take a look at the methods of the RestTemplate
class. The class provides over 50 methods, most of them are overloaded several times. The following table gives a rough overview:
Method | Description |
void delete | Executes a DELETE request and returns nothing. |
ResponseEntity<T> exchange | Executes a specified HTTP method, such as GET or POST , and returns a ResponseEntity that contains both the HTTP status code and the resource as an object. |
T execute | Works similar to exchange , but expects an additional RequestCallback and a ResultSetExtractor as parameters. This is useful, for example, if you frequently create complex requests or want to process complex responses. |
ResponseEntity<T> getForEntity | Executes a GET request and returns a ResponseEntity that contains both the status code and the resource as an object. |
T getForObject | Works similar to getForEntity , but returns the resource directly. |
HttpHeaders headForHeaders | Executes a HEAD request and returns all HTTP headers for the specified URL. |
Set<HttpMethod> optionsForAllow | Executes an OPTIONS request and uses the Allow header to return which HTTP methods are allowed under the specified URL. |
T patchForObject | Executes a PATCH request and returns the representation of the resource from the response. The JDK HttpURLConnection does not support PATCH , but Apache HttpComponents and others do. |
ResponseEntity<T> postForEntity | Executes a POST request and returns a ResponseEntity which contains the status code as well as the resource as an object. |
URI postForLocation | Works like postForEntity , but returns the Location header from the response, which indicates under which URI the newly created resource can be reached. |
T postForObject | Works like postForEntity , but returns the resource directly. |
void put | Executes a PUT request and returns nothing. |
Most of the methods are overloaded according to the following scheme:
- URL as
String
and URL parameters as VarArgs of typeString
- URL as
String
and URL parameters asMap<String, String>
- URL as
java.net.URI
without support for URL parameters
Each method with a return type expects a generic class type as a parameter to determine the type of response.
4. RestTemplate Demonstrations
The following examples show how we can consume a REST web service using the RestTemplate
class. All of the following examples are in the EmployeeRestClient
class. It’s a simple client that wraps RestTemplate
and provides Employee-related methods. As always, you can find the code in our GitHub Repository.
public class EmployeeRestClient { private static final String RESOURCE_PATH = "/rest/employees"; private Logger LOG = LoggerFactory.getLogger(EmployeeRestClient.class); private String REQUEST_URI; private RestTemplate restTemplate; public EmployeeRestClient(RestTemplate restTemplate, String host, int port) { this.restTemplate = restTemplate; this.REQUEST_URI = host + ":" + port + RESOURCE_PATH; } }
So far the EmployeeRestClient
is quite unspectacular. We get an instance of the RestTemplate
from the constructor. Also via constructor parameters, we get the host and the port on which the REST web service runs.
Important: All following examples use Apache HttpComponents as underlying HTTP client API. How this can be configured for the RestTemplate
is explained in the post Using RestTemplate with Apaches HttpClient.
4.1 GET
4.1.1 getForEntity()
Let’s start with a simple example to query a single resource:
public ResponseEntity<Employee> getForEntity(long id) { ResponseEntity<Employee> entity = restTemplate.getForEntity(REQUEST_URI + "/{id}", Employee.class, Long.toString(id)); LOG.info("Status code value: " + entity.getStatusCodeValue()); LOG.info("HTTP Header 'ContentType': " + entity.getHeaders().getContentType()); return entity; }
In this code snippet, we use the getForEntity()
method, which returns a ResponseEntity
object as a result. As a parameter, the method expects the URI of the resource including any placeholders and the class type for converting the body.
ResponseEntity
encapsulates the status code of the HTTP response, the HTTP headers and the body that has already been converted into a Java object.
Instead of querying a single resource, it is of course also possible to query a collection of resources, as the following code snippet shows:
public List<Employee> getAll(int page, int pageSize) { String requestUri = REQUEST_URI + "?page={page}&pageSize={pageSize}"; Map<String, String> urlParameters = new HashMap<>(); urlParameters.put("page", Integer.toString(page)); urlParameters.put("pageSize", Long.toString(pageSize)); ResponseEntity<Employee[]> entity = restTemplate.getForEntity(requestUri, Employee[].class, urlParameters); return entity.getBody() != null? Arrays.asList(entity.getBody()) : Collections.emptyList(); }
The REST web service expects a page number and a pageSize (number of resources per page) as query parameters for querying a collection of resources. For these parameters, a Map
is used in this code snippet instead of VarArgs. The ResponseEntity
is typed to an array of Employee
since we expect an undefined number of employees in the result.
4.1.2 getForObject()
If only the body is of interest, the getForObject()
method can be used to query the resource directly as a Java object:
public Optional<Employee> getForObject(long id) { Employee employee = restTemplate.getForObject(REQUEST_URI + "/{id}", Employee.class, Long.toString(id)); return Optional.ofNullable(employee); }
However, if you want to operate directly on the JSON string, this is also possible. If the class type is simply String.class
, we get the raw JSON string:
public JsonNode getAsJsonNode(long id) throws IOException { String jsonString = restTemplate.getForObject(REQUEST_URI + "/{id}", String.class, id); ObjectMapper mapper = new ObjectMapper(); return mapper.readTree(jsonString); }
Via ObjectMapper
we can simply transform the JSON string into a JsonNode
and then access the individual nodes of the JsonNode
very comfortably via jsonNode.path("fieldName")
:
@Test void test_getAsJsonNode() throws Exception { JsonNode jsonNode = client.getAsJsonNode(3); assertNotNull(jsonNode); assertEquals(peterGrey.getId(), jsonNode.path("id").asLong()); assertEquals(peterGrey.getFirstName(), jsonNode.path("firstName").asText()); assertEquals(peterGrey.getLastName(), jsonNode.path("lastName").asText()); assertEquals(peterGrey.getYearlyIncome(), jsonNode.path("yearlyIncome").asLong()); }
4.2 POST
4.2.1 postForObject()
The creation of a new resource via POST
is possible with a one-liner:
public Employee postForObject(Employee newEmployee) { return restTemplate.postForObject(REQUEST_URI, newEmployee, Employee.class); }
In addition to the request URI, the method postForObject()
expects any object that represents the body of the request and a class type for the conversion of the response. As a response, the REST web service returns the created resource including the assigned ID.
4.2.2 postForLocation()
Very similar to postForObject
works the method postForLocation()
. Here we only get the URI of the new resource instead of the created resource:
public URI postForLocation(Employee newEmployee) { return restTemplate.postForLocation(REQUEST_URI, newEmployee); }
4.2.3 postForEntity()
And finally there is postForEntity
, which returns a ResponseEntity
. Additionally, the example shows us how we can send our own values in the HTTP header to the server:
public ResponseEntity<Employee> postForEntity(Employee newEmployee) { MultiValueMap<String, String> headers = new HttpHeaders(); headers.add("User-Agent", "EmployeeRestClient demo class"); headers.add("Accept-Language", "en-US"); HttpEntity<Employee> entity = new HttpEntity<>(newEmployee, headers); return restTemplate.postForEntity(REQUEST_URI, entity, Employee.class); }
4.3 PUT
The method put()
is used for an HTTP PUT
. The return of the method is void. We can use this method to update an employee resource:
public void put(Employee updatedEmployee) { restTemplate.put(REQUEST_URI + "/{id}", updatedEmployee, Long.toString(updatedEmployee.getId())); }
However, there are some use cases where we would like to have a ResponseEntity
as a response since this gives us information about the HTTP status code and the HTTP headers sent along by the server. In this case, we can use the method exchange()
:
public ResponseEntity<Employee> putWithExchange(Employee updatedEmployee) { return restTemplate.exchange(REQUEST_URI + "/{id}", HttpMethod.PUT, new HttpEntity<>(updatedEmployee), Employee.class, Long.toString(updatedEmployee.getId())); }
4.4 DELETE
The method delete()
is used to execute a DELETE
request:
public void delete(long id) { restTemplate.delete(REQUEST_URI + "/{id}", Long.toString(id)); }
Here again the same as with put()
. If the HTTP status code or the HTTP headers are of interest, the method exchange()
must be used:
public ResponseEntity<Void> deleteWithExchange(long id) { return restTemplate.exchange(REQUEST_URI + "/{id}", HttpMethod.DELETE, null, Void.class, Long.toString(id)); }
Since the server doesn’t return anything to us we use Void.class
as the type for response body conversion.
4.5 HEAD
If only the HTTP headers of an HTTP request are of interest, we use method headForHeaders()
:
public HttpHeaders headForHeaders() { return restTemplate.headForHeaders(REQUEST_URI); }
A test of this method confirms that we receive a response with the content type application/json
when we query the specified URL:
@Test void test_headForHeaders() { HttpHeaders httpHeaders = client.headForHeaders(); assertNotNull(httpHeaders.getContentType()); assertTrue(httpHeaders.getContentType().includes(MediaType.APPLICATION_JSON)); }
4.6 OPTIONS
With a query via HTTP OPTIONS
, we can find out which HTTP verbs are allowed for the given URL. RestTemplate
provides the optionsForAllow()
method for this:
public Set<HttpMethod> optionsForAllow(long id) { return restTemplate.optionsForAllow(REQUEST_URI + "/{id}", Long.toString(id)); }
A test of this method confirms that we can query the URL http://localhost:8080/rest/employees/1
with the HTTP verbs GET
, PUT
and DELETE
:
@Test void test_optionsForAllow() { Set<HttpMethod> httpMethods = client.optionsForAllow(1); List<HttpMethod> expectedHttpMethods = List.of(HttpMethod.GET, HttpMethod.PUT, HttpMethod.DELETE); assertTrue(httpMethods.containsAll(expectedHttpMethods)); }
5. Summary
In this blog post, we looked at how we work with the class RestTemplate
. We looked at the following:
- a general overview of RestTemplate and its methods
- numerous code examples for the following HTTP verbs:
GET
POST
PUT
DELETE
HEAD
OPTIONS
Also, like to check out the project repository at GitHub. There you’ll also find a test class, which we didn’t discuss in detail here.
I would also like to draw your attention to the blog post Using RestTemplate with Apaches HttpClient. In this post, we take a look at how to configure RestTemplate
to use it with the HTTP client API of Apache.
Anju
Hi, this is really good tutorial. Apart from this i need to know how microservices talk to each other in MicroServices architecture. Im trying to use netflix eureka server and client to connect different microservices.
Uwe
Hi, good example.
But you forget to mention that a Lombok plugin must be installed.
More information are available: https://www.baeldung.com/lombok-ide