Hi! My name is Viacheslav Aksenov and I am a backend developer specializing in developing complex backend systems in Java and Kotlin. Also, I many small pet projects, that you can find on my GitHub: https://github.com/v-aksenov
A microservice is a small, independent service that is designed to perform a specific task or set of tasks within a larger application. Each microservice is developed and deployed independently of the other microservices in the system, and communicates with other microservices via APIs.
Microservices also offer several other benefits, including improved scalability, better fault tolerance, and increased agility. By breaking an application down into smaller, more independent services, developers can easily scale up or down individual components as needed, and can quickly respond to changes in user needs or market conditions.
However, microservices also introduce some challenges, such as the need for robust API management, service discovery, and distributed tracing. Properly designing and implementing microservices requires careful planning and coordination across the development team, as well as a deep understanding of the unique requirements and constraints of the system being developed.
To answer this question we need to answer the question “What is this current service responsible for?”
Very often in service business logic there is situation when we need to get response from a third-party API. Or moreover, we have several microservices in chain to handle our business process. In these situations we have to implement HTTP client in our microservice.
In a microservices architecture, an HTTP client is a software component that communicates with other microservices over the HTTP protocol. The HTTP client is responsible for making requests to other microservices and receiving responses back.
When a microservice needs to communicate with another microservice, it typically sends an HTTP request to the appropriate endpoint of the other microservice. The HTTP request may include a payload of data, such as a JSON object or XML document, that the receiving microservice can use to perform its task.
There are several ways you can choose to implement the HTTP client in the Spring Boot service. First of all you need to choose - will it be a synchronous or asynchronous client?
For example, if you have synchronous architecture you can choose one of solutions that are provided by Spring Boot.
In Spring Boot, a synchronous HTTP client is a component that is used to make HTTP requests to other services or endpoints, and blocks the current thread until the response is received. Spring Boot provides several options for implementing synchronous HTTP clients, including the RestTemplate
and WebClient
classes.
The RestTemplate
is a popular choice for implementing synchronous HTTP clients in Spring Boot. It provides a simple and intuitive API for making HTTP requests and handling responses, and supports a wide range of HTTP methods, request and response types, and message converters. To use RestTemplate
, you need to configure it as a bean in your application context, and then use it to make HTTP requests by calling its various methods.
There is example of usage RestTemplate for POST HTTP request:
public RegisterResponse registerUser(UserDto userDto) {
HttpEntity<UserDto> requestEntity = new HttpEntity<>(user, headers);
ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, requestEntity, RegisterResponse.class);
if (responseEntity.getStatusCode() == HttpStatus.OK) {
RegisterResponse response = responseEntity.getBody();
// handle the response
} else {
// handle the error
}
}
Another option for implementing synchronous HTTP clients in Spring Boot is to use the WebClient
class. WebClient
is a reactive HTTP client that provides a non-blocking API for making HTTP requests and handling responses, and is well-suited for applications that require high levels of concurrency or scalability. To use WebClient
, you need to configure it as a bean in your application context, and then use it to make HTTP requests by calling its various methods.
public RegisterResponse registerUser(UserDto userDto) {
Mono<String> responseMono = webClient.post()
.uri(endpointPath)
.contentType(MediaType.APPLICATION_JSON)
.body(Mono.just(user), UserDto.class)
.retrieve()
.bodyToMono(RegisterResponse.class);
responseMono.subscribe(response -> {
// handle the response
}, error -> {
// handle the error
});
}
It's important to note that using synchronous HTTP clients can block the current thread, which can have a negative impact on the overall performance and scalability of your application. As such, it's recommended to use asynchronous HTTP clients, such as WebClient
with reactive programming, when possible to improve application responsiveness and resource utilization.
Short answer - you can use Feign library. What is it?
Feign is a Java library that allows developers to create HTTP clients easily, specifically designed for building RESTful microservices. It provides a declarative way to define HTTP APIs that can be called from your code as if they were local method calls, making it easier to work with APIs and consume resources across different microservices.
With Feign, you can easily create interfaces that define the HTTP methods, request parameters, and response types for your RESTful endpoints. Then, Feign takes care of the rest, including the serialization and deserialization of requests and responses, URL encoding, error handling, and connection management.
Here's an example of a POST request for user registration using Feign:
// Client describes as interface with configuration:
@FeignClient(name = "exampleRegisterClient")
public interface RegisterClient {
@PostMapping("/register")
RegisterResponse registerUser(@RequestBody UserDto user);
}
// Bean creation in Spring configuration:
@Bean
public RegisterClient registerUserApi() {
return Feign.builder().target(RegisterClient.class, "https://localhost:9090/api);
}
Feign provides a simple and declarative way to interact with HTTP APIs, allowing developers to focus on the business logic of their microservices instead of the details of making HTTP requests.
In conclusion, Spring Boot provides multiple options for implementing HTTP clients in microservices, including RestTemplate, WebClient, and Feign. RestTemplate is a simple and widely-used client that provides synchronous HTTP communication. WebClient is a more modern and reactive alternative that provides non-blocking HTTP communication with a functional-style API. Feign is a declarative and type-safe client that generates code based on API definitions, providing an easy-to-use interface for RESTful microservices.
When choosing which HTTP client to use, it is important to consider the requirements of your microservice, such as performance, scalability, and ease-of-use. RestTemplate is a good choice for simple use cases that require synchronous communication. WebClient is a good choice for reactive and non-blocking use cases that require high performance and scalability. Feign is a good choice for declarative and type-safe use cases that require a simplified API and improved developer experience.
Regardless of which HTTP client you choose, it is important to write integration tests to ensure that your microservice behaves correctly when interacting with external services. By testing your HTTP clients, you can ensure that your microservice behaves as expected under different scenarios, such as network failures or unexpected responses from external services.
You can find my examples of implementing different ways of writing HTTP clients on my GitHub: https://github.com/v-aksenov
Photo by ThisisEngineering RAEng on Unsplash