How to Customize WebClient and RestClient Configurations in CoApi
You can customize CoApi's HTTP clients by setting coapi.* properties in your application.yml, providing your own WebClientCustomizer or RestTemplateCustomizer beans, or completely replacing the WebClient or RestTemplate beans with your own implementations.
CoApi is a declarative HTTP client framework for Spring Boot that auto-configures reactive WebClient and blocking RestTemplate instances. Understanding how to customize WebClient and RestClient configurations in CoApi allows you to tune timeouts, add interceptors, and swap underlying HTTP engines without modifying core library code.
Configuration Options Overview
CoApi exposes three distinct layers of customization:
- Property-driven configuration – YAML/properties entries under the
coapiprefix (e.g.,coapi.webclient.connect-timeout). - Customizer beans – Spring beans implementing
WebClientCustomizerorRestTemplateCustomizerthat CoApi auto-detects and applies after its own defaults. - Full bean replacement – Declaring a
@Primary(or named)WebClientorRestTemplatebean causes CoApi’s auto-configuration to back off entirely.
Property-Based Customization
The [CoApiProperties.kt](https://github.com/ahoo-wang/coapi/blob/main/spring-boot-starter/src/main/kotlin/me/ahoo/coapi/spring/boot/starter/CoApiProperties.kt) class maps external configuration to strongly-typed fields. You can set the following keys:
| Property | Type | Description |
|---|---|---|
coapi.webclient.connect-timeout |
Duration |
Connection timeout for the reactive client. |
coapi.webclient.read-timeout |
Duration |
Response read timeout for the reactive client. |
coapi.webclient.max-in-memory-size |
DataSize |
Maximum bytes buffered per response (prevents DataBufferLimitException). |
coapi.restclient.connect-timeout |
Duration |
Connection timeout for the blocking client. |
coapi.restclient.read-timeout |
Duration |
Response read timeout for the blocking client. |
Example application.yml:
coapi:
webclient:
connect-timeout: 5s
read-timeout: 30s
max-in-memory-size: 10MB
restclient:
connect-timeout: 5s
read-timeout: 30s
The [CoApiWebClientCustomizer.kt](https://github.com/ahoo-wang/coapi/blob/main/spring-boot-starter/src/main/kotlin/me/ahoo/coapi/spring/boot/starter/CoApiWebClientCustomizer.kt) and [CoApiRestTemplateCustomizer.kt](https://github.com/ahoo-wang/coapi/blob/main/spring-boot-starter/src/main/kotlin/me/ahoo/coapi/spring/boot/starter/CoApiRestTemplateCustomizer.kt) classes consume these properties and apply them to the underlying builders.
Programmatic Customization with Customizers
When YAML alone is insufficient, you can register Spring beans that implement WebClientCustomizer or RestTemplateCustomizer. CoApi’s auto-configuration detects these beans and invokes them after its own property-based customizer, giving you the final word on configuration.
Customizing the Reactive WebClient
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.web.reactive.function.client.WebClient
import org.springframework.web.reactive.function.client.WebClientCustomizer
@Configuration
class WebClientCustomization {
@Bean
fun loggingWebClientCustomizer(): WebClientCustomizer = WebClientCustomizer { builder ->
builder
.defaultHeader("X-Request-Source", "CoApi-Custom")
.filter { request, next ->
println(">> Sending ${request.method()} request to ${request.url()}")
next.exchange(request)
}
}
}
Customizing the Blocking RestTemplate
import org.springframework.boot.web.client.RestTemplateCustomizer
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.client.ClientHttpRequestInterceptor
import org.springframework.web.client.RestTemplate
import java.util.*
@Configuration
class RestTemplateCustomization {
@Bean
fun traceIdRestTemplateCustomizer(): RestTemplateCustomizer = RestTemplateCustomizer { template ->
template.interceptors.add(ClientHttpRequestInterceptor { request, body, execution ->
request.headers.add("X-Trace-Id", UUID.randomUUID().toString())
execution.execute(request, body)
})
}
}
Because these beans are of type WebClientCustomizer and RestTemplateCustomizer, the [CoApiAutoConfiguration.kt](https://github.com/ahoo-wang/coapi/blob/main/spring-boot-starter/src/main/kotlin/me/ahoo/coapi/spring/boot/starter/CoApiAutoConfiguration.kt) automatically wires them into the client builders.
Complete Bean Replacement
If you need total control—such as swapping the underlying HTTP engine (e.g., OkHttp, Apache HttpClient 5) or applying global SSL settings—you can override the bean entirely.
Replacing the WebClient
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Primary
import org.springframework.web.reactive.function.client.WebClient
import reactor.netty.http.client.HttpClient
import java.time.Duration
@Configuration
class WebClientReplacement {
@Bean
@Primary
fun coapiWebClient(): WebClient {
val httpClient = HttpClient.create()
.responseTimeout(Duration.ofSeconds(45))
.compress(true)
return WebClient.builder()
.clientConnector(ReactorClientHttpConnector(httpClient))
.defaultHeader("X-Custom-Engine", "Netty-Custom")
.build()
}
}
Replacing the RestTemplate
import org.springframework.boot.web.client.RestTemplateBuilder
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Primary
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory
import org.springframework.web.client.RestTemplate
@Configuration
class RestTemplateReplacement {
@Bean
@Primary
fun coapiRestTemplate(): RestTemplate {
val requestFactory = HttpComponentsClientHttpRequestFactory().apply {
setConnectTimeout(2000)
setReadTimeout(20000)
}
return RestTemplate(requestFactory)
}
}
When a bean named coapiWebClient or coapiRestTemplate (or any @Primary bean of the respective type) exists, the @ConditionalOnMissingBean guards in CoApiAutoConfiguration.kt skip the auto‑configuration, ensuring your implementation is used throughout the application.
Summary
- Property-driven: Set
coapi.webclient.*andcoapi.restclient.*in YAML to control timeouts and buffer sizes. - Customizer beans: Implement
WebClientCustomizerorRestTemplateCustomizerto add headers, filters, or interceptors programmatically. - Full replacement: Declare a
@PrimaryWebClientorRestTemplatebean to override the auto‑configured client entirely.
All three mechanisms are supported by the CoApiAutoConfiguration, CoApiProperties, CoApiWebClientCustomizer, and CoApiRestTemplateCustomizer classes in the CoApi Spring‑Boot starter.
Frequently Asked Questions
How do I change the connection timeout for CoApi WebClient?
Set the coapi.webclient.connect-timeout property in your application.yml (e.g., 5s). The CoApiWebClientCustomizer reads this value and applies it to the underlying HttpClient via the WebClient.Builder. If you need more granular control, provide a WebClientCustomizer bean and call builder.clientConnector() with a custom ReactorClientHttpConnector.
Can I use a custom HTTP client like OkHttp with CoApi?
Yes. Declare a @Primary WebClient bean that uses the OkHttpClient connector (via OkHttpClientConnector for WebClient) or a RestTemplate bean that uses OkHttp3ClientHttpRequestFactory. Because the bean is marked @Primary, CoApiAutoConfiguration will skip its own bean creation and use your custom implementation for all CoApi clients.
Why is my custom RestTemplate bean not being used by CoApi?
CoApi’s auto-configuration creates a RestTemplate bean only when no bean of that type exists (@ConditionalOnMissingBean). If your custom bean is not being picked up, ensure it is defined in a configuration class that is scanned by Spring Boot and that it is either named coapiRestTemplate or annotated with @Primary. Also verify that you are not accidentally creating the bean in a profile that is not active.
How do I add a logging interceptor to CoApi requests?
Provide a WebClientCustomizer (for reactive) or RestTemplateCustomizer (for blocking) bean. In the customizer, add a ExchangeFilterFunction to the WebClient.Builder (e.g., builder.filter(ExchangeFilterFunction.ofRequestProcessor { ... })) or add a ClientHttpRequestInterceptor to the RestTemplate. CoApi’s auto-configuration will detect these beans and apply them after the default property-based settings, ensuring your logging logic is active for all CoApi-generated clients.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →