Technology
Spring Cloud Fine is a framework that provides a way to consume the rest of the services declaratively. It provides an easy way to access the rest of the services. The Feign framework will interact with the rest of the services by providing annotations and providing Java objects using encoders, decoders, and even HTTP message converters provided by Spring Web Framework.
It integrates with other spring modules like Eureka server, and Spring cloud Ribbon to provide service discovery and client-side load balancing automatically, without modifying the code.
Spring Cloud Eureka server is a service discovery application where microservices will register with the application name so that with this name other registered microservices will consume the services without hard-coding the IP address of the rest service in the client code.
Spring Ribbon is one of the modules that load balancers for specified applications at the client end. It will accept the comma-separated URLs for the same services, so by using the algorithms it will pick one of the configured URLs and invoke the rest service.
Maven Setup
Create a sample Spring boot web application and select Feign as a dependency in http://start.spring.io or add the Spring boot starter project for Feign.
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
And any class annotated with @Configuration or @SpringBootApplicationin Spring boot application, add @EnableFeignClients annotation so that Feign framework-related spring beans will be initialized.
Creating Feign Client
@FeignClient is the annotated used to create Ribbon load balancer, if we add Spring Ribbon in the classpath, this annotation accepts name/value to fetch the Service details from Eureka Server Registry if we are using Eureka Server, otherwise, it is the only name to represent the client.
If we are not using the Eureka Server, then we can specify the URL attribute with the full absolute path of the rest service application.
The sample Feign Client will look like below:
@Component @FeignClient(name = "books", path = "/book", url = "http://localhost:8000") publicinterface BookRestClient { @RequestMapping(consumes = "application/json", produces = "application/json", method = RequestMethod.POST public Book addBook(Book book); @RequestMapping(method = RequestMethod.GET, produces = "application/json") public Iterable<Book>getAll(); @RequestMapping(consumes = "application/json", produces = "application/json", method = RequestMethod.PUT) public Book updateBook(@RequestBody Book book); @RequestMapping(produces = "application/json", method = RequestMethod.DELETE, path = "/{id}") publicvoid deleteBook(@PathVariablelong id); @RequestMapping(produces = "application/json", method = RequestMethod.GET, path = "/{id}") public Book getBook(@PathVariablelong id); }
My rest Service is running in localhost:8000/book and we specified the same in the FeignCleint annotation URL property, Instead of hard coding we can also externalize using application.properties.
For each requestMapping we are specifying one method, which means by calling the interface method, internally Feign framework call service and do the response conversion to specified return type, return the converted object. No need to write a single line of code, to contact the rest service, by annotations also Feign framework will do everything in the background.
It is important to make sure that the annotated class must be annotated to the spring stereotype of annotation, advice to annotate with Spring @Component annotation.
Customizing Feign Defaults
Spring Cloud creates a new ensemble as an ApplicationContext on demand for each named client using FeignClientsConfiguration. This contains (amongst other things) a feign.Decoder, a feign.Encoder, and a feign.Contract.
We can also create a new Configuration for each FeignClient configuration property, where we can add any new messageconverters additional to the client application needed, or any decoders, or encoders are needed, we can specify the CustomConfiguration class and create beans for it.
CustomConfiguration class needs to annotate with @Configuration, as it is specific to the @Feign client, and if we want to share this configuration with all FeignClient then only specify the @configuration annotation. If the class is annotated with @Configuration, make sure that it is added to a separate package which is not available for component scan.
Spring Cloud Netflix provides the following beans by default for feign (beanName: ClassName):
feignDecoder: ResponseEntityDecoder feignEncoder: SpringEncoder feignLogger: Slf4jLogger feignContract: SpringMvcContract feignBuilder: HystrixFeign.Builder
Client feignClient: if Ribbon is enabled it is a LoadBalancerFeignClient, otherwise the default feign client is used.
We can also customize the httpclient, which library is used for contacting the rest service, by default RestTemplate is used to invoke the rest service.
Alternatively, we can use the OKHTTP library, by setting the feign.okhttp.enabled property to be true. If we want to use Apache httpclient, we by setting the property feign.httpclient.enabled to true, and add the corresponding libraries to the classpath.
If the rest service is secured, then we can write RequestInterceptor to intercept the request, and add the authentication details into it.
For this, we need to add the Configuration class and the same provided to FeignClient property.
We can configure the connectionTimeout, and log levels while contacting the service using the below configuration, which will be applicable for all FeignClients.
We can also specify configuration using spring application properties:
feign.client.config.book.decoder=com.example.SimpleDecoder feign.client.config.book.encoder=decoder=com.example.SimpleEncoder feign.client.config.book.error-decoder=com.example.SimpleErrorDecoder feign.client.config.book.connect-timeout=5000 feign.client.config.book.read-timeout=5000 feign.client.config.book.logger-level=FULL feign.client.config.book.decode404=false feign.client.config.book.request-interceptors=com.example.BookRequestInterceptor
Where the book is out FeignClient name, we can also specify the same set of default properties under the default key, instead of book use default, which will be shared across all FeignClients.
SpringFeign also supports Circuit breakers using the Hystrix library, we can create a bean that implements the Feign interface and provides the implemented class as a fallback. Or we can implement the HystrixClientFallbackFactory interface and return the object as Feign interface, and also it should be a spring bean.
Spring Feign client applicationContext found two beans of the same interface types if we enable Hystrix, so we need to mark the FeignClient interface as the Primary property.
Feign Request/Response Compression: we can compress the Rest service requests, and responses by setting the below properties:
feign.compression.request.enabled=true feign.compression.response.enabled=true
We can also selectively compress the requests by setting the minimum request size in the application properties file.
feign.compression.request.min-request-size=2048
Conclusion
This Blog explains how to build a Rest client in a declarative way, to consume Rest Services, and how to customize each client, and also default configuration properties for all Feign Clients, if the service is secured then, using Interceptors how to pass authentication details for Rest services.
The source code will be available at https://github.com/sravan4rmhyd/SpringCloudFeignExample.git