Master Spring Cloud OpenFeign: Complete Guide with Code Samples

This article provides a comprehensive introduction to Spring Cloud OpenFeign, comparing it with Feign and HttpExchange, and walks through practical setup, client declaration, custom configuration, interceptors, error handling, timeout and logging settings with full code examples for Spring Boot 3.2.5.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Master Spring Cloud OpenFeign: Complete Guide with Code Samples

1. Introduction

OpenFeign is a declarative HTTP client that simplifies writing network service clients. By annotating an interface, you can call other services without writing boilerplate code. It supports both OpenFeign and Jakarta JAX‑RS annotations.

The article offers a full‑stack overview of Spring Cloud OpenFeign.

2. Practical Example

2.1 Add Dependency

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-openfeign</artifactId>
  <version>2022.0.3</version>
</dependency>

Choose the Cloud version that matches your Spring Boot version.

2.2 Enable Feign Clients

@SpringBootApplication
@EnableFeignClients(basePackages = "com.pack.feign")
public class AppApplication {
}

If the annotation is placed on the main class, the basePackages attribute can be omitted.

2.3 Declare Feign Client

@FeignClient(value = "userFeignClient", url = "http://localhost:8088")
public interface UserFeignClient {
    @GetMapping("/users")
    ResponseEntity<List<User>> getUsers();
}

value specifies the client name (required). url defines the base request URL. The @GetMapping annotation maps the target endpoint.

2.4 Invoke the Client

private final UserFeignClient userFeignClient;
public UserFeignController(UserFeignClient userFeignClient) {
    this.userFeignClient = userFeignClient;
}
ResponseEntity<List<User>> response = userFeignClient.getUsers();
if (response.getStatusCode().is2xxSuccessful()) {
    List<User> users = response.getBody();
    users.forEach(System.out::println);
} else if (response.getStatusCode().is4xxClientError()) {
    throw new BadRequestException("Bad Request");
} else {
    throw new RuntimeException("Server Error");
}

The client is injected like any other Spring bean.

2.5 Inheritance

Common functionality can be placed in a base interface and extended:

@FeignClient(value = "accountFeignClient", url = "http://localhost:8088/")
public interface AccountFeignClient extends UserFeignClient {
    @GetMapping("/account/{id}")
    String getAccountByUser(@PathVariable("id") Long id);
}

Multi‑level inheritance is not supported.

2.6 OpenFeign Configuration

Default components are defined in FeignClientsConfiguration and can be overridden.

Decoder – ResponseEntityDecoder (wraps SpringDecoder)

Encoder – SpringEncoder Logger – Slf4jLogger Contract – SpringMvcContract Retryer – configurable retry strategy

Client – global request handler

Custom configuration example:

public class PackAccountFeignConfiguration {
    @Bean
    public CloseableHttpClient feignClient() {
        return HttpClients.createDefault();
    }
}

Use the custom configuration in the client annotation:

@FeignClient(value = "accountFeignClient",
             url = "http://localhost:8088/",
             configuration = PackAccountFeignConfiguration.class)
public interface AccountFeignClient extends UserFeignClient {}

Add the required dependency for the Apache HttpClient:

<dependency>
  <groupId>io.github.openfeign</groupId>
  <artifactId>feign-hc5</artifactId>
</dependency>

2.7 Property‑Based Configuration

Override settings via application.yml:

spring:
  cloud:
    openfeign:
      config:
        default:
          connectTimeout: 5000
          read-timeout: 5000

Specific client configuration:

spring:
  cloud:
    openfeign:
      config:
        accountFeignClient:
          connectTimeout: 5000

When both a @Configuration bean and properties are present, properties take precedence unless spring.cloud.openfeign.client.default-to-properties is set to false.

2.8 Interceptor Configuration

@Bean
RequestInterceptor requestInterceptor() {
    return template -> template.header("requestID", "UUID");
}

Allows adding custom headers or authentication logic.

2.9 Error Handling

@Bean
ErrorDecoder errorDecoder() {
    return (methodKey, response) -> switch (response.status()) {
        case 400 -> new BadRequestException(response);
        case 429 -> new TooManyRequestsException(response);
        default -> new Exception("feign client exception");
    };
};

Provides fine‑grained exception handling based on HTTP status.

2.10 Logging

Enable logging via properties:

logging:
  level:
    com.pack.feign: DEBUG

Or for a specific client:

logging:
  level:
    com.pack.feign.AccountFeignClient: DEBUG

Define logger level bean for full logging:

@Bean
Logger.Level feignLoggerLevel() {
    return Logger.Level.FULL;
}

Supported levels: NONE, BASIC, HEADERS, FULL.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

MicroservicesSpring BootOpenFeignFeignClient
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.