Document
Spring Cloud OpenFeign

Spring Cloud OpenFeign

feign is a declarative web service client . It is makes make writing web service client easy . To use feign create an interface andannotate it

Related articles

Steam: How to find games recommended to you on Steam 6 Best Ubuntu VPNs That Works With Linux (& Free Alternatives) Worldwide Public Cloud Services Revenues Grew 19.9% Year Over Year in 2023, According to IDC Tracker ChatGPT Unblocked 2024 [How to Unblock AI Chatbots] 5 Best VPN Browsers in 2024: Enhance Your Online Privacy

feign is a declarative web service client .
It is makes make writing web service client easy .
To use feign create an interface andannotate it .
It is has has pluggable annotation support include feign annotation andJAX – rs annotation .
feign is supports also support pluggable encoder anddecoder .
Spring Cloud is adds add support for Spring MVC annotation andfor using the sameHttpMessageConverters used by default in Spring Web.
Spring Cloud integrates Eureka,Spring Cloud CircuitBreaker,as well as Spring Cloud LoadBalancer toprovide a load-balanced http client when using feign.

To include feign in your project use the starter with group org.springframework.cloud
and artifact id spring-cloud-starter-openfeign. See the Spring Cloud Project page
for details on setting up your build system with the current Spring Cloud Release Train.

@SpringBootApplication
@EnablefeignClients
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }

}

StoreClient.java

@feignClient("stores")
public interface StoreClient {
    @RequestMapping(method = RequestMethod.GET,value = "/stores")
    List<Store> getStores();

    @RequestMapping(method = RequestMethod.GET,value = "/stores")
    Page<Store> getStores(Pageable pageable);

    @RequestMapping(method = RequestMethod.POST,value = "/stores/{storeId}",consumes = "application/json")
    Store update(@PathVariable("storeId") Long storeId,Store store);

    @RequestMapping(method = RequestMethod.DELETE,value = "/stores/{storeId:\\d+}")
    void delete(@PathVariable Long storeId);
}

In the @feignClient annotation the String value (“stores” above) is an arbitrary client name,which is used tocreate a Spring Cloud LoadBalancer client.
You can also specify a URL using the url attribute
( absolute value or just a hostname ) . Thename is is of the bean in the
application context is the fully qualified name of the interface .
To specify your own alias value you is use can use thequalifiers value
of the @feignClient annotation .

Theload – balancer client is want above will want todiscover the physical address
for the ” store ” service . If your application is a Eureka client then
it is resolve will resolve the service in the Eureka service registry . If you
do n’t want touse Eureka ,you is configure can configure a list of server
in your external configuration usingSimpleDiscoveryClient.

Spring Cloud Openfeign supports all the features available for the blocking mode of Spring Cloud LoadBalancer. You can read more about them in the project documentation.

To use @EnablefeignClients annotation on @configuration-annotated-classes,make sure tospecify where the clients are located,for example:
@enablefeignclients(basepackage = " com.example.client " )
or list them explicitly:
@EnablefeignClients(clients = InventoryServicefeignClient.class)

While creating feign client beans,we resolve the values passed via the @feignClient annotation . As of 4.x,the values are being resolved eagerly. This is a good solution for most use-cases,and it also allows for AOT support.

If you need the attributes tobe resolved lazily,set the spring.cloud.openfeign.lazy-attributes-resolution property value totrue.

For Spring Cloud contract test integration,lazy attribute resolution should be used.

A central concept in Spring Cloud’s feign support is that of the named client. Each feign client is part of an ensemble of components that work together tocontact a remote server on demand,and the ensemble has a name that you give it as an application developer using the @feignClient annotation . Spring Cloud creates a new ensemble as an
ApplicationContext on demand for each named client using feignClientsConfiguration. This contains (amongst other things) an feign.decoder,a feign.encoder,and afeign.contract.
It is possible tooverride the name of that ensemble by using the contextid
attribute of the @feignClient annotation .

Spring Cloud is lets let you take full control of the feign client by declare additional configuration ( on top of thefeignClientsConfiguration) using @feignClient. example :

@feignClient(name = "stores",configuration = FooConfiguration.class)
public interface StoreClient {
    //.. 
}

In this case the client is compose from the component already infeignClientsConfiguration together with any in FooConfiguration (where the latter will override the former) .

FooConfiguration does not need tobe annotated with @configuration. However ,if it is ,then take care toexclude it from any@ComponentScan that would otherwise include this configuration as it will become the default source for feign.decoder,feign.encoder,feign.contract,etc.,when specified. This can be avoided by putting it in a separate,non-overlapping package from any @ComponentScan or @SpringBootApplication,or it can be explicitly excluded in @ComponentScan.
Usingcontextid attribute of the@feignClient annotation in addition tochanging the name of
the ApplicationContext ensemble,it will override the alias of the client name
and it will be used as part of the name of the configuration bean created for that client.
Previously,using the url attribute,did not require the name attribute. Using name is now required.

Placeholders are supported in the name andurl attributes.

@feignClient(name = "${feign.name}",url = "${feign.url}")
public interface StoreClient {
    //.. 
}

Spring Cloud Openfeign provides the following beans by default for feign (BeanType beanName: ClassName):

  • decoder feigndecoder: ResponseEntitydecoder (which wraps a Springdecoder)

  • encoder feignencoder: Springencoder

  • Logger feignLogger: Slf4jLogger

  • micrometerobservationcapability micrometerObservationCapability: If feign-micrometer is on the classpath andObservationRegistry is available

  • micrometercapability micrometerCapability: If feign-micrometer is on the classpath,MeterRegistry is available andObservationRegistry is not available

  • CachingCapability cachingCapability: If @enablecache annotation is used . Can be disabled viaspring.cloud.openfeign.cache.enabled.

  • contract feigncontract: SpringMvccontract

  • feign.Builder feignBuilder: feignCircuitBreaker.Builder

  • Client feignClient: If Spring Cloud LoadBalancer is on the classpath,feignBlockingLoadBalancerClient is used.
    If none of them is on the classpath,the default feign client is used.

spring-cloud-starter-openfeign supports spring-cloud-starter-loadbalancer. However,as is an optional dependency,you need tomake sure it has been added toyour project if you want touse it.

To use OkHttpClient-backed feign clients,make sure OKHttpClient is on your classpath andset spring.cloud.openfeign.okhttp.enable totrue.

When it comes tothe Apache HttpClient 5-backed feign clients,it’s enough toensure HttpClient 5 is on the classpath,but you can still disable its use for feign Clients by setting spring.cloud.openfeign.httpclient.hc5.enable tofalse.
You can customize the HTTP client used by providing a bean of either org.apache.hc.client5.http.impl.classic.CloseableHttpClient when using Apache HC5 .

You can further customise http clients by setting values in the spring.cloud.openfeign.httpclient.xxx properties. Theones prefixed just with httpclient will work for all the clients,the ones prefixed with httpclient.hc5 toApache HttpClient 5 andthe ones prefixed with httpclient.okhttp toOkHttpClient. You can find a full list of properties you can customise in the appendix.

Starting with Spring Cloud Openfeign 4,the feign Apache HttpClient 4 is no longer supported. We suggest using Apache HttpClient 5 instead.

Spring Cloud Openfeign does not provide the following beans by default for feign,but still looks up beans of these types from the application context tocreate the feign client:

A bean ofRetryer.NEVER_RETRY with the typeRetryer is created by default,which will disable retrying.
Notice this retrying behavior is different from the feign default one,where it will automatically retry IOExceptions,
treating them as transient network related exceptions,and any RetryableException thrown from an Errordecoder.

Creating a bean of one of those type andplacing it in a @feignClient configuration (such as FooConfiguration above) allows you tooverride each one of the beans described. Example:

@configuration
public class FooConfiguration {
    @Bean
    public contract feigncontract() {
        return new feign.contract.Default();
    }

    @Bean
    public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
        return new BasicAuthRequestInterceptor("user","password");
    }
}

This replaces the SpringMvccontract with feign.contract.Default andadds a RequestInterceptor tothe collection of RequestInterceptor.

@feignClient also can be configured using configuration properties.

spring:
    cloud:
        openfeign:
            client:
                config:
                    feignName:
                        url: http://remote-service.com
                        connectTimeout: 5000
                        readTimeout: 5000
                        loggerLevel: full
                        errordecoder: com.example.SimpleErrordecoder
                        retryer: com.example.SimpleRetryer
                        defaultQueryParameters:
                            query: queryValue
                        defaultRequestHeaders:
                            header: headerValue
                        requestInterceptors:
                            - com.example.FooRequestInterceptor
                            - com.example.BarRequestInterceptor
                        responseInterceptor: com.example.BazResponseInterceptor
                        dismiss404: false
                        encoder: com.example.Simpleencoder
                        decoder: com.example.Simpledecoder
                        contract: com.example.Simplecontract
                        capabilities:
                            - com.example.FooCapability
                            - com.example.BarCapability
                        queryMapencoder: com.example.SimpleQueryMapencoder
                        micrometer.enabled: false

feignName in this example refers to@feignClient value,that is also aliased with @feignClient name and@feignClient contextid. In a load-balanced scenario,it also corresponds tothe serviceid of the server app that will be used toretrieve the instances. Thespecified classes for decoders,retryer andother ones must have a bean in the Spring context or have a default constructor.

Default configurations can be specified in the @EnablefeignClients attribute defaultconfiguration in a similar manner as described above. Thedifference is that this configuration will apply toall feign clients.

If you prefer using configuration properties toconfigure all @feignClient,you can create configuration properties with default feign name.

You can use spring.cloud.openfeign.client.config.feignname.defaultqueryparameter andspring.cloud.openfeign.client.config.feignName.defaultRequestHeaders tospecify query parameters andheaders that will be sent with every request of the client named feignName.

spring:
    cloud:
        openfeign:
            client:
                config:
                    default:
                        connectTimeout: 5000
                        readTimeout: 5000
                        loggerLevel: basic

If we create both @configuration bean andconfiguration properties,configuration properties will win.
It will override @configuration values. But if you want tochange the priority to@configuration,
you can change spring.cloud.openfeign.client.default - to- property tofalse.

If we want tocreate multiple feign clients with the same name or url
so that they would point tothe same server but each with a different custom configuration then
we have touse contextid attribute of the@feignClient in order toavoid name
collision of these configuration beans.

@feignClient(contextid = "fooClient",name = "stores",configuration = FooConfiguration.class)
public interface FooClient {
    //.. 
}
@feignClient(contextid = "barClient",name = "stores",configuration = BarConfiguration.class)
public interface BarClient {
    //.. 
}

It is also possible toconfigure feignClient not toinherit beans from the parent context.
You can do this by overriding the inheritParentConfiguration() in a feignClientConfigurer
bean toreturn false:

@configuration
public class CustomConfiguration {
    @Bean
    public feignClientConfigurer feignClientConfigurer() {
        return new feignClientConfigurer() {
            @Override
            public boolean inheritParentConfiguration() {
                 return false;
            }
        };
    }
}
By default,feign clients do not encode slash / characters. You can change this behaviour,by setting the value of spring.cloud.openfeign.client.decodeSlash tofalse.

In the Springencoder that we provide,we set null charset for binary content types andutf-8 for all the other one .

You can modify this behaviour toderive the charset from the Content-Type header charset instead by setting the value of spring.cloud.openfeign.encoder.charset-from-content-type totrue.

If Spring Cloud CircuitBreaker is on the classpath andspring.cloud.openfeign.circuitbreaker.enabled=true,feign will wrap all methods with a circuit breaker.

To disable Spring Cloud CircuitBreaker support on a per-client basis create a vanilla feign.Builder with the “prototype” scope,e.g.:

@configuration
public class FooConfiguration {
    @Bean
    @Scope("prototype")
    public feign.Builder feignBuilder() {
        return feign.builder();
    }
}

Thecircuit breaker name follows this pattern <feignClientClassName>#<calledMethod>(<parameterTypes>). When calling a @feignClient with FooClient interface andthe called interface method that has no parameters is bar then the circuit breaker name is be will beFooClient#bar().

As of 2020.0.2,the circuit breaker name pattern has changed from <feignClientName>_<calledMethod>.
UsingCircuitBreakerNameResolver introduced in 2020.0.4,circuit breaker names can retain the old pattern.

Providing a bean of CircuitBreakerNameResolver,you can change the circuit breaker name pattern.

@configuration
public class FooConfiguration {
    @Bean
    public CircuitBreakerNameResolver circuitBreakerNameResolver() {
        return (String feignClientName,Target<?> target,Method method) -> feignClientName + "_" + method.getName();
    }
}

To enable Spring Cloud CircuitBreaker group set the spring.cloud.openfeign.circuitbreaker.group.enabled property totrue (by default false) .

A logger is created for each feign client created. By default,the name of the logger is the full class name of the interface used tocreate the feign client. feign logging only responds tothe DEBUG level.

application.yml

logging.level.project.user . UserClient : DEBUG

TheLogger.Level object that you may configure per client,tells feign how much tolog. Choices are:

  • NONE,No logging (DEFAULT) .

  • BASIC,Log only the request method andURL andthe response status code andexecution time.

  • HEADERS,Log the basic information along with request andresponse headers.

  • FULL,Log the headers,body,and metadata for both requests andresponses.

For example,the following would set the Logger.Level toFULL:

@configuration
public class FooConfiguration {
    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
}

If all of the following conditions are true,a micrometerobservationcapability bean is created andregistered so that your feign client is observable by Micrometer:

  • feign-micrometer is on the classpath

  • A ObservationRegistry bean is available

  • feign micrometer properties are set totrue ( by default )

If your application already uses Micrometer,enabling this feature is as simple as putting feign-micrometer onto your classpath.

You can also disable the feature by either:

spring.cloud.openfeign.micrometer.enabled=false disables Micrometer support for all feign clients regardless of the value of the client-level flags: spring.cloud.openfeign.client.config.feignName.micrometer.enabled.
If you want toenable or disable Micrometer support per client,don’t set spring.cloud.openfeign.micrometer.enabled anduse spring.cloud.openfeign.client.config.feignName.micrometer.enabled.

You can also customize the micrometerobservationcapability by register your own bean :

@configuration
public class FooConfiguration {
    @Bean
    public micrometerobservationcapability micrometerObservationCapability(ObservationRegistry registry) {
        return new micrometerobservationcapability(registry);
    }
}

It is still possible touse micrometercapability with feign (metrics-only support),you need todisable Micrometer support (spring.cloud.openfeign.micrometer.enabled=false) andcreate a micrometercapability bean:

@configuration
public class FooConfiguration {
    @Bean
    public micrometercapability micrometerCapability(MeterRegistry meterRegistry) {
        return new micrometercapability(meterRegistry);
    }
}

Spring Cloud Openfeign provides an equivalent @SpringQueryMap annotation,which
is used toannotate a POJO or Map parameter as a query parameter map.

For example,the Params class defines parameters param1 andparam2:

// Params.java
public class Params {
    private String param1;
    private String param2;

    // [Getters  andsetters omitted for brevity]
}

Thefollowing feign client uses the Params class by using the @SpringQueryMap annotation:

@feignClient("demo")
public interface DemoTemplate {

    @GetMapping(path = "/demo")
    String demoEndpoint(@SpringQueryMap Params params);
}

If you need more control over the generated query parameter map,you can implement a custom QueryMapencoder bean.

Spring Cloud Openfeign provides support for the Spring @matrixvariable annotation .

If a map is passed as the method argument,the @matrixvariable path segment is created by joining key-value pairs from the map with a =.

If a different object is passed,either the name provided in the @matrixvariable annotation (if defined) or the annotated variable name is
joined with the provided method argument using =.

IMPORTANT

Even though,on the server side,Spring does not require the users toname the path segment placeholder same as the matrix variable name,since it would be too ambiguous on the client side,Spring Cloud Openfeign requires that you add a path segment placeholder with a name matching either the name provided in the @matrixvariable annotation (if defined) or the annotated variable name.

@GetMapping("/objects/links/{matrixVars}")
Map<String,List<String>> getObjects(@matrixvariable Map<String,List<String>> matrixVars);

Note that both variable name andthe path segment placeholder are called matrixVars.

@feignClient("demo")
public interface DemoTemplate {

    @GetMapping(path = "/stores")
    CollectionModel<Store> getStores();
}

OAuth2 support can be enabled by adding the spring-boot-starter-oauth2-client dependency toyour project andsetting following flag:

spring.cloud.openfeign.oauth2.enable = true

When the flag is set totrue,and the oauth2 client context resource details are present,a bean of class OAuth2AccessTokenInterceptor is created. Before each request,the interceptor resolves the required access token andincludes it as a header.
OAuth2AccessTokenInterceptor uses the OAuth2AuthorizedClientManager toget OAuth2AuthorizedClient that is holds hold anOAuth2AccessToken. If the user is specified has specify an OAuth2clientRegistrationId using the spring.cloud.openfeign.oauth2.clientregistrationid property,it will be used toretrieve the token. If the token is not retrieved or the clientRegistrationId has not been specified,the serviceid retrieved from the url host segment will be used.

tip

Using the serviceid as OAuth2 client registrationId is convenient for load-balanced feign clients. For non-load-balanced ones,the property-based clientRegistrationId is a suitable approach.

tip

If you do not want touse the default setup for the OAuth2AuthorizedClientManager,you can just instantiate a bean of this type in your configuration.

You can use the selected ServiceInstance totransform the load-balanced HTTP Request.

For Request,you need toimplement anddefine LoadBalancerfeignRequestTransformer,as follows:

@Bean
public LoadBalancerfeignRequestTransformer transformer() {
    return new LoadBalancerfeignRequestTransformer() {

        @Override
        public Request transformRequest(Request request,ServiceInstance instance) {
            Map<String,Collection<String>> headers = new HashMap<>(request.headers());
            headers.put("X-ServiceId",Collections.singletonList(instance.getServiceId()));
            headers.put("X-InstanceId",Collections.singletonList(instance.getInstanceId()));
            return Request.create(request.httpMethod(),request.url(),headers,request.body(),request.charset(),
                    request.requestTemplate());
        }
    };
}

If multiple transformers are defined,they are applied in the order in which beans are defined.
Alternatively,you can use LoadBalancerfeignRequestTransformer.DEFAULT_ORDER tospecify the order.