Skip to main content

7.4 Inter-Service Communication: OpenFeign & WebClient

← Back to Chapter 7: Microservices & Spring Cloud

Synchronous communication between microservices can be achieved via declarative HTTP clients (Spring Cloud OpenFeign) or non-blocking reactive clients (Spring WebClient).


1. Spring Cloud OpenFeign (Declarative REST Client)​

OpenFeign allows you to define an interface annotated with standard Spring MVC annotations. Spring automatically generates the underlying HTTP client implementation at runtime!

1. Enable Feign Clients​

@SpringBootApplication
@EnableFeignClients
public class OrderApplication { ... }

2. Define the Feign Interface​

// 'name' maps to the registered Eureka service name!
@FeignClient(name = "payment-service", path = "/api/v1/payments", configuration = FeignClientConfig.class)
public interface PaymentServiceClient {

@PostMapping("/process")
PaymentResponse processPayment(@RequestBody PaymentRequest request);

@GetMapping("/{transactionId}")
PaymentDetails getPaymentDetails(@PathVariable("transactionId") UUID transactionId);
}

3. Propagating Headers via RequestInterceptor​

Pass auth tokens and correlation IDs to downstream services automatically:

@Configuration
public class FeignClientConfig {

@Bean
public RequestInterceptor bearerAuthRequestInterceptor() {
return requestTemplate -> {
String token = SecurityContextHolder.getContext().getAuthentication().getCredentials().toString();
requestTemplate.header("Authorization", "Bearer " + token);
requestTemplate.header("X-Correlation-Id", MDC.get("correlationId"));
};
}
}

2. Spring WebClient (Non-Blocking & Reactive)​

WebClient (from spring-boot-starter-webflux) is the modern replacement for legacy RestTemplate, supporting both asynchronous reactive streams and synchronous .block() execution.

@Service
public class InventoryClient {

private final WebClient webClient;

public InventoryClient(WebClient.Builder builder) {
this.webClient = builder.baseUrl("http://inventory-service").build();
}

public Mono<InventoryResponse> checkStock(String sku) {
return webClient.get()
.uri("/api/v1/inventory/{sku}", sku)
.retrieve()
.bodyToMono(InventoryResponse.class)
.timeout(Duration.ofMillis(1500));
}
}

3. Comparison: RestTemplate vs OpenFeign vs WebClient​

FeatureRestTemplateOpenFeignWebClient
ParadigmBlocking (Synchronous)Blocking (Synchronous)Non-blocking (Reactive) & Blocking
API StyleProgrammatic templateDeclarative InterfaceFluent Functional Builder
RecommendationMaintenance modeExcellent for standard microservicesModern default for high throughput