javaspring-bootmicroservicesspring-cloudspring-cloud-feign

Handling feign exception in Spring boot using RestControllerAdvice


I have some Fiegn client to send request other springboot micro service.

 @ExceptionHandler(FeignException.class)
    public ResponseEntity<ApiError> handleFeignException(FeignException ex, WebRequest webRequest) throws JsonProcessingException {
           try{
            ObjectMapper objectMapper = JsonMapper.builder()
                    .findAndAddModules()
                    .build();
            ApiError apiError = objectMapper.readValue(ex.contentUTF8(), ApiError.class);
               return new ResponseEntity<>(apiError, HttpStatusCode.valueOf(ex.status()));
    
        } catch (JsonProcessingException e) {
            log.error("Error deserializing Feign exception: {}", e.getMessage());
            ApiError fallbackError = new ApiError("Error deserializing Feign exception", LocalDate.now(), ex.status(), webRequest.getDescription(false));
            return ResponseEntity.status(HttpStatusCode.valueOf(ex.status()))
                    .body(fallbackError);
        }
    }
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
public class ApiError {
    private String message;
    private LocalDate timeStamp;
    private int status;
    private String requestPath;
}

So I am handling feign exception thrown by feign client during inter service communication between spring boot micro services this way.... Is there any other good approach or am i doing it the correct way


Solution

  • What you have is another way to handle exception, but what I could suggest you is to have custom ErrorDecoder according to Custom-error-handling on the wiki page of OpenFeign.

    As an example:

    public class CustomErrorDecoder implements ErrorDecoder {
    
        @Override
        public Exception decode(String methodKey, Response response) {
            if (response.status() >= 400 && response.status() <= 499) {
                return new StashClientException(
                        response.status(),
                        response.reason()
                );
            }
            if (response.status() >= 500 && response.status() <= 599) {
                return new StashServerException(
                        response.status(),
                        response.reason()
                );
            }
            return errorStatus(methodKey, response);
        }
    }
    

    After declaring it create a configuration class, Beside of ErrorDecoder you could also declare: custom filters, interceptors in this class.

    @Configuration
    public class MyFeignClientConfiguration {
    
        @Bean
        public ErrorDecoder errorDecoder() {
            return new CustomErrorDecoder();
        }
    }
    

    And in the Feign Interface you will have:

    @FeignClient(
        value = "myFeignClient", 
        configuration = MyFeignClientConfiguration.class
    )