A Guide to Spring RestTemplate

Photo by Ilya Pavlov on Unsplash

A Guide to Spring RestTemplate

REST-based APIs are being used all around us. A lot of applications now use REST APIs for some or all of their functions. Applications must therefore consume APIs elegantly and reliably to function gracefully.

RestTemplate is a class within the Spring framework that allows us to do just that. In this article, we will understand how to use RestTemaplate to invoke REST APIs.

What is REST API?

A REST API (also known as RESTful API) is an application programming interface (API or web API) that conforms to the constraints of REST architectural style and allows for interaction with RESTful web services. REST stands for representational state transfer and was created by computer scientist Roy Fielding.

REST is a set of architectural constraints, not a protocol or a standard. API developers can implement REST in a variety of ways.

A representation of the resource's state is transferred to the requester or endpoint when a client request is made using a RESTful API. This data, or representation, is transmitted over HTTP in one of the following formats: JSON (Javascript Object Notation), HTML, XLT, Python, PHP, or plain text. Despite its name, JSON is the most widely used file format since it can be read by both humans and machines and is language-independent.

Another thing to keep in mind is that headers and parameters play a crucial role in the HTTP methods of a RESTful API HTTP request as they include crucial identification information regarding the request's metadata, authorization, unified resource identifier (URI), caching, cookies, and more. Both request and response headers contain their own HTTP connection details and status codes.

What is spring RestTemplate?

As per official documentation, RestTemplate is a synchronous client to perform HTTP requests.

It is a higher-order API as it uses various HTTP client libraries like JDK HttpURLConnection, Apache HttpClient, and others, to perform HTTP requests.

All of the technical aspects of communication over HTTP are handled by the HTTP client library, and the RestTemplate adds the ability to convert JSON or XML requests and responses to Java objects.

By default, RestTemplate uses the class java.net.HttpURLConnection as the HTTP client. We can, however, switch to another HTTP client library, which we'll see in a later section.

Some Useful Methods of RestTemplate

RestTemplate provides higher-level methods for each of the HTTP methods which makes it easy to invoke RESTful services.

The names of most of the methods follow a simple naming convention:

  • The first part indicates the HTTP method being invoked

  • The second part indicates the returned element

For example, the method getForObject() will invoke a GET request and return an object.

  • getForEntity(): performs a GET request and returns an object of the ResponseEntity class that includes the resource as an object and the status code.

  • getForObject() : similar to getForEntity(), but it returns the resource object directly.

  • exchange(): performs a specified HTTP method, such as GET, POST, PUT, etc, and returns a ResponseEntity including both the resource as an object and the HTTP status code.

  • execute() : similar to the exchange() method, but it takes additional parameters: RequestCallback and ResponseExtractor.

  • headForHeaders(): performs a HEAD request and returns all HTTP headers for the specified URL.

  • optionsForAllow(): performs an OPTIONS request and uses the Allow header to return the HTTP methods that are allowed for the specified URL.

  • delete(): deletes the resources at the given URL using the HTTP DELETE method.

  • put(): updates a resource using HTTP PUT method for a given URL

  • postForObject() : creates a new resource using HTTP POST method and returns an entity representation.

  • postForLocation(): creates a new resource using the HTTP POST method and returns the value of Location header.

For more information on RestTemplate methods , please refer to the Javadoc.

Project Setup for RestTemplate Example

Let’s create a simple spring boot project with the help of Spring Initializer and add the web dependency. The dependency spring-boot-starter-web is a starter dependency for building web applications. This dependency contains a dependency spring-web which has the RestTemplate class.

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

We will build a minimal REST web service to process student data with the following @RestController.

@RestController
public class StudentController {

    private List<Student> students = List.of(new Student(1, "John", 9.08, "Kolkata, WB"),
            new Student(2, "Jack", 9.08, "Patna, Bihar"), new Student(3, "Ramesh", 9.08, "Lucknow, UP"),
            new Student(4, "Shail", 9.08, "Bengalauru, Karnatak"),
            new Student(5, "Karan", 9.08, "Mumbai, Maharashtra"));

    @GetMapping("/students/{id}")
    public Student getStudent(@PathVariable("id") Integer id) {
        return students.stream().filter(student -> student.getId() == id).findFirst().get();
    }

    @GetMapping("/students")
    public List<Student> getStudents() {
        return students;
    }

    @PostMapping("/students")
    public ResponseEntity<String> addNewStudent (@RequestBody Student student) {
        Integer id = students.size();
        student.setId(id);

        students.add(student);

        return new ResponseEntity<>("{\"message\":\"Student record addedd successfully\"}", HttpStatus.CREATED);
    }

    @PutMapping("/students")
    public ResponseEntity<?> updateStudent(@RequestBody Student student) {
        int index = IntStream.range(0, students.size())
                                .filter(i -> students.get(i).getId() == student.getId())
                                .findFirst()
                                .orElse(-1);
        if (index != -1) {
            students.set(index, student);
            return new ResponseEntity<> (HttpStatus.NO_CONTENT);
        }
        return null;
    }

    @DeleteMapping("/students")
    public ResponseEntity<?> deleteStudent(@RequestBody Student student) {
        int index = IntStream.range(0, students.size())
                                .filter(i -> students.get(i).getId() == student.getId())
                                .findFirst()
                                .orElse(-1);
        if (index != -1) {
            students.remove(index);
            return new ResponseEntity<> (HttpStatus.NO_CONTENT);
        }
        return null;
    }
}

The REST service can create, read, update, and delete student resource and supports HTTP GET, POST, PUT, and DELETE request.

In the following section, we will utilize RestTemplate to make use of all these APIs.

Performing Http GET Request to get JSON response

The easiest way of using RestTemplate is to perform an HTTP GET request to fetch the response body as raw JSON string.

Here we will use getForEntity() method from the RestTemplate class to invoke the API and get response as JSON string.

public void getStudentAsJson() {

        String url = "http://localhost:8080/students";

        // Fetch JSON response as String wrapped in ResponseEntity
        ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);

        String student = response.getBody();

        System.out.println(student);
    }

We can use JSON parsing libraries like Jackson to further process the JSON response.

Performing Http GET Request to get response as POJO

We can modify our previous example to get the response as POJO object. We will have to create a POJO class to map the API response body.

Here we can use both getForEntity() method and/or getForObject() method with slight variations in code as shown below:

public void getStudent() {

        String url
          = "http://localhost:8080/students";

        // Fetch response as List wrapped in ResponseEntity
        ResponseEntity<List> response = restTemplate.getForEntity(url, List.class);

        List<Student> student1 = response.getBody();
        System.out.println(student1);


        // Fetching response as Object  
        List<?> student2 = restTemplate.getForObject(url, List.class);

        System.out.println(student2);
    }

Performing Http POST Request

Let us look at an example of how to perform a POST request with the RestTemplate. Here we will use postForObject() method for invoking post API.

public void addNewStudent() {

        String url = "http://localhost:8080/students";

        // Create the request body by wrapping the object in HttpEntity 
        HttpEntity<Student> request = new HttpEntity<Student>(new Student(1, "Rohit", 7.8, "BBSR"));

        // Send the request body in HttpEntity for HTTP POST request
        String response = restTemplate.postForObject(url, request, String.class);

        System.out.println(response);
    }

Request body is passed in postForObject() method in the form of an HttpEntity class.

Perfoming POST request using exchange() method

In previous examples, we saw specific methods for performing API class like postForObject() for HTTP Post, getForObject() for HTTP GET. Similarly, for HTTP PUT, DELETE and PATCH we have similar methods in RestTemplate class.

On the other hand the exchange() method is more flexible and can be applied to various HTTP methods. Http method is passed as parameter.

    public void addNewStudentExchange() {
        String url = "http://localhost:8080/students";

        // Create the request body by wrapping the object in HttpEntity
        HttpEntity<Student> request = new HttpEntity<Student>(new Student("Robin", 8.0, "Agra"));

        ResponseEntity<String> resp = restTemplate.exchange(url, HttpMethod.POST, request, String.class);

        System.out.println(resp);
    }

Performing PUT request using excahange() method

In below example, we will exchange() method to perform HTTP PUT request.

    public void updateStudentWithExchange() {

        String url = "http://localhost:8080/students";

        // Create the request body by wrapping the object in HttpEntity
        HttpEntity<Student> request = new HttpEntity<Student>(new Student(1, "Rakesh", 7.8, "Ara"));

        // Send the PUT method as a method parameter
        restTemplate.exchange(url, HttpMethod.PUT, request, Void.class);
    }

Example to use execute() method

In comparison to exchange(), execute() method is the most generalized way to perform HTTP request, with complete control over request preparation and response extraction via callback interfaces.

The execute method takes RequestCallback parameter for creating request and ResponseExtractor callback for processing response.

public void getStudentasStream() {
            final Student student = new Student(1, "Rakesh", 7.8, "Ara");

            String url = "http://localhost:8080/Students";

            // Set HTTP headers in the request callback
            RequestCallback requestCallback = request -> {
                ObjectMapper mapper = new ObjectMapper();
                    mapper.writeValue(request.getBody(), 
                            student);

                    request.getHeaders()
                     .setAccept(Arrays.asList(
                             MediaType.APPLICATION_OCTET_STREAM, 
                             MediaType.ALL));
                    };

            // Processing the response. Here we are extracting the 
            // response and copying the file to a folder in the server.
            ResponseExtractor<Void> responseExtractor = response -> {
                     Path path = Paths.get("/var/temp/path");
                     Files.copy(response.getBody(), path);
                     return null;
                 };

            restTemplate.execute(url, HttpMethod.GET, requestCallback, responseExtractor );    

        }

Configuring HTTP Client in RestTemplate

The easiest way to use the RestTemplate is by creating a Bean of the RestTemplate with empty constructor and adding it as dependency by Autowiring wherever needed as shown in previous examples.

As mentioned earlier, RestTemplate uses java.net.HttpURLConnection as the default Http Client. However if needed we can configure RestTemplate to use a different HTTP client library like Apache HttpComponents, Netty, OkHttp, etc.

In the below example we will configure RestTemplate to use ApacheHttpClient library. To do this we will have to add the client library as dependency.

<dependency>
            <groupId>org.apache.httpcomponents.client5</groupId>
            <artifactId>httpclient5</artifactId>
</dependency>

Next, we will configure the various settings/attributes of the HTTP client like connection timeout, socket read timeout, pooled connection limit etc.

@Bean
    public RestTemplate customRestTemplate() {
        return new RestTemplate(getClientHttpRequestFactory());
    }

    private ClientHttpRequestFactory getClientHttpRequestFactory() {

        // Create an instance of Apache HttpClient
        HttpComponentsClientHttpRequestFactory httpClientFactory = new HttpComponentsClientHttpRequestFactory();

        int connectTimeout = 5000;

        httpClientFactory.setConnectTimeout(connectTimeout);
        httpClientFactory.setConnectionRequestTimeout(5000);

        return httpClientFactory;
    }

Other Http Client in Spring

In Spring 5, RestTemplate class is moved to maintenance mode. And a non-blocking WebClient is provided as a modern alternative to the RestTemplate.

WebClient supports both synchronous and asynchronous HTTP requests and streaming scenarios. Therefore, RestTemplate will be marked as deprecated in future version of the Spring Framework.

Conclusion

  • RestTemplate is a synchronous client used for making REST API calls via HTTP.

  • It offers generalized methods like execute() and exchange(), with execute() being the most versatile as it allows for customizing request and response processing through callbacks.

  • RestTemplate also provides specific methods for various HTTP methods, such as getForObject() and getForEntity().

  • You can choose to receive the response in either raw JSON format, which requires further processing with a JSON parser, or as a structured POJO that can be directly used in your application.

  • When sending a request body, you wrap the POJOs in an HttpEntity class.

  • RestTemplate can be customized by integrating an HTTP client library, error handler, and message converter.

  • It's important to note that calling RestTemplate methods blocks the request thread until a response is received. For new applications, it is recommended to consider using the Reactive WebClient.

You can refer the source code used in the article on GitHub.