관리 메뉴

너와 나의 스토리

[SpringBoot] RestTemplate Custom Error Response 받기 / Custom Error Message 확인하기 본문

개발/Spring Boot

[SpringBoot] RestTemplate Custom Error Response 받기 / Custom Error Message 확인하기

노는게제일좋아! 2022. 6. 7. 00:10
반응형

Custom Error Response 보내는 방법

 

[Spring] @ControllerAdvice를 이용하여 exception handling - Custom Error Response 보내기 & message를 포함한 error res

Exception Handler Rest API로 받은 요청을 처리하다가 exception이 발생하는 경우가 있다. 이러한 exception들을 한 곳에서 처리하도록 ExceptionHandler를 만들어보자. @ControllerAdvice에 있는 메서드들은 모..

hororolol.tistory.com

  • RestTemplate에서 다음과 같은 custom response로 응답이 온다고 하자.

 

 

Response Error Handler 

public class ResponseErrorHandler extends DefaultResponseErrorHandler {

    private List<HttpMessageConverter<?>> messageConverters = Arrays.asList(new MappingJackson2HttpMessageConverter());

    @Override
    public void handleError(ClientHttpResponse response) throws IOException {
        try {
            super.handleError(response);
        } catch (HttpStatusCodeException e) {
            System.out.println("Error response body is " + e.getResponseBodyAsString());
            throw e;
        }
    }
}
  • 다음처럼 error handler 정의 후, RestTemplate에 set해주면 해당 resttemplate으로 들어오는 모든 에러가 위의 handleError()로 들어오게 된다.
restTemplate.setErrorHandler(new ResponseErrorHandler());
  • print된 response
    • Error response body is {"message":"manual not available exception","code":"PRECONDITION_FAILED","timestamp":"2022-06-06T01:51:23.838","status":412}
  • Custom Error Response 객체로 받기
    • HttpStatusCodeException으로부터 값을 받아 parsing
    • ObjectMapper로 parsing
public class ResponseErrorHandler extends DefaultResponseErrorHandler {

    @Override
    public void handleError(ClientHttpResponse response) throws IOException {
        try {
            super.handleError(response);
        } catch (HttpStatusCodeException e) {
            ErrorResponse error = parse(e.getResponseBodyAsString(), ErrorResponse.class);
            if (error.code == HttpStatus.PRECONDITION_FAILED) {
                handlePreconditionFailed(error.message);
            } else if (error.code == HttpStatus.NOT_IMPLEMENTED) {
                throw new CustomException3(error.message);
            }
            throw new CustomException4(error.message);
        }
    }

    private void handlePreconditionFailed(String message) {
        if (message.contains("Message 1")) {
            throw new CustomException1(message);
        } else if (message.contains("Message 2")) {
            throw new CustomException2(message);
        }
        throw new CustomException3(message);
    }

    @Getter
    @JsonIgnoreProperties(ignoreUnknown = true)
    static class ErrorResponse {
        private LocalDateTime timestamp;
        private String message;
        private HttpStatus code;
        private int status;
    }
}
  • Parsing
    • Custom response에 timestamp가 포함되는 경우 그냥 mapper.readValue()하게 되면 에러가 발생할 것이다.
    • string 형식의 timestamp를 deserializing하는데 에러가 발생한 것으로 다음과 같이 설정해 주면 문제 해결!
public class PayloadParser {

    private static ObjectMapper mapper;

    static {
        mapper = new ObjectMapper();
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        mapper.registerModule(new JavaTimeModule()
                .addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("M/d/yyyy"))));
    }

    public static <T> T parse(String payload, Class<T> valueType) {
        try {
            return mapper.readValue(payload, valueType);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            throw new InvalidPayloadException("Invalid payload form");
        }
    }

}
반응형
Comments