Using Rest Template for Microservices Communication | SpringBoot
In this article we will learnt to make Http call using RestTemplate from one microservice to another microservice api and consume data.
We have 3 microservices for our Hotel Rating Application →
UserService - localhost:8081/users
HotelService - localhost:8082/hotels
RatingService - localhost:8083/ratings
We already have setup our Discover server and above 3 microservices and Discovery Client for out Hotel Rating Application. Check out these articles for recap -
Implementing Discovery Server in SpringBoot | Service Discovery | Microservices
Implementing Service Discovery Client in SpringBoot | Microservices
To achieve microservices communication we will make call from UserService to RatingService microservice api to get list of rating for a particular user using the user id of that user. This is how our microservices will communicate.
Step 1 → Creating a RestTemplate Bean. There are two ways to do this (Use either A or B) -
- ( A ) Declare the bean inside the main method of our Application class.
package com.movie_rating.user.service;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.web.client.RestTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
@EnableDiscoveryClient
@SpringBootApplication
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
@Bean
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
- ( B ) Create the bean inside the config class.
package com.movie_rating.user.service.config;
import org.springframework.web.client.RestTemplate;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Bean;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
@Configuration
public class AppConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplateBean() {
return new RestTemplate();
}
}
Here @LoadBalanced annotation does a few important things for us. It enables Load Balancing for our application in case multiple instances of a microservices are running. Also it allows us to not hard code the Api url when we make call to Api through RestTemplate.
So, “http://localhost:8083/ratings/users/{userID}“ becomes “http://RATINGSERVICE/ratings/users/{userId}”. We don’t need to mention the hostname and port number in our Api url when we make call to Api through RestTemplate, both hostname and port number are replaced with name of the microservice (The name should be same as that appears on Discovery Server under the Applications column).
This also gives us the flexibility to run our microservices to run on any hostname or port number because we don’t need to specify then in the url anymore, since the url isn’t hardcoded.
Step 2 → Autowire the RestTemplate bean and use it to make call to the RatingService Api (http://RATINGSERVICE/ratings/users/{userId}) -
package com.movie_rating.user.service.controllers;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import com.movie_rating.user.service.entities.Rating;
import com.movie_rating.user.service.entities.UserEntity;
import com.movie_rating.user.service.services.UserService;
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@Autowired
private RestTemplate restTemplate;
@PostMapping
public ResponseEntity<UserEntity> createtUser (@RequestBody UserEntity user){
UserEntity tempUser = userService.saveUSer(user);
return ResponseEntity.status(HttpStatus.CREATED).body(tempUser);
}
@GetMapping("{userId}")
public ResponseEntity<UserEntity> getUser (@PathVariable String userId){
UserEntity tempUser = userService.getUser(userId);
ArrayList<Rating> ratings = restTemplate.getForObject("http://RATINGSERVICE/ratings/users/"+userId, ArrayList.class);
tempUser.setRatings(ratings);
return ResponseEntity.ok(tempUser);
}
@GetMapping
public ResponseEntity<List<UserEntity>> getAllUser (){
List<UserEntity> allUser = userService.getAllUser();
return ResponseEntity.ok(allUser);
}
}
Subscribe to my newsletter
Read articles from Prashant Katare directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Prashant Katare
Prashant Katare
Experienced Spring Boot Developer with over 3+ years of expertise in developing scalable and high-performance web applications and microservices. Proficient in Java and Spring Boot frameworks, with hands- on experience in RESTful APIs and Microservices architecture. Adept at building secure, database-driven applications and integrating various third- party services. Strong problem-solving skills with a focus on delivering clean, maintainable, and efficient code.