본문 바로가기

Programing/Framework

[Spring] RestClientException 예외 정리

RestTemplate 은 Retire되었다. WebClient가 계승할 예정이다.

하지만 아직 많은 곳에 RestTemplate를 쓰고 있어서 정리를 하게 되었다.

 

계층도

빨간선 아래가 스프링의 예외 클래스들이다.

  • NestedRuntimeException: RuntimeException의 root cause를 다루기 쉽게 래핑한 예외 클래스
    • 내부적으로는 NestedExceptionUtils 라는 유틸리티 클래스를 이용한다.
  • RestClientException: 클라이언트 사이드의 HTTP 에러를 만났을 때 던져지는 기본 예외 클래스
  • RestClientResponseException: 실제 HTTP 응답 데이터를 포함하고 있는 예외클래스들의 공통 기반 클래스
    • int rawStatusCode
    • String statusText
    • byte[] responseBody: getResponseBodyAsString() 메서드로 읽어올 수 있다.
    • HttpHeaders responseHeaders
    • String responseCharset
  • ResourceAccessException: I/O를 하는 도중 에러가 발생했을 때 던져진다.
  • HttpStatusCodeException: HttpStatus (enum)를 기반으로 하여 만든 추상 클래스(RestClientResponseException의 경우 int 타입의 rawStatusCode를 가지고 있다.)
    • getStatusCode() 메서드를 통해 HttpStatus를 읽어올 수 있다.
    • 직접쓰기 보다는 상속받은 아래 두 클래스를 사용한다.
      • HttpClientErrorException : 4xx 대 응답을 받았을 때 던져지는 예외
      • HttpServerErrorException: 5xx 대 응답을 받았을 때 던져지는 예외
  • UnknownHttpStatusCodeException: HTTP 응답 코드가 허용 범위를 넘어섰을 경우 던져진다.
    • 499 (Nginx) ...

HttpClientErrorException vs HttpServerErrorException

DefaultResponseErrorHandler의 handleError 메서드를 보면 쉽게 이해 할 수 있다.

protected void handleError(ClientHttpResponse response, HttpStatus statusCode) throws IOException {
	switch (statusCode.series()) {
		case CLIENT_ERROR:
			throw new HttpClientErrorException(statusCode, response.getStatusText(),
					response.getHeaders(), getResponseBody(response), getCharset(response));
		case SERVER_ERROR:
			throw new HttpServerErrorException(statusCode, response.getStatusText(),
					response.getHeaders(), getResponseBody(response), getCharset(response));
		default:
			throw new UnknownHttpStatusCodeException(statusCode.value(), response.getStatusText(),
					response.getHeaders(), getResponseBody(response), getCharset(response));
	}
}

UnknownHttpStatusCodeException

 

int rawStatusCode -> org.springframework.http.HttpStatus 변환시 적절한 값이 없을 경우

org.springframework.web.client.UnknownHttpStatusCodeException 를 발생시키는 것이 적절해 보인다.

실제 DefaultResponseErrorHandler의 handleError 메서드에서 HttpStatus.resolve 를 통해 변환을 했을 때 null (변환을 못했을)일 경우 이 예외를 반환시키고 있다.

@Override
public void handleError(ClientHttpResponse response) throws IOException {
	HttpStatus statusCode = HttpStatus.resolve(response.getRawStatusCode());
	if (statusCode == null) {
		throw new UnknownHttpStatusCodeException(response.getRawStatusCode(), response.getStatusText(),
				response.getHeaders(), getResponseBody(response), getCharset(response));
	}
	handleError(response, statusCode);
}