The RestTemplate class in Spring Framework is a synchronous HTTP client for making HTTP requests to consume RESTful web services. It exposes a simple and easy-to-use template method API for sending an HTTP request and also handling the HTTP response. The RestTemplate class also provides aliases for all supported HTTP request methods, such as GET, POST, PUT, DELETE, and OPTIONS.

In this tutorial, we will learn how to use the Spring REST client — RestTemplate — for sending HTTP requests in a Spring Boot application. For all our examples, we will use JSONPlaceholder fake REST API to mimic real application scenarios.

Dependencies

Since RestTemplate class is a part of Spring Web project, we only need spring-boot-starter-web dependency. Add the following dependency to your Gradle project's build.gradle file:

implementation 'org.springframework.boot:spring-boot-starter-web'

If you are using Maven, add the following dependency to your pom.xml file:

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

GET Request

Let's start with a simple example to retrieve a list of posts using RestTemplate's getForObject() method:

RestService.java

@Service
public class RestService {

    private final RestTemplate restTemplate;

    public RestService(RestTemplateBuilder restTemplateBuilder) {
        this.restTemplate = restTemplateBuilder.build();
    }

    public String getPostsPlainJSON() {
        String url = "https://jsonplaceholder.typicode.com/posts";
        return this.restTemplate.getForObject(url, String.class);
    }
}

Notice the response returned by the getForObject() method. It is a plain JSON string. We can easily parse this JSON string into an object using Jackson.

Get Response as Object

We can also map the response directly to a model class. Let us first create a model class:

Post.java

public class Post implements Serializable {

    private int userId;
    private int id;
    private String title;
    private String body;

    // getters and setters
}

Now we can simply use the Post class as response type in getForObject() method:

public Post[] getPostsAsObject() {
    String url = "https://jsonplaceholder.typicode.com/posts";
    return this.restTemplate.getForObject(url, Post[].class);
}

URL Parameters

If you want to pass the query parameters, just append them to URL:

String url = "https://jsonplaceholder.typicode.com/posts?userId=2";

Another way is to use placeholders in the URL for parameters:

public Post getPostWithUrlParameters() {
    String url = "https://jsonplaceholder.typicode.com/posts/{id}";
    return this.restTemplate.getForObject(url, Post.class, 1);
}

Response Handing

If you want to manipulate the response (like checking HTTP status code), use getForEntity() method instead like below:

public Post getPostWithResponseHandling() {
    String url = "https://jsonplaceholder.typicode.com/posts/{id}";
    ResponseEntity<Post> response = this.restTemplate.getForEntity(url, Post.class, 1);
    if(response.getStatusCode() == HttpStatus.OK) {
        return response.getBody();
    } else {
        return null;
    }
}

Custom Request Headers

If you want to set the request headers like content-type, accept, or any custom header, use generic exchange() method:

public Post getPostWithCustomHeaders() {
    String url = "https://jsonplaceholder.typicode.com/posts/{id}";

    // create headers
    HttpHeaders headers = new HttpHeaders();
    // set `accept` header
    headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
    // set custom header
    headers.set("x-request-source", "desktop");

    // build the request
    HttpEntity request = new HttpEntity(headers);

    // use `exchange` method for HTTP call
    ResponseEntity<Post> response = this.restTemplate.exchange(url, HttpMethod.GET, entity, Post.class, 1);
    if(response.getStatusCode() == HttpStatus.OK) {
        return response.getBody();
    } else {
        return null;
    }
}

Quick Guide: Check out RestTemplate GET Request with Parameters and Headers for more GET request examples.

POST Request

A POST request is used to create a new resource. The RestTemplate class offers several template methods like postForObject(), postForEntity(), and postForLocation() for making POST request. The first two methods are quite similar to what we have discussed above in terms of response format. The last method returns the location of the newly created resource instead of returning the full resource.

Let us make use of the postForEntity() method to create a new post:

public Post createPost() {
    String url = "https://jsonplaceholder.typicode.com/posts";

    // create headers
    HttpHeaders headers = new HttpHeaders();
    // set `content-type` header
    headers.setContentType(MediaType.APPLICATION_JSON);
    // set `accept` header
    headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));

    // create a map for post parameters
    Map<String, Object> map = new HashMap<>();
    map.put("userId", 1);
    map.put("title", "Introduction to Spring Boot");
    map.put("body", "Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications.");

    // build the request
    HttpEntity<Map<String, Object>> entity = new HttpEntity<>(map, headers);

    // send POST request
    ResponseEntity<Post> response = this.restTemplate.postForEntity(url, entity, Post.class);

    // check response status code
    if (response.getStatusCode() == HttpStatus.CREATED) {
        return response.getBody();
    } else {
        return null;
    }
}

Alternatively, we can also use postForObject() method to create a new post:

public Post createPostWithObject() {
    String url = "https://jsonplaceholder.typicode.com/posts";

    // create headers
    HttpHeaders headers = new HttpHeaders();
    // set `content-type` header
    headers.setContentType(MediaType.APPLICATION_JSON);
    // set `accept` header
    headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));

    // create a post object
    Post post = new Post(1, "Introduction to Spring Boot",
            "Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications.");

    // build the request
    HttpEntity<Post> entity = new HttpEntity<>(post, headers);

    // send POST request
    return restTemplate.postForObject(url, entity, Post.class);
}

Quick Guide: Check out RestTemplate POST Request with JSON and Headers for more POST request examples.

PUT Request

The RestTemplate class provides put() method that can be used to update a resource:

public void updatePost() {
    String url = "https://jsonplaceholder.typicode.com/posts/{id}";

    // create headers
    HttpHeaders headers = new HttpHeaders();
    // set `content-type` header
    headers.setContentType(MediaType.APPLICATION_JSON);
    // set `accept` header
    headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));

    // create a post object
    Post post = new Post(4, "New Title", "New Body");

    // build the request
    HttpEntity<Post> entity = new HttpEntity<>(post, headers);

    // send PUT request to update post with `id` 10
    this.restTemplate.put(url, entity, 10);
}

The put() method does not return anything. If you want to process the response, use generic exchange() method instead:

public Post updatePostWithResponse() {
    String url = "https://jsonplaceholder.typicode.com/posts/{id}";

    // create headers
    HttpHeaders headers = new HttpHeaders();
    // set `content-type` header
    headers.setContentType(MediaType.APPLICATION_JSON);
    // set `accept` header
    headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));

    // create a post object
    Post post = new Post(4, "New Title", "New Body");

    // build the request
    HttpEntity<Post> entity = new HttpEntity<>(post, headers);

    // send PUT request to update post with `id` 10
    ResponseEntity<Post> response = this.restTemplate.exchange(url, HttpMethod.PUT, entity, Post.class, 10);

    // check response status code
    if (response.getStatusCode() == HttpStatus.OK) {
        return response.getBody();
    } else {
        return null;
    }
}

DELETE Request

To delete an existing resource, you can use delete() method:

public void deletePost() {
    String url = "https://jsonplaceholder.typicode.com/posts/{id}";

    // send DELETE request to delete post with `id` 10
    this.restTemplate.delete(url, 10);
}

HEAD Request

The RestTemplate class offers headForHeaders() method to retrieve headers:

public HttpHeaders retrieveHeaders() {
    String url = "https://jsonplaceholder.typicode.com/posts";

    // send HEAD request
    return this.restTemplate.headForHeaders(url);
}

OPTIONS Request

Let us use optionsForAllow() method to get a list of all supported HTTP operations:

public Set<HttpMethod> allowedOperations() {
    String url = "https://jsonplaceholder.typicode.com/posts";

    // send HEAD request
    return this.restTemplate.optionsForAllow(url);
}

Error Handling

If there is an error during the execution of the request or the server returns a non-successful HTTP error (4xx or 5xx), RestTemplate will throw an exception. You can catch the HttpStatusCodeException in catch block to get the response body and headers:

public String unknownRequest() {
    try {
        String url = "https://jsonplaceholder.typicode.com/404";
        return this.restTemplate.getForObject(url, String.class);
    } catch (HttpStatusCodeException ex) {
        // raw http status code e.g `404`
        System.out.println(ex.getRawStatusCode());
        // http status code e.g. `404 NOT_FOUND`
        System.out.println(ex.getStatusCode().toString());
        // get response body
        System.out.println(ex.getResponseBodyAsString());
        // get http headers
        HttpHeaders headers= ex.getResponseHeaders();
        System.out.println(headers.get("Content-Type"));
        System.out.println(headers.get("Server"));
    }

    return null;
}

Quick Guide: Learn more about handling errors while using the RestTemplate in a Spring Boot application.

RestTemplate Connection Timeout

There are two types of timeouts: connection timeout and read time out. By default, RestTemplate has infinite timeouts. But we can change this behavior by using RestTemplateBuilder class for setting the connection and read timeouts:

public RestService(RestTemplateBuilder restTemplateBuilder) {
    // set connection and read timeouts
    this.restTemplate = restTemplateBuilder
            .setConnectTimeout(Duration.ofSeconds(500))
            .setReadTimeout(Duration.ofSeconds(500))
            .build();
}

Source code: Download the complete source code from GitHub available under MIT license.

Conclusion

That's all folks for using Spring Framework's RestTemplate class to call remote RESTful web services in a Spring Boot application. We talked about almost all important HTTP verbs and used RestTemplate to make requests for all of them.

If you are interested in learning more, check out processing JSON data in Spring Boot guide. It will introduce you to Jackson that is frequently used with RestTemplate for parsing unknown JSON data.

Read Next: RestTemplate Basic Authentication Example

✌️ Like this article? Follow @attacomsian on Twitter. You can also follow me on LinkedIn and DEV. Buy me a coffee (cost $3)

Need help to start a new Spring Boot or MEAN stack project? I am available for contract work. Hire me to accomplish your business goals with engineering and design. Let’s talk about your project: hi@attacomsian.com.