2

My goal is to get the HttpStatus from a Spring WebClient request. All other information of the request is irrelevant.

My old way of doing this was:

WebClient.builder().baseUrl("url").build()
        .get().exchange().map(ClientResponse::statusCode).block();

With Spring Boot 2.4.x/Spring 5.3, the exchange method of WebClient is deprecated in favor of retrieve.

With the help of https://stackoverflow.com/a/65791800 i managed to create the following solution.

WebClient.builder().baseUrl("url").build()
        .get().retrieve()
        .toEntity(String.class)
        .flatMap(entity -> Mono.just(entity.getStatusCode()))
        .block();

However, this looks like a very "hacky" way and and does not work when 4xx or 5xx responses are received (In this case the result is null).

Alf
  • 81
  • 1
  • 9
  • 2
    Why are you blocking on a reactive call? Just use `RestTemplate` if you’re blocking anyway. – Boris the Spider Jun 11 '21 at 21:22
  • See also https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/reactive/function/client/WebClient.ResponseSpec.html#toBodilessEntity-- – Boris the Spider Jun 11 '21 at 21:23
  • Finally https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/reactive/function/client/WebClient.RequestHeadersSpec.html#exchangeToMono-java.util.function.Function- – Boris the Spider Jun 11 '21 at 21:26
  • @BoristheSpider Because `RestTemplate` is getting deprecated: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html I prefer not to use functionality that may not be usable in the foreseeable future. – Alf Jun 11 '21 at 21:40
  • where do you see that in the link you posted? – Boris the Spider Jun 11 '21 at 21:48
  • In the class comment @BoristheSpider > NOTE: As of 5.0 this class is in maintenance mode, with only minor requests for changes and bugs to be accepted going forward. Please, consider using the org.springframework.web.reactive.client.WebClient which has a more modern API and supports sync, async, and streaming scenarios. – Alf Jun 11 '21 at 21:49
  • Maintenance mode is **not** deprecation. You’re reading between lines that don’t exist. If you have legacy blocking code use the legacy blocking api. – Boris the Spider Jun 11 '21 at 21:50
  • I agree with you on this point, however to stay consistent within the application I would like to use the WebClient. However, this function should no longer block and use the asynchronous functionality. Task for this is created :) – Alf Jun 11 '21 at 21:57

1 Answers1

3

This problem can be solved with the method exchangeToMono. This results into the following snippet.

WebClient.builder().baseUrl("url").build()
        .get().exchangeToMono(response -> Mono.just(response.statusCode()))
        .block();

The usage of the retrieve method can be improved in the following way, still not very clean.

WebClient.builder().baseUrl("url").build()
        .get().retrieve()
        .onStatus(httpStatus -> true, clientResponse -> {
            //Set variable to return here
            status.set(clientResponse.statusCode());
            return null;
        })
        .toBodilessEntity().block();
Alf
  • 81
  • 1
  • 9
  • as an additional comment, `exchangeToMono` is one of the 2 new methods introduced when `exchange` was deprecated to allow the same functionality as before without the dangers of memory leaks. This is stated on their javadoc https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/reactive/function/client/WebClient.RequestHeadersSpec.html#exchange – Michael McFadyen Jun 12 '21 at 21:20