I wrote a Service in Spring Boot that executes the getForObject(URI url, Class<T> responseType)
method. I implemented a dedicated RestTemplate, the restTemplateWithErrorHandler, to handle any errors:
@Configuration
public class RestTemplateWithErrorHandlerConfig {
@Bean
public RestTemplate restTemplateWithErrorHandler() {
return new RestTemplateBuilder()
.errorHandler(new RestTemplateResponseErrorHandler())
.build();
}
}
where:
public class RestTemplateResponseErrorHandler implements ResponseErrorHandler {
@Override
public boolean hasError(ClientHttpResponse clientHttpResponse)
throws IOException {
return clientHttpResponse.getStatusCode().is4xxClientError()
|| clientHttpResponse.getStatusCode().is5xxServerError();
}
@Override
public void handleError(ClientHttpResponse response) throws IOException {
}
@Override
public void handleError(
URI url,
HttpMethod method,
ClientHttpResponse clientHttpResponse
) throws IOException {
HttpStatusCode statusCode = clientHttpResponse.getStatusCode();
if (statusCode.isSameCodeAs(HttpStatus.SERVICE_UNAVAILABLE)) {
throw new RestTemplateException(statusCode, "Service Unavailable");
}
if (statusCode.isSameCodeAs(HttpStatus.INTERNAL_SERVER_ERROR)) {
throw new RestTemplateException(statusCode, "Internal Server Error");
}
if (statusCode.isSameCodeAs(HttpStatus.UNAUTHORIZED)) {
throw new RestTemplateException(statusCode, "Unauthorized access");
}
if (statusCode.isSameCodeAs(HttpStatus.BAD_REQUEST)) {
throw new RestTemplateException(statusCode, "Bad Request");
}
if (statusCode.isSameCodeAs(HttpStatus.NOT_FOUND)) {
throw new RestTemplateException(statusCode, "Not Found");
}
throw new RestTemplateException(statusCode, "Unknown status code");
}
}
and
public class RestTemplateException extends RuntimeException {
private HttpStatusCode statusCode;
private String error;
public RestTemplateException(HttpStatusCode statusCode, String error) {
super(error);
this.statusCode = statusCode;
this.error = error;
}
public HttpStatusCode getStatusCode() {
return statusCode;
}
public String getError() {
return error;
}
public void setStatusCode(HttpStatusCode statusCode) {
this.statusCode = statusCode;
}
public void setError(String error) {
this.error = error;
}
}
So when an error occurs, I can return a response that illustrates to the client, in a neat way, that an error has occurred in the service case.
However, there are cases where the request succeeds on the third-party API but returns a responseType that is not the one in (i.e., EnsembleForecastResponseDTO.class
):
public EnsembleForecastResponseDTO callResponse(
EnsembleForecastRequestDTO requestDTO
){
String url = OpenMeteoUrlEncoder
.getQuery(requestDTO);
return restTemplateWithErrorHandler
.getForObject(
url,
EnsembleForecastResponseDTO.class);
}
The call to the service returns an error JSON, developed by the third-party API of the type:
// 20230626132612
// https://climate-api.open-meteo.com/v1/climate?latitude=52.52&longitude=13.41&start_date=1750-01-01&end_date=2050-11-23&daily=temperature_2m_mean&models=CMCC_CM2_VHR4,FGOALS_f3_H,HiRAM_SIT_HR,MRI_AGCM3_2_S,EC_Earth3P_HR,MPI_ESM1_2_XR,NICAM16_8S
{
"reason": "Invalid date",
"error": true
}
My question is whether it is possible to handle this by extracting the error message (i.e. Invalid date
) issued by the third party and pass it to my client