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
Feature | RestTemplate | WebClient |
---|---|---|
Synchronous/Asynchronous | Synchronous | Asynchronous (Reactive) |
Module | Spring Web | Spring WebFlux |
Request Types | GET, POST, PUT, DELETE | GET, POST, PUT, DELETE |
Response Handling | Synchronous response handling | Asynchronous response handling (Reactive) |
Non-blocking | No | Yes |
Modern Approach | No | Yes |
Use Cases | Traditional applications | Reactive applications |
1.2 Advantages and Disadvantages
Aspect | RestTemplate | WebClient |
---|---|---|
Advantages |
|
|
Disadvantages |
|
|
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
: AnHttpEntity
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.