27 Ağustos 2022 Cumartesi

SpringMVC RestTemplate Error Handling

Giriş
Açıklaması şöyle
By default, the RestTemplate will throw one of these exceptions in the case of an HTTP error:

HttpClientErrorException – in the case of HTTP status 4xx
HttpServerErrorException – in the case of HTTP status 5xx
UnknownHttpStatusCodeException – in the case of an unknown HTTP status
All of these exceptions are extensions of RestClientResponseException.
Şeklen şöyle


Bu exception'ların fırlatılmasını sağlayan sınıf DefaultResponseErrorHandler. Örneğin olmayan bir URL'ye GET gönderirsek şu sonucu alırız
Response body
{
  "timestamp": 1661608573837,
  "status": 500,
  "error": "Internal Server Error",
  "path": "/exchangerate"
}
Hatalı apiKey gönderirse şu sonucu alırız
{
  "timestamp": 1661632797098,
  "status": 500,
  "error": "Internal Server Error",
  "path": "/exchangerate"
}
Hatalı Json gönderirsek şu sonucu alırız. Yani fırlatılan exception ismi, ve exception mesajı da var.
{
 "timestamp": 1500597044204,
 "status": 400,
 "error": "Bad Request",
 "exception": "org.springframework.http.converter.HttpMessageNotReadableException",
 "message": "JSON parse error: Unrecognized token 'three': was expecting ('true', 'false' or 'null'); nested exception is com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'aaa': was expecting ('true', 'false' or 'null')\n at [Source: java.io.PushbackInputStream@cba7ebc; line: 4, column: 17]",
 "path": "/birds"
}
1. RestClientResponseException Sınıfı Yakalamak
Örnek - ResponseEntity 
Çıktıyı değiştirmek için bu exception'ı yakalayıp kendi istediğimiz bir ResponseEntity nesnesini dönmek gerekir. Şöyle yaparız
@ExceptionHandler(RestClientResponseException.class)
public ResponseEntity<String> restClientResponseExceptionHandler(
  RestClientResponseException exception) {

  return ResponseEntity.status(exception.getRawStatusCode())
    .body(exception.getResponseBodyAsString());
}
Hatalı apiKey gönderirse 401 alırız ve bu sefer çıktı şöyle olur
{"message":"Invalid authentication credentials"}
Örnek - Kendi Sınıfımız 
Elimizde şöyle bir kod olsun
@Data
public class ErrorResponse {

  int status;
  String message;
  String path;
}
Şöyle yaparız
@ExceptionHandler(RestClientResponseException.class)
public ResponseEntity<ErrorResponse> restClientResponseExceptionHandler(
  RestClientResponseException exception, 
  HttpServletRequest httpServletRequest ) {

  ErrorResponse errorResponse = new ErrorResponse();
  errorResponse.setStatus(exception.getRawStatusCode());
  errorResponse.setMessage(exception.getResponseBodyAsString());
  errorResponse.setPath(httpServletRequest.getRequestURI());
  return new ResponseEntity(errorResponse, 
                            HttpStatus.valueOf(exception.getRawStatusCode()));
}
401 alırız ve çıktı şöyledir
{
  "status": 401,
  "message": "{\"message\":\"Invalid authentication credentials\"}",
  "path": "/exchangerate"
}
2. Kendi Error Handler Sınıfımız
Burada amaç fırlatılan exception'nı değiştirmek. Önümüzde iki seçenek var
1. ResponseErrorHandler  arayüzünden kalıtmak
2. DefaultResponseErrorHandler sınıfından kalıtmak

Örnek - DefaultResponseErrorHandler Kalıtımı
Şöyle yaparız.
restTemplate.setErrorHandler(new DefaultResponseErrorHandler() {
  @Override
   public boolean hasError(ClientHttpResponse response)
    throws IOException {
    try {
      //Do your stuff
      return super.hasError(response);
    } catch (Exception e) {
      ...;
       return true;
    }
  }

  @Override
   public void handleError(ClientHttpResponse response)
    throws IOException {
    try {
      //Do your stuff
      super.handleError(response);
    } catch (Exception e) {
      ...
      throw e;
    }
  }
});


Hiç yorum yok:

Yorum Gönder