Hello!
In our last lesson, we successfully refactored a monolithic application into separate, independent microservices for Company, Job, and Review. While this independence is a core tenet of microservice architecture, it also introduces a challenge: our services are now isolated. For example, our Job service holds a companyId, but it has no way to retrieve the actual details of the corresponding company.
Today, we'll bridge that gap by exploring inter-service communication. This lesson focuses on the first and most straightforward method in the Spring ecosystem: using RestTemplate to make synchronous, blocking HTTP calls between services. We will learn how to make our Job service communicate with our Company service to fetch the data it needs.
1. Inter-Service Communication and RestTemplate
In a microservice architecture, services need to talk to each other to fulfill business requests. This communication can happen in two primary ways: synchronously (the caller waits for a response) or asynchronously (the caller sends a message and moves on).
RestTemplate is Spring's primary tool for synchronous communication. It's a client that simplifies the process of making HTTP requests to external REST APIs.
To understand the context and fundamentals of RestTemplate, let's start with a short video.
Inter-service Communication using RestTemplate | Spring Boot REST API to Microservices | Video #8
This video from EmbarkX introduces the concept of inter-service communication and explains the role of RestTemplate within the Spring framework.
Watch from 02:05 to 11:35. Pay attention to the distinction between synchronous and asynchronous communication and the key features of RestTemplate, such as its blocking nature and abstraction over low-level HTTP details.
As the video explained, RestTemplate is a powerful abstraction. It handles the details of making HTTP requests and, crucially, can automatically convert the JSON or XML response from an API into a Java object (a POJO).
From a system design perspective, it's useful to see where RestTemplate fits.

2. Making a Synchronous Call with RestTemplate
Let's put this into practice. We'll continue with the microservices we defined in the previous lesson. Our goal is to make the Job service call the Company service's GET /companies/{id} endpoint to retrieve details for a job posting.
The following video demonstrates exactly this scenario. It shows the initial, most direct way to implement this call.
Inter-service Communication using RestTemplate | Spring Boot REST API to Microservices | Video #8
Continuing with the same project from our last lesson, this segment shows the hands-on implementation of a RestTemplate call from the Job service to the Company service.
Watch from 11:35 to 20:23. The key steps are: creating a RestTemplate instance, using the getForObject() method, and defining a local POJO to map the response.
Let's break down the process shown in the video.
Key Implementation Steps:
-
Instantiate
RestTemplate:
ARestTemplateobject is created.RestTemplate restTemplate = new RestTemplate(); -
Define the Target URL:
The full URL of the endpoint you want to call is specified. For now, this is hardcoded."http://localhost:8081/companies/1" -
Define a Local POJO:
TheJobmicroservice needs a Java class that mirrors the structure of the JSON response from theCompanyservice. This is a critical point: thisCompanyclass is not a JPA entity. It's a simple Plain Old Java Object (POJO) used for data transfer. You'll often see these referred to as Data Transfer Objects (DTOs), which we'll cover more formally later.// In Job microservice public class Company { private Long id; private String name; private String description; // getters and setters... } -
Make the Call with
getForObject():
ThegetForObject()method makes a GET request and automatically deserializes the response body into an object of the specified class.// The URL of the company service endpoint String companyServiceUrl = "http://localhost:8081/companies/1"; // Make the call Company company = restTemplate.getForObject(companyServiceUrl, Company.class); // Now you can use the company object System.out.println(company.getName());
This flow is visualized well in the following diagram, where one Spring Boot service uses RestTemplate to consume an endpoint from another.

3. A Better Way: Managing RestTemplate as a Spring Bean
The implementation we just saw works, but it has a significant drawback. Creating new RestTemplate() inside a service method for every request is inefficient. It creates unnecessary objects and misses out on the power of Spring's dependency injection container.
The standard and recommended practice is to create a single, shared instance of RestTemplate and manage it as a Spring bean.
12 Using a Bean to create RestTemplate instance - Spring Boot Microservices Level 1
The channel Java Brains provides a clear rationale for why creating RestTemplate as a bean is superior and demonstrates how to do it.
First, watch from 00:45 to 01:15 to understand the problem with the 'new' keyword. Then, watch from 01:15 to 04:14 to see the solution: defining a @Bean in a configuration class and injecting it with @Autowired.
The Recommended Approach:
-
Create a Configuration Class:
Create a new class and annotate it with@Configuration. This tells Spring that the class contains bean definitions.@Configuration public class AppConfig { // Bean definitions go here } -
Define the
RestTemplateBean:
Inside your configuration class, create a method that returns aRestTemplateinstance and annotate it with@Bean. Spring will execute this method once at startup and manage the returned object as a singleton bean.@Configuration public class AppConfig { @Bean public RestTemplate restTemplate() { return new RestTemplate(); } } -
Inject the Bean:
Now, in any service class where you need to make an HTTP call, you can simply ask Spring to inject theRestTemplatebean using constructor injection. This is the dependency injection pattern in action.@Service public class JobServiceImpl implements JobService { private final RestTemplate restTemplate; // Use @Autowired on the constructor for dependency injection @Autowired public JobServiceImpl(RestTemplate restTemplate) { this.restTemplate = restTemplate; } @Override public Job getJobById(Long id) { // ... find job from repository ... // Use the injected RestTemplate instance String companyServiceUrl = "http://localhost:8081/companies/" + job.getCompanyId(); Company company = restTemplate.getForObject(companyServiceUrl, Company.class); // ... combine job and company info ... return job; } }
This approach is more efficient, aligns with Spring's design philosophy, and makes your code easier to test and configure.
4. RestTemplate Methods and Configuration
RestTemplate offers a family of methods for different use cases. While we focused on getForObject(), it's good to be aware of the others.
Complete Guide to Spring RestTemplate
The article 'Complete Guide to Spring RestTemplate' from Reflectoring provides a great summary of the most common methods.
Read the section titled 'Some Useful Methods of RestTemplate'. This provides a concise overview of methods like getForEntity, postForObject, and the versatile exchange.
A key takeaway from that reading is the difference between getForObject() and getForEntity().
getForObject(): Returns just the response body, mapped to your POJO. Simple and direct.getForEntity(): Returns aResponseEntityobject, which wraps the response body and includes HTTP metadata like status codes and headers. This is useful when you need to programmatically check if the call was successful (e.g., status 200 OK) before processing the body.
Finally, in a production system, it's critical to configure timeouts for synchronous calls. A call to another service might hang, and you don't want your calling service to be blocked indefinitely, which can cause cascading failures. RestTemplate can be configured with connection and read timeouts. The Reflectoring article you just looked at covers this in the section "Configuring the HTTP Client in RestTemplate" if you wish to explore further.
Conclusion
In this lesson, we established our first communication channel between microservices. We learned how to use RestTemplate to make synchronous, blocking calls, enabling our Job service to enrich its data with information from the Company service.
Key Takeaways:
RestTemplateis Spring's synchronous REST client, abstracting away low-level HTTP details.- The
getForObject()method makes a GET request and maps the JSON response directly to a Java POJO. - The calling service needs a local POJO (or DTO) to represent the data it expects to receive.
- Best Practice:
RestTemplateshould be defined as a singleton@Beanin a@Configurationclass and injected where needed, rather than being instantiated withnewfor each use. - Synchronous calls are inherently blocking. This is a simple model but can have performance and resilience implications in a large-scale distributed system.
The blocking nature of RestTemplate is its most significant characteristic and limitation. What if we could make a request without waiting, freeing up the thread to do other work until the response arrives? In our next lesson, we will explore exactly that by learning about WebClient, Spring's modern, non-blocking, and asynchronous client for making HTTP calls.