Feign exception handling in Spring Cloud

Carvia Tech | December 03, 2019 | 2 min read | 1,845 views

Feign is a declarative web service client for inter-service communicate. It is quite similar to retrofit that is used as a web service client in android.


Feign is a Java to HTTP client binder inspired by Retrofit, JAXRS-2.0, and WebSocket. Feign’s first goal was reducing the complexity of binding Denominator uniformly to HTTP APIs regardless of ReSTfulness.

Why Feign and not Retrofit (with Spring Cloud)

There are few reasons to prefer Feign as the web service clients over Retrofit when used with Spring Cloud.

  1. Spring Cloud integrates Ribbon and Eureka to provide a load-balanced HTTP client when using Feign. These essential inter-service features are not supported in Retrofit. So any Feign client in Spring Cloud environment will be aware of available instances for a given service and we need not provide it with Host/Port/Protocol for any service as Eureka discovery client will take care of this. In-case of Retrofit, we will have to hard-code the things thereby losing all the flexibility of cloud-native application.

  2. Spring MVC annotations support is added to Feign client by Spring Cloud. So we need not learn any new syntax for using Feign.

  3. The default Spring Web HttpMessageConverters are configured to use with Feign out of the box when used with Spring Cloud.

Exception handling issues

OpenFeign’s FeignException doesn’t bind to a specific HTTP status (i.e. doesn’t use Spring’s @ResponseStatus annotation), which makes Spring default to 500 whenever faced with a FeignException.

Sample response when FeignException occurs
    "timestamp": "2019-07-28T08:53:12.168+0000",
    "status": 500,
    "error": "Internal Server Error",
    "message": "status 400 reading client#sendMessage(MessagePayload)",
    "path": "/send-notification"

That’s because the root cause for FeignException may not be even related to Http status code sent by remote web service.

In order to propagate the actual error message to the client, we can write our custom ExceptionHandler using a ControllerAdvice.

import feign.FeignException;
import org.json.JSONObject;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletResponse;
import java.util.Collections;
import java.util.Map;

public class FeignExceptionHandler {

    @ExceptionHandler(FeignException.BadRequest.class)  (1)
    public Map<String, Object> handleFeignStatusException(FeignException e, HttpServletResponse response) {
        return new JSONObject(e.contentUTF8()).toMap(); (2)

1 Handling FeignException for BadRequests only. We can write similar ExceptionHandlers for other types of exceptions.
2 We are assuming here that remote web service returns a JSON response for error messages

After we add this ExceptionHandler, we will be able to see custom exception response with additional details from remote web service.

Propagating actual error message to the caller from remote web service
    "exception": "org.springframework.web.bind.MethodArgumentNotValidException",
    "path": "/api/message/notification/",
    "error_code": 2151,
    "message": "Target id not valid",
    "status": 400,
    "timestamp": 1564304731547

Top articles in this category:
  1. HTTP logging & connection timeout in Feign Clients with Spring Boot
  2. Feign common headers using RequestInterceptor
  3. Retrofit vs Feign for Server Side
  4. Creating AWS Lambda in Java using Spring Cloud Function
  5. Creating AWS Lambda in Kotlin using Spring Cloud Function
  6. Integrating non-JVM apps into Spring Cloud using Sidecar approach
  7. How will you handle unresolved circular dependency in spring dependency injection?

Find more on this topic:
Spring Framework image
Spring Framework

Spring Framework - MVC, Dependency Injection, Spring Hibernate, Spring Data JPA, Spring Boot and Spring Cloud for Microservices Architecture.

Last updated 1 week ago

Recommended books for interview preparation:

This website uses cookies to ensure you get the best experience on our website. more info