Usage
About
Feign is a declarative HTTP client that allows developers to write clean, type-safe interfaces to call remote HTTP services in a Spring-based application. Rather than writing boilerplate code for HTTP requests, Feign enables us to define Java interfaces annotated with Spring MVC annotations (@GetMapping
, @PostMapping
, etc.), and it takes care of the rest.
This is especially useful in microservices where services frequently communicate over REST. It promotes better abstraction, reusability, and readability.
Dependency
To use Feign in a Spring Boot application, add the following dependency:
If we’re using Spring Cloud OpenFeign:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
Also, make sure to include the appropriate Spring Cloud BOM in our dependencyManagement
:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2023.0.1</version> <!-- Replace the version -->
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Compatibility
Spring Boot
Fully compatible with Spring Boot 2.x and 3.x
Spring Cloud
Required. Feign is integrated via Spring Cloud OpenFeign
Spring WebMVC
Native support using Spring MVC-style annotations
WebFlux
Not recommended. Feign is blocking and not reactive
OpenAPI
Not directly integrated. OpenAPI-generated clients are better suited for spec-first development
Declarative API
OpenFeign follows a declarative programming model we define what the client interface should look like, and the library generates the HTTP call logic at runtime. Unlike RestTemplate or WebClient, we don't explicitly construct HTTP requests in a fluent chain. Instead, we declare how to reach a service using Java interfaces and annotations.
This approach leads to cleaner, more concise, and maintainable code — especially in large enterprise applications where service-to-service communication is frequent.
Declarative API Style
Declarative means we describe the desired behavior (the what), not the process (the how). With Feign, the focus is on interface-first programming.
@FeignClient(name = "user-service", url = "http://localhost:8081")
public interface UserClient {
@GetMapping("/api/users/{id}")
UserDto getUser(@PathVariable("id") Long id);
@PostMapping("/api/users")
UserDto createUser(@RequestBody UserDto user);
}
We are not writing the logic to build the request, set headers, parse the response, or handle connection issues Feign generates that code based on annotations.
How It Differs from Fluent API (e.g., WebClient)
Programming Style
Interface-based with annotations
Code-based chain of method calls
HTTP Verb Configuration
Annotated on method (@GetMapping
, @PostMapping
, etc.)
Explicitly called (.get()
, .post()
etc.)
URL & Path
Declared in interface and method-level mapping
Built using .uri(...)
and path/query params
Headers, Cookies
Declared via annotations or interceptors
Set dynamically in the fluent chain
Control Flow
Abstracted away
Developer fully controls request/response logic
Type Safety
Strong — compile-time checks via interface
Moderate — dynamic object mapping via lambdas
Common Use
Simpler synchronous REST clients
Advanced or reactive usage (streaming, backpressure, etc.)
Creating a OpenFeign Instance
In OpenFeign, we don’t create an instance manually like we would with WebClient or RestTemplate. Instead, we define an interface, annotate it with @FeignClient
, and Spring Boot (via Spring Cloud OpenFeign) automatically generates the implementation at runtime and registers it as a Spring bean.
This promotes clean separation of concerns and allows us to inject the client wherever needed just like any other Spring-managed dependency.
How It Works ?
To create and use a Feign client:
Define an interface
Annotate with
@FeignClient
Use Spring’s dependency injection to autowire the client
Example
Step 1: Enable Feign Support
@SpringBootApplication
@EnableFeignClients
public class PaymentServiceApplication {
public static void main(String[] args) {
SpringApplication.run(PaymentServiceApplication.class, args);
}
}
Step 2: Define the Feign Client Interface
@FeignClient(name = "account-service", url = "http://localhost:8081")
public interface AccountClient {
@GetMapping("/api/accounts/{id}")
AccountDto getAccountById(@PathVariable("id") Long id);
}
Step 3: Use the Client in a Service
@Service
public class PaymentService {
private final AccountClient accountClient;
public PaymentService(AccountClient accountClient) {
this.accountClient = accountClient;
}
public void processPayment(Long accountId) {
AccountDto account = accountClient.getAccountById(accountId);
// use account info...
}
}
Last updated