RestTemplate in Spring Boot: Synchronous Communication Between Microservices

RestTemplate in Spring Boot: Synchronous Communication Between Microservices

RestTemplate is one of the traditional ways to make HTTP calls between microservices in a Spring Boot application.

In a microservices architecture, different services usually run independently and communicate with each other through APIs. For example, an Order Service may need to call a Product Service to retrieve product information.

In this article, we will understand:

  • What synchronous communication means
  • How two Spring Boot microservices communicate
  • How to call REST APIs using plain Java
  • What RestTemplate is
  • How to configure RestTemplate
  • GET, POST, PUT and DELETE operations
  • exchange() method
  • execute() method
  • HTTP connection and keep-alive
  • Limitations of RestTemplate
  • Why newer Spring applications may use RestClient

1. What Is Synchronous Communication?

In synchronous communication, the client sends a request to the server and waits for the response before continuing.

For example:

OrderService  --->  ProductService
     |                  |
     |------ Request -->|
     |                  |
     |<----- Response --|

The calling thread waits until the response is received.

Therefore, synchronous communication is generally blocking in nature.

Some common synchronous HTTP communication approaches in Spring Boot include:

  • RestTemplate
  • RestClient
  • FeignClient

2. Example: Two Microservices

Let’s consider two Spring Boot microservices:

OrderService
Port: 8081

ProductService
Port: 8082

The requirement is simple:

OrderService
     |
     | HTTP Request
     ↓
ProductService
     |
     | HTTP Response
     ↓
OrderService

The ProductService exposes an endpoint such as:

GET http://localhost:8082/products/1

The OrderService will call this endpoint and consume the response.

The original setup uses two independent Spring Boot applications running on different ports.


3. ProductService

Let’s first create a simple Product Service.

@RestController
@RequestMapping("/products")
public class ProductController {

    @GetMapping("/{id}")
    public String getProduct(@PathVariable String id) {
        return "Product fetched with id: " + id;
    }
}

For example:

GET http://localhost:8082/products/101

Response:

Product fetched with id: 101

The example in the source document uses the same basic controller structure.


4. Calling REST API Using Plain Java

Before understanding RestTemplate, let’s see what is involved when we make an HTTP call using Java’s lower-level HttpURLConnection.

For example:

String url = "http://localhost:8082/products/" + id;

URL obj = new URL(url);

HttpURLConnection connection =
        (HttpURLConnection) obj.openConnection();

connection.setRequestMethod("GET");
connection.setRequestProperty("Accept", "application/json");

connection.setConnectTimeout(100);
connection.setReadTimeout(500);

BufferedReader in =
        new BufferedReader(
                new InputStreamReader(
                        connection.getInputStream()
                )
        );

StringBuilder response = new StringBuilder();

String responseLine;

while ((responseLine = in.readLine()) != null) {
    response.append(responseLine);
}

in.close();

System.out.println("Response: " + response);

There are several things that need to be handled manually:

  1. Opening the connection
  2. Setting the HTTP method
  3. Setting headers
  4. Configuring timeouts
  5. Reading the response
  6. Closing streams
  7. Handling exceptions
  8. Managing the connection lifecycle

The uploaded notes demonstrate this low-level approach and explain how HttpURLConnection works with the underlying TCP connection.


5. Why Do We Need RestTemplate?

Writing all the low-level HTTP communication code manually creates a lot of boilerplate.

For example, we have to manually handle:

Open connection
      ↓
Set headers
      ↓
Send request
      ↓
Read response
      ↓
Handle response
      ↓
Close streams
      ↓
Handle connection

The notes identify several disadvantages of this approach, including manually setting headers, reading responses, closing streams/connections, manually handling responses, and limited convenience around features such as connection pooling and interceptors.

This is where RestTemplate becomes useful.


6. What Is RestTemplate?

RestTemplate is a Spring class that simplifies communication with REST APIs.

Instead of manually creating an HttpURLConnection, reading streams and converting responses, we can write:

String response = restTemplate.getForObject(
        "http://localhost:8082/products/" + id,
        String.class
);

Much simpler!

The source describes RestTemplate as an abstraction over lower-level HTTP communication and as a traditional approach for calling REST APIs from Spring applications.


7. Creating a RestTemplate Bean

A common approach is to define RestTemplate as a Spring bean.

@Configuration
public class AppConfig {

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

Now Spring can inject this RestTemplate wherever it is required.


Configuring Timeouts

We can also configure connection and read timeouts.

@Configuration
public class AppConfig {

    @Bean
    public RestTemplate restTemplate() {

        SimpleClientHttpRequestFactory factory =
                new SimpleClientHttpRequestFactory();

        factory.setConnectTimeout(1000);
        factory.setReadTimeout(5000);

        return new RestTemplate(factory);
    }
}

The uploaded notes demonstrate both the simple configuration and a configuration using SimpleClientHttpRequestFactory for timeouts.


8. Using RestTemplate in OrderService

Now we can inject RestTemplate into our controller.

@RestController
@RequestMapping("/orders")
public class OrderController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/{id}")
    public ResponseEntity<String> getOrder(
            @PathVariable String id) {

        String response = restTemplate.getForObject(
                "http://localhost:8082/products/" + id,
                String.class
        );

        System.out.println(
                "Response from Product API: " + response
        );

        return ResponseEntity.ok("Order call successful");
    }
}

The flow is:

Client
  |
  | GET /orders/101
  ↓
OrderService
  |
  | RestTemplate
  | GET /products/101
  ↓
ProductService
  |
  | Response
  ↓
OrderService
  |
  | Response
  ↓
Client

The example in the uploaded document follows this same OrderService → ProductService flow using getForObject().


9. How Does getForObject() Work?

Consider:

String response = restTemplate.getForObject(
        "http://localhost:8082/products/" + id,
        String.class
);

Here:

URL

"http://localhost:8082/products/" + id

is the endpoint we want to call.

Response Type

String.class

tells RestTemplate that we expect the response to be converted into a String.

For example, if the API returns:

Product fetched with id: 101

then response contains that value.


10. RestTemplate and TCP Connection Reuse

One important point is that RestTemplate does not simply mean creating and explicitly closing a TCP connection for every call.

The source notes that after the response stream is closed, the underlying connection can be available for reuse depending on the configured connection/idle limits.

This is related to HTTP keep-alive.

With HTTP/1.1, persistent connections are used by default unless the connection is explicitly closed.

For example:

Client
   |
   | Request 1
   |------------------>
   |<------------------|
   |
   | Request 2
   |------------------>
   |<------------------|
   |
   | Same connection can potentially be reused

The uploaded notes also explain parameters such as idle timeout and maximum requests for a persistent connection.


11. Important RestTemplate Methods

RestTemplate provides different methods depending on what we need from the HTTP response.

GET – getForObject()

Product product = restTemplate.getForObject(
        url,
        Product.class
);

It returns the response body as an object.

For example:

Product product =
        restTemplate.getForObject(
                url,
                Product.class
        );

12. GET – getForEntity()

If we need the complete HTTP response, we can use:

ResponseEntity<Product> response =
        restTemplate.getForEntity(
                url,
                Product.class
        );

Then:

HttpStatus status = response.getStatusCode();

Product product = response.getBody();

The difference is:

getForObject()
       ↓
Response Body

getForEntity()
       ↓
Status + Headers + Body

This distinction is covered in the source’s RestTemplate method table.


13. POST Request

For creating a new resource, we can use postForObject().

Product newProduct =
        new Product("Ice-cream", 100);

Product createdProduct =
        restTemplate.postForObject(
                url,
                newProduct,
                Product.class
        );

This sends the POST request and returns the response body.

The source also shows postForEntity() when the complete ResponseEntity is required.


14. POST Using postForEntity()

Product newProduct =
        new Product("Ice-cream", 100);

ResponseEntity<Product> response =
        restTemplate.postForEntity(
                url,
                newProduct,
                Product.class
        );

Product createdProduct = response.getBody();

HttpStatus status = response.getStatusCode();

Use this when you need information such as:

  • HTTP status
  • Headers
  • Response body

15. PUT Request

For updating an existing resource:

Product updatedProduct =
        new Product("Ice-cream", 150);

restTemplate.put(
        url,
        updatedProduct
);

The put() method is intended for a PUT request where a response body is not expected.


16. DELETE Request

For deleting a resource:

restTemplate.delete(url);

Example:

String url =
        "http://localhost:8080/api/products/1";

restTemplate.delete(url);

The source describes delete() as sending a DELETE request where no response body is expected.


17. Using exchange() for More Control

Sometimes the simple methods aren’t enough.

For example, we may need to customize:

  • HTTP method
  • HTTP headers
  • Request body

In such cases, exchange() is useful.

HttpHeaders headers = new HttpHeaders();

headers.setContentType(
        MediaType.APPLICATION_JSON
);

headers.set(
        "Authorization",
        "Bearer my-token"
);

Product product = new Product();

product.setName("Ice-cream");
product.setPrice(100);

HttpEntity<Product> requestEntity =
        new HttpEntity<>(product, headers);

ResponseEntity<Product> response =
        restTemplate.exchange(
                url,
                HttpMethod.POST,
                requestEntity,
                Product.class
        );

Product result = response.getBody();

HttpStatus status = response.getStatusCode();

The uploaded notes use exchange() specifically to demonstrate customization of headers and the request body while retaining Spring’s automatic conversion capabilities.


18. execute() Method

When we need more control over the request and response processing, RestTemplate also provides:

execute()

Its structure is:

execute(
    String url,
    HttpMethod method,
    RequestCallback requestCallback,
    ResponseExtractor<T> responseExtractor
)

This provides lower-level control over request and response handling.


RequestCallback

RequestCallback allows us to customize the outgoing request.

For example:

RequestCallback requestCallback = request -> {

    request.getHeaders().setContentType(
            MediaType.APPLICATION_JSON
    );

    Product product =
            new Product("Ice-cream", 100);

    ObjectMapper mapper = new ObjectMapper();

    byte[] body =
            mapper.writeValueAsBytes(product);

    StreamUtils.copy(
            body,
            request.getBody()
    );
};

The source explains that RequestCallback provides control over the request, including headers and request body.


ResponseExtractor

ResponseExtractor controls how the response is read and converted.

Example:

ResponseExtractor<String> responseExtractor =
        response -> {

            return StreamUtils.copyToString(
                    response.getBody(),
                    StandardCharsets.UTF_8
            );
        };

Then:

String response = restTemplate.execute(
        url,
        HttpMethod.POST,
        requestCallback,
        responseExtractor
);

The source demonstrates ResponseExtractor for controlling response processing.


19. RestTemplate Method Cheat Sheet

HTTP Operation RestTemplate Method Purpose
GET getForObject() Get response body
GET getForEntity() Get status, headers and body
POST postForObject() POST and get response body
POST postForEntity() POST and get complete response
PUT put() Send PUT request
DELETE delete() Send DELETE request
Any HTTP method exchange() Customize method, headers and body
Advanced execute() More control over request/response

These methods and their intended use are summarized in the uploaded material.


20. Limitations of RestTemplate

Although RestTemplate is easy to use, it has some limitations.

1. Many overloaded methods

RestTemplate provides many methods and overloads, which can make the API harder to remember and maintain as requirements become more complex.

2. Older API design

RestTemplate comes from an older style of Spring HTTP client API, and modern requirements can require additional configuration or supporting components.

3. Maintenance mode

The source notes that RestTemplate is in maintenance mode, meaning development is focused on maintenance rather than introducing new features.


21. RestClient – The Modern Alternative

Modern Spring applications can also use RestClient, which provides a more fluent, builder-style API.

Instead of a large collection of overloaded methods, the API is designed around a more readable request-building style.

The uploaded notes highlight:

  • Fluent/builder-style API
  • More readable endpoint invocation
  • Easier integration with interceptors and filters

So, when starting a new Spring application, it is worth understanding both RestTemplate and RestClient, particularly if you are maintaining existing applications that already use RestTemplate.


22. RestTemplate vs RestClient

Feature RestTemplate RestClient
Communication Synchronous Synchronous
API style Traditional Fluent
Common in legacy applications Yes Less likely
Readability Method-based Builder-style
Existing project support Very common Increasingly relevant
Maintenance status Maintenance mode Modern Spring API

23. Complete Microservice Flow

Putting everything together:

                 HTTP GET
OrderService ------------------> ProductService
     |                                |
     |                                |
     |                         Process Request
     |                                |
     |<-------------------------------|
              Response

The OrderService doesn’t directly access the Product Service’s database.

Instead:

OrderService
     |
     | REST API
     ↓
ProductService
     |
     ↓
Product Database

This keeps the services separated and allows each service to expose its own API.


24. Final Takeaway

RestTemplate makes synchronous REST communication significantly simpler than directly working with low-level Java HTTP APIs.

With RestTemplate, we can easily perform:

GET
POST
PUT
DELETE

and use more flexible methods such as:

exchange()
execute()

For example:

String response = restTemplate.getForObject(
        "http://localhost:8082/products/101",
        String.class
);

is considerably simpler than manually managing HttpURLConnection.

However, for new Spring applications, developers should also understand the modern RestClient API, while RestTemplate remains important knowledge for maintaining existing Spring Boot applications.


Frequently Asked Questions

Is RestTemplate synchronous?

Yes. RestTemplate is used for synchronous HTTP communication, meaning the calling operation waits for the response.

Is RestTemplate still used?

Yes. It is still encountered frequently in existing Spring applications, although Spring’s newer RestClient API should also be considered for modern applications.

What is the difference between getForObject() and getForEntity()?

getForObject() returns the response body, while getForEntity() returns a ResponseEntity containing information such as the response status, headers and body.

When should I use exchange()?

Use exchange() when you need more control over the HTTP method, headers, request body and response type.

What is execute() used for?

execute() is useful when you need greater control over how the request is created and how the response is extracted.


Suggested SEO title

RestTemplate in Spring Boot: Complete Guide to Synchronous Microservice Communication

Suggested URL slug

/resttemplate-spring-boot-microservices/

Suggested meta description

Learn how to use RestTemplate in Spring Boot for synchronous microservice communication, including GET, POST, PUT, DELETE, exchange(), execute(), timeouts, and RestClient.

Suggested tags

Java, Spring Boot, RestTemplate, Microservices, REST API, Spring Framework, Java Microservices, RestClient, Backend Development

Leave a Reply