How to Create an OpenFeign Client with Resilience4j

Daniel Angel
3 min readSep 11, 2024

--

In this article, you will learn how to create an OpenFeign client with Resilience4j to handle failures and improve the resilience of your Spring Boot applications. We will go step-by-step through the configuration and integration of these components to build a robust and fault-tolerant application.

Photo by Alex Shute on Unsplash

Introduction

OpenFeign is a declarative HTTP client that simplifies calling web services, while Resilience4j is a library that provides resilience patterns such as Circuit Breaker, Rate Limiter, Retry, and Bulkhead. By combining them, we can build applications that handle failures gracefully.

Prerequisites

Before you start, ensure you have:

  • Java JDK 11 or higher.
  • Maven.
  • Basic knowledge of Spring Boot.

Project Setup

  1. Initialize a new Spring Boot project:
  • Go to Spring Initializr and set up your project with the following dependencies:
  • Spring web
  • OpenFeign
  • Resilience4j
  • Download and unzip the project.

2. Add dependencies in your pom.xml:

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot2</artifactId>
<version>1.7.1</version>
</dependency>
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-micrometer</artifactId>
<version>1.7.1</version>
</dependency>
</dependencies>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR9</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

Creating the OpenFeign Client

  1. Enable Feign in your main application class:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableFeignClients
public class FeignResilienceApplication {
public static void main(String[] args) {
SpringApplication.run(FeignResilienceApplication.class, args);
}
}

2. Create a Feign interface for your client:

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

@FeignClient(name = "exampleClient", url = "https://api.example.com")
public interface ExampleClient {
@GetMapping("/data")
String getData(@RequestParam(name = "param") String param);
}

Integration with Resilience4j

  1. Add the @CircuitBreaker annotation to your Feign method:
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;

@FeignClient(name = "exampleClient", url = "https://api.example.com")
public interface ExampleClient {
@GetMapping("/data")
@CircuitBreaker(name = "exampleClient", fallbackMethod = "fallbackGetData")
String getData(@RequestParam(name = "param") String param);

default String fallbackGetData(String param, Throwable throwable) {
return "Fallback response due to: " + throwable.getMessage();
}
}

Resilience4j Configuration

  1. Configure Resilience4j in your application.yml file:
resilience4j:
circuitbreaker:
instances:
exampleClient:
registerHealthIndicator: true
slidingWindowSize: 10
permittedNumberOfCallsInHalfOpenState: 3
minimumNumberOfCalls: 5
waitDurationInOpenState: 10000
failureRateThreshold: 50
eventConsumerBufferSize: 10
recordExceptions:
- org.springframework.web.client.HttpServerErrorException
- java.io.IOException
ignoreExceptions:
- org.springframework.web.client.HttpClientErrorException$NotFound

Create a controller to test the Feign client:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ExampleController {

@Autowired
private ExampleClient exampleClient;

@GetMapping("/fetch-data")
public String fetchData(@RequestParam String param) {
return exampleClient.getData(param);
}
}

Run your application:

./mvnw spring-boot:run

Conclusion

In summary, integrating Feign Client with Resilience4j allows us to build resilient and robust applications, prepared to handle temporary failures in communication with external services. Throughout the article, we explored how to configure a Feign client and apply fault tolerance patterns like circuit breakers, timeouts, and retries. This approach helps mitigate network failures and ensures our applications remain stable and reliable even in distributed environments.

Adopting these practices not only improves the user experience by reducing wait times and unexpected errors, but also enhances the scalability and maintainability of our applications, aligning with modern design principles for microservices.

It’s important to remember that while Resilience4j provides an excellent set of tools, we must always adjust its configuration according to the requirements and expected behavior of our application to avoid introducing unnecessary overhead. With proper implementation, our microservices will be better equipped to handle failures and continue operating under adverse conditions.

--

--

Daniel Angel
Daniel Angel

Written by Daniel Angel

Backend developer | Java, Spring boot, Cloud| Laravel, Php

No responses yet