Spring RestTemplate (with Hands-On Examples)

Spring RestTemplate is a part of the Spring Framework’s WebMVC module and has been the main entry point for making HTTP requests before Spring WebFlux’s WebClient became the new standard.

RestTemplate provides a template-style API (e.g., JdbcTemplate or JmsTemplate) for making HTTP requests, making it easy to work with RESTful APIs in a structured manner. RestTemplate uses an underlying HTTP client library, such as JDK HttpURLConnection, Apache HttpComponents etc.

Depreciation Warning: Spring docs recommend to use the non-blocking, reactive WebClient API which offers efficient support for both sync, async and streaming scenarios. RestTemplate will be deprecated in the future versions.

1. Maven

To use RestTemplate in an application, we must include the latest version of spring-web dependency in non-boot project.

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>6.0.2</version>
</dependency>

If we are using Spring boot then we can import all necessary dependencies by including the spring-boot-starter-web dependency.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>3.1.2</version>
</dependency>

2. Setting Up RestTemplate Bean

The given below are a few ways to create RestTemplate bean in the application.

2.1. Using Constructor

The simplest way to create a RestTemplate instance is by using its constructor:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class WebConfig {

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

2.2. Using RestTemplateBuilder

In Spring Boot application, the RestTemplateBuilder is a convenience class that provides a builder-style API for configuring and creating RestTemplate instances. It also offers to customize advanced configurations such as timeouts.

@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
 
  return builder
    .setConnectTimeout(Duration.ofMillis(3000))
    .setReadTimeout(Duration.ofMillis(3000))
    .build();
}

Apache HTTP client library provides a very granular level of control for whole request and response processing like connection pooling, custom connection management, and request retrying. We can use its CloseableHttpClient as the implementation of HttpClient that also implements Closeable.

@Autowired
CloseableHttpClient httpClient;
 
@Value("${api.host.baseurl}")
private String apiHost;
 
@Bean
public RestTemplate restTemplate() {

	RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory());
	restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(apiHost));
	return restTemplate;
}
 
@Bean
@ConditionalOnMissingBean
public HttpComponentsClientHttpRequestFactory clientHttpRequestFactory() {

	HttpComponentsClientHttpRequestFactory clientHttpRequestFactory
			= new HttpComponentsClientHttpRequestFactory();
	clientHttpRequestFactory.setHttpClient(httpClient);
	return clientHttpRequestFactory;
}

See Also: RestTemplate Configuration with HttpClient

3. HTTP GET Requests using RestTemplate

Let us start learning about making GET requests using RestClient.

3.1. RestTemplate Methods to Make GET Requests

In RestTemplate, the available methods for executing GET APIs are:

  • getForObject(url, classType) – retrieve a representation by doing a GET on the URL. The response (if any) is unmarshalled to the given class type and returned.
  • getForEntity(url, responseType) – retrieve a representation as ResponseEntity by doing a GET on the URL.
  • exchange(url, httpMethod, requestEntity, responseType) – execute the specified RequestEntity and return the response as ResponseEntity.
  • execute(url, httpMethod, requestCallback, responseExtractor) – execute the httpMethod to the given URI template, prepare the request with the RequestCallback, and read the response with a ResponseExtractor.

3.2. Receiving API Response as POJO

We have the following GET API that we will learn to consume using the RestTemplate.

  • /users/{id}: returns a user by id.
@GetMapping("users/{id}")
public ResponseEntity<User> getById(@PathVariable long id) { ... }

Let us call this API with all available 4 methods.

long id = 1L;
String url = "http://localhost:8080/users/{id}";

// Method 1: Using getForObject()

User user = restTemplate.getForObject(url, User.class, id);
System.out.println("User: " + user);

// Method 2: Using getForEntity()

ResponseEntity<User> responseEntity = restTemplate.getForEntity(url, User.class, id);
User user = responseEntity.getBody();
System.out.println("User: " + user);

// Method 3: Using exchange()

ResponseEntity<User> responseEntity = restTemplate.exchange(
  url,
  HttpMethod.GET,
  null,
  User.class,
  id
);

User user = responseEntity.getBody();
System.out.println("User: " + user);

// Method 4: Using execute()

RequestCallback requestCallback = request -> {
  // You can customize the request if needed
};

ResponseExtractor<ResponseEntity<User>> responseExtractor 
  = restTemplate.responseEntityExtractor(User.class);

ResponseEntity<User> responseEntity = restTemplate.execute(
  url,
  HttpMethod.GET,
  requestCallback,
  responseExtractor,
  id
);
User user = responseEntity.getBody();
System.out.println("User: " + user);

3.3. Receiving API Response as XML or JSON String

This is pretty useful when we are getting an unparsable response from the server, and we have no control over getting it fixed on the server side. Here, we can get the response as String, and use a custom parser or a string replacement function to fix the response before handing it over to the parser.

long id = 1L;
String url = "http://localhost:8080/users/{id}";

String userJson = restTemplate.getForObject("/users/{id}", String.class, userid);
System.out.println("User JSON : " + userJson);

We can use the getForEntity() API which returns the ResponseEntity instance. To extract the response body, use its responseEntity.getBody() method.

ResponseEntity<String> responseEntity = restTemplate.getForEntity("/users/{id}", String.class, Map.of("id", "1"));

ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(responseEntity.getBody());

3.4. Sending Request Headers

If we want to send the request headers then we need to use the generic exchange() API.

HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
headers.set("X-COM-PERSIST", "NO");
headers.set("X-COM-LOCATION", "USA");

HttpEntity<String> entity = new HttpEntity<String>(headers);

ResponseEntity<User[]> responseEntity = restTemplate.exchange("/users", HttpMethod.GET, entity, User[].class);

4. HTTP POST Requests using RestTemplate

The available methods for consuming POST APIs are:

  • postForObject(url, request, classType) – POSTs the given object to the URL and returns the representation found in the response as given class type.
  • postForEntity(url, request, responseType) – POSTs the given object to the URL and returns the response as ResponseEntity.
  • postForLocation(url, request, responseType) – POSTs the given object to the URL and returns the value of the Location header.
  • exchange(url, requestEntity, responseType)
  • execute(url, httpMethod, requestCallback, responseExtractor)

We will consume the following POST API using the RestTemplate:

@PostMapping("users")
public ResponseEntity<User> create(@RequestBody User newUser) { ... }

4.1. Using postForObject()

The postForObject() API accepts a POJO instance directly submitted to the remote API and can return the response body having the created resource.

User newUser = new User(1, "Alex", "Golan", "alex@mail.com");  

User createdUser = restTemplate.postForObject("/users", newUser, User.class);

4.2. Using postForLocation()

The postForLocation() API is very similar to postForObject(), except it returns only the Location of the created resource.

User newUser = new User(1, "Alex", "Golan", "alex@mail.com");  

URI location = restTemplate.postForLocation("/users", newUser, User.class);

4.3. Using postForEntity()

Using postForEntity(), we send a POST request to the given API and get access to the HTTP status, headers and response body.

User newUser = new User(1, "Alex", "Golan", "alex@mail.com");  

ResponseEntity<User> responseEntity = restTemplate.postForEntity("/users", newUser, User.class);

System.out.println("HTTP Status: " + responseEntity.getStatusCode());
System.out.println("Response Body: " + responseEntity.getBody());

HttpHeaders headers = responseEntity.getHeaders();
System.out.println("Response Headers: " + headers);

5. HTTP PUT

The available method to invoke an HTTP PUT API is:

  • put(url, request) – PUTs the given request object to the URL.

We are consuming the following PUT API.

@PutMapping("users/{id}")
public ResponseEntity<User> update(@RequestBody User updatedUser) { ... }

Use the put() API as follows:

User user = new User(1, "Alex", "Golan", "a@mail.com");   //POJO

User updatedUser = restTemplate.put("/users/{id}", user, User.class, Map.of("id", "1"));

6. HTTP DELETE

The available methods for invoking an HTTP DELETE API are:

  • delete(url) – deletes the resource at the specified URL.

We are consuming the following DELETE API.

@DeleteMapping("users/{id}")
public HttpStatus delete(@PathVariable long id) { ... }

Use the delete() API as follows:

restTemplate.delete ("/users/{id}",  Map.of("id", "1"));

Feel free to copy and modify the above Spring RestTemplate examples for building the Spring REST API Consumer in your Spring WebMVC application.

7. Exception Handling

To add exception handling to RestTemplate, we can catch exceptions that may occur during HTTP requests and handle them gracefully.

RestTemplate may throw various exceptions depending on the nature of the error, such as HttpClientErrorException for 4xx client errors, HttpServerErrorException for 5xx server errors, and more.

RestTemplate restTemplate = new RestTemplate();
String apiUrl = "https://api.example.com/resource";

try {
  // Send an HTTP GET request
  ResponseEntity<String> responseEntity = restTemplate.getForEntity(apiUrl, String.class);

  // Process the response
  if (responseEntity.getStatusCode().is2xxSuccessful()) {
      String responseBody = responseEntity.getBody();
      System.out.println("Response: " + responseBody);
  } else {
      System.err.println("Unexpected HTTP status: " + responseEntity.getStatusCode());
  }
} catch (HttpClientErrorException e) {
  // Handle HTTP client errors (4xx status codes)
  if (e.getStatusCode().is4xxClientError()) {
      System.err.println("Client error: " + e.getStatusCode() + " - " + e.getStatusText());
      System.err.println("Response Body: " + e.getResponseBodyAsString());
  } else {
      System.err.println("Unexpected HTTP status: " + e.getStatusCode());
  }
} catch (Exception e) {
  // Handle other exceptions
  System.err.println("An error occurred: " + e.getMessage());
}

8. RestTemplate Examples

Happy Learning !!

Sourcecode on Github

Comments

Subscribe
Notify of
guest
11 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.

Our Blogs

REST API Tutorial

Dark Mode

Dark Mode