0

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.

enter image description here

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

Gianni Spear
  • 7,033
  • 22
  • 82
  • 131

0 Answers0