➤ How to Code a Game
➤ Array Programs in Java
➤ Java Inline Thread Creation
➤ Java Custom Exception
➤ Hibernate vs JDBC
➤ Object Relational Mapping
➤ Check Oracle DB Size
➤ Check Oracle DB Version
➤ Generation of Computers
➤ XML Pros & Cons
➤ Git Analytics & Its Uses
➤ Top Skills for Cloud Professional
➤ How to Hire Best Candidates
➤ Scrum Master Roles & Work
➤ CyberSecurity in Python
➤ Protect from Cyber-Attack
➤ Solve App Development Challenges
➤ Top Chrome Extensions for Twitch Users
➤ Mistakes That Can Ruin Your Test Metric Program
FeignClient Example in Spring Cloud | Open Feign is built on top of LoadBalancerClient and it is the most used client for the intra-communication of microservices.
- It is also called an open Feign or abstract client.
- Here no need to define any manual code for consumers.
- Code generated using LoadBalancerClient. We need to define one interface only that follows Producer RestController. When we write FeignClient code then internally LoadBalancerClient code is generated.
- This client code makes a call to Eureka and fetches ServiceInstance using LoadBalancer, ie instance which has a Less Load Factor.
- It will make an HTTP call to the Producer Application and get the response back to the consumer even.
We have to develop 3 projects:-
- Discovery Client
- Producer Application
- Consumer Application
Eureka Server
- Create a new spring starter project SpringCloudEurekaServer with dependencies:- Eureka Server (
spring-cloud-starter-netflix-eureka-server
). - In the starter class add the annotation:-
@EnableEurekaServer
- In the application.properties file:-
server.port=8761
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
Producer Application
- Create a new spring starter project
SpringCloudFCBookServices
with dependencies:- Lombok, Spring Web, Eureka Discovery Client (spring-cloud-starter-netflix-eureka-client
). - In the starter class add the annotation:-
@EnableDiscoveryClient
The use of @EnableDiscoveryClient
is optional in Spring Boot applications. As of recent updates, simply having a DiscoveryClient implementation (like Eureka, Consul, or Zookeeper) on the classpath is enough to enable service registration and discovery. The application will automatically register with the service discovery server without explicitly using the @EnableDiscoveryClient annotation.
- In application.properties:-
server.port=9900
spring.application.name=BOOK-SERVICE
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
eureka.instance.instance-id=${spring.application.name}:${random.value}
It is not compulsory to provide eureka.instance.instance-id=${spring.application.name}:${random.value}
in your Producer microservices when working with a FeignClient and Eureka server. However, it is a common practice to ensure that each instance of your microservice has a unique identifier. This helps Eureka distinguish between different instances of the same service. By default, Eureka uses the combination of the application name and a random value to generate a unique instance ID. This configuration ensures that each instance registers with a unique ID, which is particularly useful in a microservices architecture where multiple instances of the same service might be running.
If you don’t specify the instance-id, Eureka will still generate a unique ID for each instance, but explicitly setting it can help with debugging and monitoring.
- Model class:-
package com.knowprogram.demo.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Book {
private Integer bookId;
private String bookName;
private String bookAuthor;
}
- RestController:-
package com.knowprogram.demo.controller;
import java.util.Arrays;
import java.util.List;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.knowprogram.demo.model.Book;
@RestController
@RequestMapping("/books")
public class BookRestController {
@GetMapping("/all")
public ResponseEntity<List<Book>> getAllBooks() {
return ResponseEntity.ok(
Arrays.asList(
new Book(10, "Core Java", "SAM"),
new Book(11, "Adv Java", "RAM"),
new Book(12, "Spring Boot", "SAM"),
new Book(13, "Microservices", "SYED")
)
);
}
@GetMapping("/find/{id}")
public ResponseEntity<Book> getOneBook(@PathVariable Integer id) {
return ResponseEntity.ok(new Book(id, "Dummy Book", "Dummy Author"));
}
@PostMapping("/create")
public ResponseEntity<String> createNewBook(@RequestBody Book book) {
return ResponseEntity.ok(book.toString());
}
@DeleteMapping("/remove/{id}")
public ResponseEntity<String> deleteBook(@PathVariable Integer id) {
return ResponseEntity.ok("Book deleted! " + id);
}
}
Consumer Application
- Create a new spring starter project
SpringCloudFCPublisherService
with dependencies:- Lombok, Spring Web, Eureka Discovery Client (spring-cloud-starter-netflix-eureka-client
), and OpenFeign (spring-cloud-starter-openfeign
). - In the starter class add the annotation:-
@EnableDiscoveryClient
, and@EnableFeignClients
. - In application.properties:-
server.port=9880
spring.application.name=PUBLISHER-SERVICE
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
- Model Class (Copy the Model class from Producer to Consumer):-
package com.knowprogram.demo.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Book {
private Integer bookId;
private String bookName;
private String bookAuthor;
}
- Consumer:-
This interface must follow the Producer RestController. The interface name and method name can be different but the method’s request mapping, return type, and parameter must be the same. It means except method name and interface name others should match.
package com.knowprogram.demo.consumer;
import java.util.List;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import com.knowprogram.demo.model.Book;
@Component
@FeignClient("BOOK-SERVICE")
public interface BookRestConsumer {
@GetMapping("/books/all")
public ResponseEntity<List<Book>> getAllBooks();
@GetMapping("/books/find/{id}")
public ResponseEntity<Book> getOneBook(@PathVariable Integer id);
@PostMapping("/books/create")
public ResponseEntity<String> createNewBook(@RequestBody Book book);
@DeleteMapping("/books/remove/{id}")
public ResponseEntity<String> deleteBook(@PathVariable Integer id);
}
- RestController:-
package com.knowprogram.demo.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.knowprogram.demo.consumer.BookRestConsumer;
import com.knowprogram.demo.model.Book;
@RestController
@RequestMapping("/publisher")
public class PublisherRestController {
@Autowired
private BookRestConsumer consumer;
@GetMapping("/view")
public String viewPublisherBooks() {
ResponseEntity<List<Book>> resp = consumer.getAllBooks();
return "FROM PUBLISHER =>" + resp.getBody();
}
@GetMapping("/getOne")
public String viewOnePublisherBook() {
ResponseEntity<Book> resp = consumer.getOneBook(550);
return "FROM PUBLISHER ONE BOOK=>" + resp.getBody();
}
@PostMapping("/save")
public String createOnePublisherBook(@RequestBody Book book) {
ResponseEntity<String> resp = consumer.createNewBook(book);
return "FROM PUBLISHER SAVE BOOK=>" + resp.getBody();
}
@DeleteMapping("/del/{id}")
public String removeOnePublisherBook(@PathVariable Integer id) {
ResponseEntity<String> resp = consumer.deleteBook(id);
return "FROM PUBLISHER DELETE BOOK=>" + resp.getBody();
}
}
How to create multiple instances of an application on the same machine? Change the port number and run the same application again for a new instance on the local machine.
Execution Order
- Run Eureka (
SpringCloudEurekaServer
) Starter class [1 time] - Run Producer (
SpringCloudFCBookServices
) Starter class [run 3 times, by changing port number] - Run Consumer (
SpringCloudFCPublisherService
) Starter class [ run 1 time] - Go to the Eureka server (http://localhost:8761/). It will list all instances.
In the Eureka server dashboard (http://localhost:8761/) and from the “instance info” section gather the “ipAddr” value. In our case, it is 192.168.31.151. And 9880 is the port number of the consumer application. We will use this IP and Port to access the consumer APIs.

API Calls
curl http://192.168.31.151:9880/publisher/view
FROM PUBLISHER =>[Book(bookId=10, bookName=Core Java, bookAuthor=SAM), Book(bookId=11, bookName=Adv Java, bookAuthor=RAM), Book(bookId=12, bookName=Spring Boot, bookAuthor=SAM), Book(bookId=13, bookName=Microservices, bookAuthor=SYED)]
curl http://192.168.31.151:9880/publisher/getOne
FROM PUBLISHER ONE BOOK=>Book(bookId=550, bookName=Dummy Book, bookAuthor=Dummy Author)
POST http://192.168.31.151:9880/publisher/save
Body => raw => JSON
{
"bookId": 99,
"bookName": "Test",
"bookAuthor": "SAMPLE"
}
curl -X POST http://192.168.31.151:9880/publisher/save -H "Content-Type: application/json" -d "{ \"bookId\": 99,\"bookName\": \"Test\",\"bookAuthor\": \"SAMPLE\"}"
FROM PUBLISHER SAVE BOOK=>Book(bookId=99, bookName=Test, bookAuthor=SAMPLE)
curl -X DELETE http://192.168.31.151:9880/publisher/del/1234
FROM PUBLISHER DELETE BOOK=>Book deleted! 1234
One Microservice is recommended to write for 1 module and it should contain only 1 RestController. One microservice can have multiple modules integration so it can have N RestConsumers. There can be multiple RestConsumers but there will be only 1 RestController for 1 project.
If you enjoyed this post, share it with your friends. Do you want to share more information about the topic discussed above or do you find anything incorrect? Let us know in the comments. Thank you!