Aditya K
Aditya K

Reputation: 185

Spring Boot WebClient Connection and Read Timeout

Currently my post and get requests are handled through WebClients which has a common connection and read timeout in Spring Boot. I have 5 different classes each requiring its own set of connection and read timeout. I don't want to create 5 different WebClients, rather use the same Webclient but while sending a post or a get request from a particular class, specify the required connection and read timeout. Is there any way to implement this?

My current WebClient:

    @Bean
    public WebClient getWebClient(WebClient.Builder builder){

        HttpClient httpClient = HttpClient.newConnection()
                .tcpConfiguration(tcpClient -> {
                    tcpClient = tcpClient.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, connectionTimeout*1000);
                    tcpClient = tcpClient.doOnConnected(conn -> conn
                            .addHandlerLast(new ReadTimeoutHandler(readTimeout, TimeUnit.SECONDS)));
                    return tcpClient;
                }).wiretap(true);

        ClientHttpConnector connector = new ReactorClientHttpConnector(httpClient);

        return builder.clientConnector(connector).build();
    }

A post request I'm using:

public WebClientResponse httpPost(String endpoint, String requestData, Map<String, Object> requestHeader) {

        ClientResponse res = webClient.post().uri(endpoint)
                .body(BodyInserters.fromObject(requestData))
                .headers(x -> {
                    if(requestHeader != null && !requestHeader.isEmpty()) {
                        for (String s : requestHeader.keySet()) {
                            x.set(s, String.valueOf(requestHeader.get(s)));
                        }
                    }
                })
                .exchange()
                .doOnSuccess(x -> log.info("response code = " + x.statusCode()))
                .block();

        return convertWebClientResponse(res);
    }

Upvotes: 6

Views: 25166

Answers (3)

newLearner
newLearner

Reputation: 51

@Bean
public WebClient getWebClient() {
    HttpClient httpClient = HttpClient.create()
            .tcpConfiguration(client ->
                    client.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 4000)
                            .doOnConnected(conn -> conn
                                    .addHandlerLast(new ReadTimeoutHandler(4)) 
                                    .addHandlerLast(new WriteTimeoutHandler(4))));
    ClientHttpConnector connector = new ReactorClientHttpConnector(httpClient.wiretap(true));
    return WebClient.builder()
            .clientConnector(connector)
            .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) // if you need a default header
            .build();
}

or you can use what @Amol has suggested

Upvotes: 0

Amol Damodar
Amol Damodar

Reputation: 369

You can try timeout with webClient like below,

webClient.post()
   .uri(..)
   .body(..)
   .retrieve()
   .
   .
   .
   .timeout(Duration.ofMillis(30);

30 is just example.

Upvotes: 0

Manish Kumar
Manish Kumar

Reputation: 634

You can configure request-level timeout in WebClient.

 webClient.get()
   .uri("https://baeldung.com/path")
   .httpRequest(httpRequest -> {
   HttpClientRequest reactorRequest = httpRequest.getNativeRequest();
   reactorRequest.responseTimeout(Duration.ofSeconds(2));
 });

Now what you can do is that based on the request you can add those values either from the properties file or you can hard code them.

Reference:- https://www.baeldung.com/spring-webflux-timeout

Upvotes: 7

Related Questions