MIGRATE FROM
RESTTEMPLATE TO
RESTCLIENT SPRING BOOT
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:
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:
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
@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
@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: