When two web applications communicate with each other for data exchange, they work on Producer-Consumer technique. An application who produces data is known as a Producer/Provider application. Similarly the one who consumes data is known as Consumer application. As a Java developer, we might be very familiar with REST API for Producer application whereas RestTemplate for Consumer application. With Microservices based application also, two Microservices communicate with each other and follow the Producer-Consumer model. Here, in consumer side, we use a concept โFeign Clientโ as a better option instead of RestTemplate in order to minimize our effort of coding. Therefore, our topic of discussion is โHow to Implement Feign Client in Spring Boot Microservices?โ.
Apart from consuming REST services in an easy way, FeignClient/OpenFeign when combined with Eureka also offers us an easy load balancing. We will discuss about both the features of OpenFeign step by step in this article. Letโs discuss our topic โHow to Implement Feign Client in Spring Boot Microservices?โ and the related concepts.
Table of Contents (Click on links below to navigate)
- 1 What is Feign or Open Feign?
- 2 How to Implement Feign Client in Spring Boot Microservices?
- 3 Details of the Use Case
- 4 Create Microservice #1(Eureka Server)
- 5 Create Microservice #2(Producer Service)
- 6 Create Microservice #3(Consumer Service)
- 6.1 Step #1: Create a Spring Boot Project
- 6.2 Step #2: Apply Annotation @EnableEurekaClient and @EnableFeignClients at the main class
- 6.3 Step #3: Modify application.properties file
- 6.4 Step #4: Create Model class as Book.java
- 6.5 Step #5: Create an interface as BookRestConsumer.java
- 6.6 Step #6: Create a RestController as StudentRestController.java
- 7 How to test FeignClient Enabled Microservice?
- 8 How to test FeignClient Enabled Microservice as a Load Balancer?
- 9 Conclusion
What is Feign or Open Feign?
Feign is a declarative REST Client. It helps in writing web service clients more easily. In order to use Feign, create an interface and apply @FeignClient annotation on it. Moreover, it internally generates a Proxy class at runtime using Dynamic Proxy Pattern. It actually gets Application name (Service Instance) from Eureka and supports Making HTTP call. We should use two annotations for this concept, they are:
@EnableFeignClients :ย To apply at starter class
@FeignClient(name=โApplicationNameโ) : To define an interface for a Consumer
How to Implement Feign Client in Spring Boot Microservices?
Programmatically, FeignClient is implemented by creating an interface and annotating it with @FeignClient as below.
@FeignClient(name="ApplicationName") public interface <AnyName> { //abstract method @__Mapping("/path") public <ReturnType> <anyMethodName>(<params>); . . . }
Details of the Use Case
We are going to implement a simple use case to make the concept of Feign Client crystal clear. Here, we will use three Microservices: Eureka Server, Producer service, and Consumer Service. Both Producer as well as Consumer services will register themselves with Eureka in order to communicate with each other. Furthermore, letโs assume Book Service as a Producer and Student Service as a Consumer. Needless to say, Book service will publish the data and Student service will consume that data. Here, Feign Client will play an important role to consume data produced by Book service.
Apart from that we will see the magic of the Feign Client as a load balancer when used with Eureka. Moreover, we will implement load balancer in the following sections of this article.
Now, letโs find the answer of โHow to Implement Feign Client in Spring Boot Microservices?โ by applying step by step process.
Create Microservice #1(Eureka Server)
In order to discover and communicate Microservices with each other, we need toย create a Eureka Server Service. Creating a Eureka Server is itself similar to creating a Microservice. Moreover, it is just a Spring Boot Project that incorporates Spring Cloudโs Eureka Server dependency. In โapplication. propertiesโ file we will have some specific properties that will indicate that this application/microservice is a Eureka server. In order to create Eureka Server follow the below steps.
Step #1: Create a Spring Boot Project
Here, we will use STS(Spring Tool Suite) to create our Spring Boot Project. If you are new to Spring Boot, visitย Internal Linkย to create a sample project in spring boot. While creating a project in STS, add starter โEureka Serverโ in order to get features of it.
Step #2: Apply Annotation @EnableEurekaServer at the main class
In order to make your application/microservice acts as Eureka server, you need to apply @EnableEurekaServer at the main class of your application.
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @SpringBootApplication @EnableEurekaServer public class SpringCloudEurekaServerApplication { public static void main(String[] args) { SpringApplication.run(SpringCloudEurekaServerApplication.class, args); } }
Step #3: Modify application.properties file
Add below properties in your application.properties file.
server.port=8761 eureka.client.register-with-eureka=false eureka.client.fetch-registry=false
eureka.client.register-with-eureka=false
Default value of property โeureka.client.register-with-eurekaโ is true. Please note that this property is mandatory to include in Eureka Server in order to make its value as false. However, this is optional to add in case of other microservices/applications that are not Eureka server. Moreover, every microservice project is connected to Spring Cloud project that provides default value to true. Therefore, We shouldย include โeureka.client.register-with-eureka=falseโย for one time only in case of Eureka serverย as Eureka Server itself canโt be registered.
eureka.client.fetch-registry=false
This property indicates that Eureka Server is supported to fetch instance details of microservice to make intra-communication between microservices happen. If one microservice wants to communicate with another microservice by using Eureka then inside microservice we should add this property (eureka.client.fetch-registry) and set it to true. However, inside Eureka Server we should include this property with a value as false. However,ย Eureka server will never try to fetch registry as it is itself having a registry.ย Hence the value of this property in case of Eureka server will be false. Moreover, every microservice project is connected to Spring Cloud project that provides default value to true.
Default port for Eureka Server is 8761.
Create Microservice #2(Producer Service)
In our case, Book Service is the provider/producer Service. Moreover, the Book service will publish the REST endpoints. Letโs develop it step by step.
Step #1: Create a Spring Boot Project
Here, we will use STS(Spring Tool Suite) to create our Spring Boot Project. If you are new to Spring Boot, visitย Internal Link to create a sample project in spring boot. While creating a project in STS, add starter โEureka Discovery Clientโ , โSpring Webโ and โLombokโ in order to get all required features. Furthermore, if you are new to โLombokโ, kindly visit โHow to configure Lombokโ and to know all about it in detail.
Step #2: Apply Annotation @EnableEurekaClient at the main class
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication @EnableEurekaClient public class SpringCloudFeignBookServiceApplication { public static void main(String[] args) { SpringApplication.run(SpringCloudFeignBookServiceApplication.class, args); } }
Step #3: Modify application.properties file
Add below properties in your application.properties file.
server.port=9000
spring.application.name=BOOK-SERVICE
eureka.client.service-url.default-zone=http://localhost:8761/eurekaย ย ย ย ย ย #Register with Eureka
Moreover, โeureka.client.service-url.default-zone=http://localhost:8761/eurekaโ indicates that this service is getting registered with the Eureka Server.
Step #4: Create Model class as Book.java
Letโs create model class as Book.java as below. Please note that, here we have used โLombokโ annotations in order to reduce the boilerplate code.
import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @NoArgsConstructor @AllArgsConstructor public class Book { private Integer bookId; private String bookName; private Double bookCost; }
Step #5: Create a RestContoller class as BookRestController.java
In order to publish Book Service, we will create a BookRestController and define the endpoints as below. Please note that, here we are not using a database as our focus is on Feign Client functionality. Instead, we are using some hardcoded values and the Collections to store values wherever required.
import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.dev.springcloud.feign.model.Book; @RestController @RequestMapping("/book") public class BookRestController { @Autowired Environment environment; @GetMapping("/data") public String getBookData() { return "data of BOOK-SERVICE, Running on port: " +environment.getProperty("local.server.port"); } @GetMapping("/{id}") public Book getBookById(@PathVariable Integer id) { return new Book(id, "Head First Java", 500.75); } @GetMapping("/all") public List<Book> getAll(){ return List.of( new Book(501, "Head First Java", 439.75), new Book(502, "Spring in Action", 340.75), new Book(503, "Hibernate in Action", 355.75) ); } @GetMapping("/entity") public ResponseEntity<String> getEntityData() { return new ResponseEntity<String>( "Hello from BookRestController", HttpStatus.OK); } }
Create Microservice #3(Consumer Service)
In our case, Student Service is the consumer Service. Moreover, the Consumer service will consume the services published by Book service. Our primary focus here is on the implementation of Feign Client. Furthermore, we will see how the Feign Client makes our service call easy. Letโs develop it step by step.
Step #1: Create a Spring Boot Project
Here, we will use STS(Spring Tool Suite) to create our Spring Boot Project. If you are new to Spring Boot, visitย Internal Link to create a sample project in spring boot. While creating a project in STS, add starter โOpenFeignโ, โEureka Discovery Clientโ , โSpring Webโ and โLombokโ in order to get all required features. Furthermore, if you are new to โLombokโ, kindly visit โHow to configure Lombokโ and to know all about it in detail.
Step #2: Apply Annotation @EnableEurekaClient and @EnableFeignClients at the main class
In order to get the features of OpenFeign, we will additionally need to apply @EnableFeignClients
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.openfeign.EnableFeignClients; @SpringBootApplication @EnableEurekaClient @EnableFeignClients public class SpringCloudFeignStudentServiceApplication { public static void main(String[] args) { SpringApplication.run(SpringCloudFeignStudentServiceApplication.class, args); } }
Step #3: Modify application.properties file
Add below properties in your application.properties file.
server.port=9100 spring.application.name=STUDENT-SERVICE eureka.client.service-url.default-zone=http://localhost:8761/eureka
Needless to say, we need to add โeureka.client.service-url.default-zone=http://localhost:8761/eurekaโ in order to get Student Service registered with Eureka Server.
Step #4: Create Model class as Book.java
Letโs replicate the model class as Book.java as it is in the producer service. Please note that, here we have used โLombokโ annotations in order to reduce the boilerplate code.
import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @NoArgsConstructor @AllArgsConstructor public class Book { private Integer bookId; private String bookName; private Double bookCost; }
Step #5: Create an interface as BookRestConsumer.java
This is the most important file when talking about Feign Client. At Interface level, we need to apply @FeignClient annotation and provide the name of producer service/application as below. Further, declare the methods as per the requirement.
import org.springframework.cloud.openfeign.FeignClient; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import com.dev.springcloud.feign.model.Book; @FeignClient(name="BOOK-SERVICE") public interface BookRestConsumer { @GetMapping("/book/data") public String getBookData(); @GetMapping("/book/{id}") public Book getBookById(@PathVariable Integer id); @GetMapping("/book/all") public List<Book> getAllBooks(); @GetMapping("/book/entity") public ResponseEntity<String> getEntityData(); }
Step #6: Create a RestController as StudentRestController.java
At the end, create a RestController as StudentRestController to receive the data from Book service as below. The important point to note here is that we need to auto-wire the BookRestConsumer here in this class and then use it.
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.dev.springcloud.feign.consumer.BookRestConsumer; @RestController @RequestMapping("/student") public class StudentRestController { @Autowired private BookRestConsumer consumer; @GetMapping("/data") public String getStudentInfo() { System.out.println(consumer.getClass().getName()); //prints as a proxy class return "Accessing from STUDENT-SERVICE ==> " +consumer.getBookData(); } @GetMapping("/allBooks") public String getBooksInfo() { return "Accessing from STUDENT-SERVICE ==> " + consumer.getAllBooks(); } @GetMapping("/getOneBook/{id}") public String getOneBookForStd(@PathVariable Integer id) { return "Accessing from STUDENT-SERVICE ==> " + consumer.getBookById(id); } @GetMapping("/entityData") public String printEntityData() { ResponseEntity<String> resp = consumer.getEntityData(); return "Accessing from STUDENT-SERVICE ==> " + resp.getBody() +" , status is:" + resp.getStatusCode(); } }
Thatโs All from coding!
How to test FeignClient Enabled Microservice?
Itโs time to test our FeignClient enabled Microservice. Please follow below steps:
1) Start Service/Application containing Eureka Server
2) Start Producer Service/Application (Book)
3) Start Consumer Service/Application (Student)
4) Open a browser window, hit below URLs and observe the results.
http://localhost:9100/student/data
http://localhost:9100/student/allBooks
http://localhost:9100/student/getOneBook/501
http://localhost:9100/student/entityData
How to test FeignClient Enabled Microservice as a Load Balancer?
Now we are going to test load-balancing functionality of FeignClient enabled Microservice. Please follow below steps:
1) Start Service/Application containing Eureka Server
2) Start multiple instances of Producer Service/Application (Book). In order to get it, change the server port in application.properties file, save the file and then start the application. Letโs assume that we need three instances of the application. Port 9000 is already configured, now configure two more 9001 and 9002.
3) Start Consumer Service/Application (Student)
4) Now, open a browser window, hitย URL โhttp://localhost:9100/student/dataโ which contains server port information. Further, refresh the browser multiple times and observe the port number in the results. It will randomly pick the server from 9000, 9001 and 9002 as shown below.
ย
Conclusion
After going through all the theoretical & example part of โHow to Implement Feign Client in Spring Boot Microservices?โ, finally, we should be able to implement Feign Client with the Microservices. Similarly, we expect from you to further extend these examples and implement them in your project accordingly. I hope you might be convinced by the article โHow to Implement Feign Client in Spring Boot Microservices?โ. In addition, If there is any update in the future, we will also update the article accordingly. Moreover, Feel free to provide your comments in the comments section below.
Nice one, if possible can you post article on some basics like containers, web and application server , Git cloud config in spring cloud and how to use multiple properties time by choosing anyone of this depend upon running environment?
Great tutorial with good explanation of FeignClient usage. Please add more such projects with code and explain each line of code for new learners like me. So much interesting. Thank you.
best article. very simplified. tysm
Helpful! Looking for more Tutorials from you. Keep it up.
Nice tutorial. it would be great if pom.xml and build.gradle files also included. Thank you!