Tuesday, 18 May 2021

What is Feign Web Service Client ?

Feign is a declarative web service client. It makes writing web service clients easier. To use Feign create an interface and annotate it.

The following dependency is expected to add Feign in the project:

Dependency:

group id: org.springframework.cloud

artefact id: spring-cloud-starter-openfeign

Annotations:

@EnableFeignClients    - to enable the Feign Client

Sample Feign Client:

@FeignClient(name = "products", url="${productsUrl}")

public interface ProductClient {

        @RequestMapping(method=RequestMethod.GET,  value ="/products")

        List<Product> getProducts();

        @RequestMapping(method= RequestMethod.POST,  

        value ="/products/{productId}", consumes = "application/json")

        Product update(@PathVariable("productId") Long productId);

}


string value "products" within @FeignClient annotation is the arbitrary client which might be used in Ribbon (load balancing) support.

Note:

> you can also specify url attribute (absolute value or just a hostname).

> you can use qualifier attribute for giving an alias value for the bean name, if not given the name of bean in the application context is the fully qualified name of the interface.

---------------------------

Note: Each feign client is part of an ensemble of components that work together to contact a remote server, and the ensemble has a name that is given in name attribute of @FeignClient annotation.

Spring Cloud creates a new ensemble as an ApplicationContext on demand for each named client using FeignClientsConfiguration. This contains other things feign.Decorder, a feign.Encoder, and a feign.Contract.

You can control the feign client by declaring additional configuration using configuration attribute.


@FeignClient(name = "products", configuration= FooConfiguration.class)

public interface ProductClient {

    //..

}

Note: FooConfiguration does not need to be annotated with @Configuration. However, if it, then take care to exclude it from any @ComponentScan that would otherwise include this configuration as it become the default source for feign.Decoder, feign.Encoder, feign.Contract.

OTHER EXTRA INFO:

Spring Cloud Netflix provides the following beans by default:

> Decoder feignDecoder: ResponseEntityDecoder (which wraps a SpringDecorder)

> Encoder feignEncoder: SpringEncoder

> Logger feignLogger: Slf4jLogger

> Contract feignContract: SpringMvcContract

> Feign.Builder feignBuilder HystrixFeign.Builder

> Client feignClient: if Ribbon is enabled it is a LoadBalancerFeignClient, otherwise the feign client is used.

Not only by using a separate Configuration class, you can configure the @FeignClient using application props.

Example: 

feign:

    client: 

        config:

            <feignName>:

                connectTimeout: 5000

                readTimeout:    5000

                loggerLevel: full

                errorDecoder: com.example.SimpleErrorDecoder

                retryer: com.example.SampleRetryer

                requestInterceptors:

                        - com.example.SampleRequestInterceptor

                        - com.sample.ExampleRequestInterceptor

                decode404: false

                encoder: com.example.SampleEncoder

                decoder: com.example.SampleDecoder

                contract: com.example.SampleContract


The above props will apply to only named feign client. To apply to all feign clients, you can declare the props using default feign name:

Example:

  feign:

    client:

        config:

            default:

                connectTimeout:    5000

                readTimeout:    5000

                loggerLevel: basic

Now, this config props applies to all feign clients.

Note: If you create both Configuration class and Feign Config props in application yaml, configuration props will win.

You can change this behaviour by changing the prop:

   feign.client.default-to-properties to false.

Feign Logging:

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 to create the Feign client.

you can configure the log level per client 

e.g, 

logging.level.com.sample.ProductClient: DEBUG

com.sample.ProductClient - full class name

Logging Levels available are:

    NONE - No logging (default)

    BASIC - logs only 

        > request method    > URL    > response status > execution time

    HEADERS    - logs basic info along with req and response headers

    FULL - log the headers, body and metadata for both requests and responses.