Tutorial OCT 07, 2025 • 04 MIN READ

MIGRATE FROM
RESTTEMPLATE TO
RESTCLIENT SPRING BOOT

Abstract technical background

Saying Goodbye to RestTemplate — and Why RestClient Deserves Your Attention.

So, why we have to migrate RestTemplate to RestClient?

In Spring Boot 3.2+, there are now two main HTTP clients you can use

  • check_circle RestTemplate (the old one)
  • check_circle RestClient (the new one introduced in Spring Boot 3.2)

RestTemplate

Status: Legacy / Deprecated for new code

Overview:

  • check_circle Has been around since Spring Boot 1.0 (very old).
  • check_circle Synchronous (blocking) HTTP client.
  • check_circle Uses the traditional RestTemplateBuilder to configure.
  • check_circle Works fine but not as flexible and extensible as modern clients.

Example:

RestExample.java JAVA
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject("https://api.example.com/data", String.class);

Notes:

  • check_circle Officially in maintenance mode: no new features will be added.
  • check_circle Still safe to use in existing projects.
  • check_circle Based on the older HttpURLConnection or Apache HttpClient under the hood.

RestClient

Status: New and recommended replacement

Overview:

  • check_circle Introduced in Spring Boot 3.2.
  • check_circle Modern fluent API, inspired by both RestTemplate and WebClient.
  • check_circle Still blocking (synchronous), but easier to use and extend.
  • check_circle Integrates better with Spring Boot’s auto-configuration.
  • check_circle Can use the same underlying HTTP libraries as WebClient.

Example:

RestExample.java JAVA
RestClient restClient = RestClient.builder()
    .baseUrl("https://api.example.com")
    .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
    .build();

Implementation

I have simple service, Space Service

We will try with RestClient for real this time. Linking My Service A to Service B (Space Service) and seeing how clean the integration feels.

First, create config builder for RestClient, create class RestClientConfig

RestClientConfig.java JAVA
@Configuration
public class RestClientConfig {
  @Value("${url.space.service}")
  private String urlSpaceService;

  @Bean
  public RestClient restClient(RestClient.Builder builder) {
    return builder
      .baseUrl(urlSpaceService)
      .defaultHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE)
      .build();
  }
}

Then create class RestService

RestService.java JAVA
@Slf4j
@Service
public class RestService {
  private final RestClient restClient;

  public RestService(RestClient restClient) {
    this.restClient = restClient;
  }

  public String displayResult(Metadata metadata, String type) {
    log.info("Start display rectangle: " + type);
    String result = "";
    try {
      result = restClient.get()
        .uri(uriBuilder -> uriBuilder
          .path("/v1/astronout/display")
          .queryParam("type", type)
          .build()
        )
        .retrieve()
        .body(String.class);
    } catch (Exception e) {
      log.error("Error when display result: " + e.getMessage());
      throw new RestException(ERROR_MESSAGE_SYSTEM_ERROR, RC_CODE_SYSTEM_ERROR, ERROR_DESCRIPTION_SYSTEM_ERROR);
    }
    return result;
  }

  public ResponseEntity<ApiBaseResponse<PageAsteroidRes>> getListAsteroid(Metadata metadata, int page, int size) {
    log.info("Start get list asteroid");
    PageAsteroidRes response = null;
    ParameterizedTypeReference<ApiBaseResponse<PageAsteroidRes>> paramResult = new ParameterizedTypeReference<>() {};
    try {
      ResponseEntity<ApiBaseResponse<PageAsteroidRes>> res = restClient.get()
        .uri(uriBuilder -> uriBuilder.path("/v1/asteroid/list")
          .queryParam("page", page)
          .queryParam("size", size)
          .build())
        .retrieve()
        .toEntity(paramResult);

      response = res.getBody().getData();
    } catch (Exception e) {
      log.error("Error when get list asteroid: " + e.getMessage());
      throw new RestException(ERROR_MESSAGE_SYSTEM_ERROR, RC_CODE_SYSTEM_ERROR, ERROR_DESCRIPTION_SYSTEM_ERROR);
    }
    return ResponseUtil.buildHttpResponse(ResponseUtil.buildResponse(RC_CODE_SUCCESS, ERROR_MESSAGE_SUCCESS, response));
  }
}

Testing

Run Space Service, then run our Rest Service.
Hit with postman.

API: Display Result
URL: http://localhost:8006/rest/v1/display?type=NORMAL
Method: GET
Response:
1
1 2
1 2 3
1 2 3 4
1 2 3 4 5

That's it. You can find source code here: https://github.com/pandz3rd/rest-client-service

Reference:

https://medium.com/@rakesh.mali/restclient-vs-webclient-vs-resttemplate-a-comprehensive-guide-6b150df476dd

READ BEYOND THE VOID

Technical blueprint background
Backend Notes

String vs StringBuilder vs StringBuffer

In a Spring Boot app, I used String everywhere...

Read Entry
Abstract digital network
Backend Notes

Update Id Sequence to Highest

My notes how to update Id Sequence in Posgresql...

Read Entry
Circuit board macro
Backend Notes

Difference between throw and throws and parent class of exceptions

I still remember the moment I realized I had been “half understanding” Java exception...

Read Entry