In a microservices architecture, services often need to communicate with each other to fulfill a request. While RestTemplate or WebClient are commonly used, OpenFeign offers a declarative and cleaner alternative for inter-service communication.
OpenFeign is a Spring Cloud project that enables declarative REST clients to call other microservices directly as if calling local methods.
In this post, weโll explore how to set up client-to-client communication with OpenFeign in a Spring Boot microservice environment using Eureka for service discovery.

๐ฆ Project Structure
1 2 3 4 5 |
com.kscodes.springboot.microservice โโโ order-service // Uses Feign to call product-service โโโ product-service // Provides product details |
โ๏ธ Step 1: Add Maven Dependencies
In order-service pom.xml
:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> </dependencies> |
Ensure this is in the dependencyManagement
:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>2023.0.0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> |
๐ application.yml Configuration
For order-service:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
server: port: 8081 spring: application: name: order-service eureka: client: service-url: defaultZone: http://localhost:8761/eureka |
For product-service:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
server: port: 8082 spring: application: name: product-service eureka: client: service-url: defaultZone: http://localhost:8761/eureka |
โ๏ธ Step 2: Enable Feign Client
In your OrderServiceApplication
class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package com.kscodes.springboot.microservice.orderservice; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.openfeign.EnableFeignClients; @SpringBootApplication @EnableFeignClients(basePackages = "com.kscodes.springboot.microservice.orderservice.client") public class OrderServiceApplication { public static void main(String[] args) { SpringApplication.run(OrderServiceApplication.class, args); } } |
๐ Step 3: Create the Feign Client Interface
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
package com.kscodes.springboot.microservice.orderservice.client; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @FeignClient(name = "product-service") public interface ProductClient { @GetMapping("/products/{id}") String getProductById(@PathVariable("id") String id); } |
๐งฉ Step 4: Use the Feign Client in a Service or Controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
package com.kscodes.springboot.microservice.orderservice.controller; import com.kscodes.springboot.microservice.orderservice.client.ProductClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController public class OrderController { private final ProductClient productClient; public OrderController(ProductClient productClient) { this.productClient = productClient; } @GetMapping("/orders/{productId}") public String getOrder(@PathVariable String productId) { String productInfo = productClient.getProductById(productId); return "Order placed for: " + productInfo; } } |
๐งช Step 5: Create Sample Endpoint in Product-Service
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
package com.kscodes.springboot.microservice.productservice.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController public class ProductController { @GetMapping("/products/{id}") public String getProduct(@PathVariable String id) { return "Product details for ID: " + id; } } |
๐ Step 6: Run and Test
- Start Eureka Server
- Run product-service on
8082
- Run order-service on
8081
- Test:
1 2 3 4 |
curl http://localhost:8081/orders/123 |
โ
You should receive:Order placed for: Product details for ID: 123
๐ Optional: Add Feign Retry and Timeout Config
1 2 3 4 5 6 7 8 9 10 |
feign: client: config: default: connectTimeout: 3000 readTimeout: 5000 loggerLevel: full |
You can also specify retry behavior via Spring Retry.
๐ Benefits of Using OpenFeign Client Communication
- โ Declarative REST clients โ clean and concise
- โ Native Spring Boot integration
- โ Works seamlessly with Eureka and LoadBalancer
- โ Reduces boilerplate code
- โ Easier testing and mocking of services
๐ Conclusion
Using OpenFeign Client Communication in Spring Boot dramatically simplifies inter-service REST calls. With Eureka integration, it enables services to talk to each other with just annotated interfaces, no manual HTTP or URL management needed.
This declarative and elegant approach enhances readability, maintainability, and reduces error-prone boilerplate code โ ideal for any production-grade microservice architecture.