Enterprise Java

Spring REST client example

Hello. In this tutorial, we will understand and explore the Spring REST client example.

1. Introduction

Spring REST client refers to a component or library within the Spring Framework ecosystem that is used to consume RESTful web services. The Spring Framework is a popular Java-based framework that provides various tools and modules to simplify the development of enterprise-level applications.

A Spring REST client allows you to interact with RESTful APIs (Application Programming Interfaces) using the HTTP protocol. REST (Representational State Transfer) is an architectural style for designing networked applications, and RESTful APIs are designed around a set of principles that make them easy to use and understand. These APIs typically expose resources through URLs, and you can perform various operations (GET, POST, PUT, DELETE, etc.) on these resources using HTTP methods.

Spring provides several ways to create REST clients:

  • RestTemplate:
    • A synchronous client within the Spring Web module.
    • Simplifies making HTTP requests and handling responses.
    • Supports GET, POST, PUT, and DELETE requests.
    • Can manage responses in formats such as JSON, XML, etc.
  • WebClient:
    • Introduced in later Spring versions.
    • Modern, non-blocking, and reactive approach for consuming RESTful services.
    • Belongs to the Spring WebFlux module.
    • Particularly useful for creating reactive applications.

Both RestTemplate and WebClient provide ways to set headers, manage authentication, handle error responses, and customize requests. They abstract away many of the low-level details of making HTTP requests, making it easier for developers to focus on their application logic.

1.1 Comparison

FeatureRestTemplateWebClient
Synchronous/AsynchronousSynchronousAsynchronous (Reactive)
ModuleSpring WebSpring WebFlux
Request TypesGET, POST, PUT, DELETEGET, POST, PUT, DELETE
Response HandlingSynchronous response handlingAsynchronous response handling (Reactive)
Non-blockingNoYes
Modern ApproachNoYes
Use CasesTraditional applicationsReactive applications

1.2 Advantages and Disadvantages

AspectRestTemplateWebClient
Advantages
  • Simplicity for traditional applications.
  • Synchronous response handling.
  • Familiarity in Spring ecosystem.
  • Well-established and widely used.
  • Asynchronous (reactive) handling for scalability.
  • Non-blocking operations.
  • Modern approach for reactive applications.
  • Efficient resource utilization.
Disadvantages
  • Not suitable for highly concurrent applications.
  • This may lead to thread blocking in large-scale systems.
  • Less efficient in resource usage.
  • The learning curve for developers new to reactive programming.
  • Complexity for simple, traditional applications.
  • Requires understanding of reactive concepts.

1.3 Use Cases

Let’s explore where to use WebClient and RestTemplate by providing use cases for each.

1.3.1 RestTemplate

You are building a traditional web application that interacts with a few external RESTful APIs to retrieve and display data on a web page. Your application is synchronous and primarily serves simple requests and responses. In this scenario, you can use RestTemplate because:

  • It is straightforward to use and fits well with the synchronous nature of your application.
  • The data retrieval and presentation process doesn’t require complex asynchronous operations.
  • You are working in a context where the traditional Spring ecosystem and tools are being used.

Example: Suppose you’re developing an e-commerce website. When a user searches for a product, your application can use RestTemplate to interact with external product catalog APIs and fetch product details. The data is then displayed synchronously on the user’s screen.

1.3.2 WebClient

You are building a high-traffic microservices architecture where services need to handle numerous concurrent requests. The services are designed using reactive principles to ensure scalability, responsiveness, and efficient resource utilization. In this scenario, you should consider using WebClient because:

  • It is designed for asynchronous and non-blocking operations, making it suitable for handling a large number of concurrent requests.
  • Your architecture follows a reactive approach, where services aim to handle multiple requests efficiently while avoiding thread blocking.
  • You want to take advantage of reactive programming benefits, such as better resource utilization and scalability.

Example: Imagine you’re creating a social media platform. When a user posts a new message, your application needs to notify multiple followers in real time without causing delays in the user’s interactions. WebClient, within a reactive framework like Spring WebFlux, could be employed to handle this situation. The messages are distributed asynchronously to followers’ feeds, ensuring responsiveness and scalability.

Remember, the choice between RestTemplate and WebClient depends on your application’s context, requirements, and architecture. If your application is traditional, synchronous, and doesn’t require advanced reactive capabilities, RestTemplate might be more suitable. On the other hand, if your application is part of a reactive architecture and needs to handle high levels of concurrency, WebClient and reactive programming might be the better choice.

2. RestTemple: Working Example

Below is an example of a Spring Boot application that demonstrates how to use RestTemplate for making GET, POST, PUT, and DELETE requests.

2.1 Create a Spring Boot Project

You can use the Spring Initializr to generate a basic Spring Boot project with the necessary dependencies. Here’s a list of Maven dependencies you should add to your Spring Boot project (pom.xml) for this tutorial.

pom.xml

<dependencies>
    <!-- Spring Boot Starter Web for building web applications -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- Spring Boot Starter Test for testing support -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

    <!-- Spring Boot Starter for RestTemplate -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
</dependencies>

Please note that the provided Maven dependencies include spring-boot-starter-web for web application development, spring-boot-starter-test for testing, and spring-boot-starter to include RestTemplate. These dependencies will ensure that you have the necessary tools and libraries to build the example Spring Boot application using RestTemplate for consuming RESTful APIs.

2.2 Create a Controller

In the controller class, we establish the core of our application by crafting a controller that outlines the REST API endpoints and incorporates the powerful RestTemplate for seamless interaction with an external RESTful API.

We begin by fashioning a Java class and annotating it as a RestController to effortlessly manage incoming HTTP requests. This class, aptly named ApiController, becomes the hub for defining methods that correspond to different API endpoints. Within this realm, the @Autowired annotation facilitates the injection of a RestTemplate instance, which we’ve designated as the bridge for our HTTP interactions.

The pivotal @GetMapping annotation combined with the method getPost constitutes our gateway to handling GET requests. Here, we embed exception handling to gracefully manage scenarios where a post isn’t found. The ensuing sections of our code unfold as a symphony of methods, each attuned to distinct HTTP verbs. For instance, createPost employs the @PostMapping annotation to govern the reception of POST requests, while updatePost with @PutMapping and deletePost with @DeleteMapping ensure the harmonious handling of PUT and DELETE requests.

The utilization of RestTemplate within each method manifests the underlying magic that fuels the interaction with the external API. By encapsulating our HTTP operations within this controller class, we engineer a robust foundation for our Spring Boot application, poised to navigate the intricate world of RESTful communication.

ApiController.java

package com.jcg.example.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

@RestController
@RequestMapping("/api")
public class ApiController {

    private final String apiUrl = "https://jsonplaceholder.typicode.com/posts";

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/posts/{postId}")
    public ResponseEntity<String> getPost(@PathVariable Long postId) {
        try {
            ResponseEntity<String> response = restTemplate.getForEntity(apiUrl + "/" + postId, String.class);
            return ResponseEntity.ok(response.getBody());
        } catch (Exception e) {
            return ResponseEntity.status(404).body("Post not found");
        }
    }

    @PostMapping("/posts")
    public ResponseEntity<String> createPost(@RequestBody String postBody) {
        ResponseEntity<String> response = restTemplate.postForEntity(apiUrl, postBody, String.class);
        return ResponseEntity.ok(response.getBody());
    }

    @PutMapping("/posts/{postId}")
    public ResponseEntity<String> updatePost(@PathVariable Long postId, @RequestBody String postBody) {
        restTemplate.put(apiUrl + "/" + postId, postBody);
        return ResponseEntity.ok("Post updated successfully");
    }

    @DeleteMapping("/posts/{postId}")
    public ResponseEntity<String> deletePost(@PathVariable Long postId) {
        restTemplate.delete(apiUrl + "/" + postId);
        return ResponseEntity.ok("Post deleted successfully");
    }
}

2.3 Set Up RestTemplate

In the main Spring Boot application class, we orchestrate the inclusion of RestTemplate into our Spring Boot application, cementing its role as the conduit for seamless HTTP communication. This critical integration unfolds within the central realm of our main Spring Boot application class.

Inside this class, a method adorned with the HTML @Bean keyword takes center stage. This method thoughtfully christened restTemplate(), is meticulously designed to create and configure a RestTemplate instance. Through this method, we lay the groundwork for RestTemplate’s pivotal role as the orchestrator of HTTP interactions, imbuing our application with the power to communicate effectively with external APIs. As we launch our Spring Boot application, the synergistic harmony of this integration comes to life, enabling the smooth and efficient exchange of data over the digital landscape.

YourApplication.java

package com.jcg.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
public class YourApplication {

    public static void main(String[] args) {
        SpringApplication.run(YourApplication.class, args);
    }

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

2.4 Update Server Port

Open the application.properties file located in the src/main/resources directory of your Spring Boot project. Add or modify the following line to set the server port to 10095.

application.properties

server.port=10095

By setting the server port to 10095, your Spring Boot application will now be accessible on that port when you run it.

2.5 Run the Application

Now you can run your Spring Boot application. You can test the different endpoints using tools like curl or a REST client like the Postman tool.

Here’s a brief overview of what each endpoint does:

Curl Requests

-- GET /api/posts/{postId}: Fetches a post by its ID from an external API. Includes exception handling to return a 404 response if the post is not found.
curl -X GET http://localhost:10095/api/posts/1

-- POST /api/posts: Creates a new post using a POST request with a JSON payload.
curl -X POST -H "Content-Type: application/json" -d '{"userId": 1, "title": "New Post", "body": "This is a new post."}' http://localhost:10095/api/posts

-- PUT /api/posts/{postId}: Updates an existing post using a PUT request with a JSON payload.
curl -X PUT -H "Content-Type: application/json" -d '{"userId": 1, "title": "Updated Post", "body": "This post has been updated."}' http://localhost:10095/api/posts/1

-- DELETE /api/posts/{postId}: Deletes a post by its ID.
curl -X DELETE http://localhost:10095/api/posts/1

3. RestTemplate exchange() API

The exchange() API is a versatile method provided by the Spring RestTemplate class, which is a core component for making HTTP requests and handling responses in Spring-based applications. The exchange() method allows you to send HTTP requests and receive responses in a more customizable way compared to simpler methods like getForObject() or postForObject(). It’s a powerful and flexible API that provides greater control over the request, response, and error handling.

Here’s the basic syntax of the exchange() method:

Syntax

public <T> ResponseEntity<T> exchange(String url, HttpMethod method, HttpEntity<?> requestEntity, Class<T> responseType, Object... uriVariables) throws RestClientException;

Let’s break down the parameters:

  • url: The URL of the resource you want to interact with.
  • method: The HTTP method (GET, POST, PUT, DELETE, etc.) is to be used in the request.
  • requestEntity: An HttpEntity containing the request headers, body, and other information.
  • responseType: The class type that represents the expected response.
  • uriVariables: Optional variables that can be used to replace placeholders in the URL.

The exchange() method returns a ResponseEntity object, which encapsulates the HTTP response. It includes details such as the status code, headers, and the response body of the specified type.

This API is particularly useful when you need to work with more complex scenarios, such as customizing headers, handling different HTTP methods, processing different types of responses, or working with error handling in a fine-grained manner.

4. WebClient: Working Example

Spring 5 introduced the WebClient as a non-blocking alternative to RestTemplate, suited for reactive programming. It leverages Project Reactor to offer a reactive way to consume RESTful services. Unlike RestTemplate, WebClient is asynchronous and non-blocking, making it well-suited for high-concurrency scenarios. To understand it better let us understand the alternative way to incorporate WebClient for interacting with RESTful APIs and for ease we’ll only update the impacted classes.

4.1 Update Dependency

Add the spring web flux dependency to the pom.xml.

pom.xml

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

4.2 Update a Controller

Update the controller to demonstrate how WebClient can be used for various HTTP methods in a reactive and non-blocking manner.

ApiController.java

package com.jcg.example.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

@RestController
@RequestMapping("/api")
public class ApiController {

    private final WebClient webClient;

    @Autowired
    public ApiController(WebClient.Builder webClientBuilder) {
        this.webClient = webClientBuilder.baseUrl("https://jsonplaceholder.typicode.com").build();
    }

    @GetMapping("/posts/{postId}")
    public Mono<String> getPost(@PathVariable Long postId) {
        return webClient.get()
                .uri("/posts/{id}", postId)
                .retrieve()
                .bodyToMono(String.class);
    }

    @PostMapping("/posts")
    public Mono<String> createPost(@RequestBody String postBody) {
        return webClient.post()
                .uri("/posts")
                .contentType(MediaType.APPLICATION_JSON)
                .bodyValue(postBody)
                .retrieve()
                .bodyToMono(String.class);
    }

    @PutMapping("/posts/{postId}")
    public Mono<Void> updatePost(@PathVariable Long postId, @RequestBody String postBody) {
        return webClient.put()
                .uri("/posts/{id}", postId)
                .contentType(MediaType.APPLICATION_JSON)
                .bodyValue(postBody)
                .retrieve()
                .bodyToMono(Void.class);
    }

    @DeleteMapping("/posts/{postId}")
    public Mono<Void> deletePost(@PathVariable Long postId) {
        return webClient.delete()
                .uri("/posts/{id}", postId)
                .retrieve()
                .bodyToMono(Void.class);
    }
}

4.3 Set Up WebClient

Inside the main Spring Boot application class, the @Bean annotation gracefully choreographs the webClientBuilder() method. This method orchestrates the creation and customization of WebClient instances. Its presence, in conjunction with Spring’s IoC container, ensures the availability of WebClient.Builder instances wherever the need arises.

YourApplication.java

package com.jcg.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.reactive.function.client.WebClient;

@SpringBootApplication
public class YourApplication {

    public static void main(String[] args) {
        SpringApplication.run(YourApplication.class, args);
    }

    @Bean
    public WebClient.Builder webClientBuilder() {
        return WebClient.builder();
    }
}

By implementing these steps, you’ve effectively integrated WebClient into your Spring Boot application, enabling you to interact with external RESTful APIs using a reactive and non-blocking approach.

Do note that the application API endpoints remain the same.

5. Conclusion

In conclusion, the utilization of RestTemplate and WebClient within the Spring ecosystem brings forth a dynamic duo of tools that cater to distinct scenarios in the realm of RESTful API consumption. RestTemplate, a stalwart of the Spring framework, offers simplicity and familiarity for traditional applications. With its synchronous nature, it excels in scenarios where straightforward data retrieval and presentation are paramount. On the other hand, WebClient ushers in a new era of asynchronous and non-blocking operations, aligning seamlessly with the demands of modern microservices architectures. Its reactive approach enables handling numerous concurrent requests while maximizing resource efficiency.

Whether your journey encompasses a traditional web application seeking simplicity or a high-traffic microservices architecture striving for scalability, the Spring ecosystem accommodates both narratives. As you navigate the landscape of web development, these tools stand ready to empower you, each finding its place where its strengths shine the brightest. Ultimately, the choice between RestTemplate and WebClient hinges on the context, requirements, and architecture of your application. By embracing the strengths of these tools, you’re equipped to craft robust, responsive, and efficient applications that seamlessly interact with RESTful services, adapting to the evolving demands of the digital age.

Yatin

An experience full-stack engineer well versed with Core Java, Spring/Springboot, MVC, Security, AOP, Frontend (Angular & React), and cloud technologies (such as AWS, GCP, Jenkins, Docker, K8).
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button