How to set onStatus in Spring WebClient builder instance
Asked Answered
C

1

10

I've got a lot of methods that use the onStatus API from Spring's WebClient:

@Override
public Mono<Accommodation> createAccommodation(CreateAccommodation create) {
    return webClient
            .post()
            .contentType(APPLICATION_JSON)
            .bodyValue(create)
            .retrieve()
            .onStatus(HttpStatus::isError,
                    clientResponse -> clientResponse
                            .bodyToMono(ApiErrorResponse.class)
                            .flatMap(errorResponse -> Mono.error(new ResponseStatusException(
                                    HttpStatus.valueOf(errorResponse.getStatus()),
                                    errorResponse.getMessage()
                            ))))
            .bodyToMono(Accommodation.class);
}

What I would like to do is to avoid having to use the "onStatus" in every single WebClient call.

Is there a way to set this when building the WebClient instance? Can you show some examples?

This is my WebClient instance:

    public AccommodationServiceClientImpl(WebClient.Builder builder) {
         this.webClient = builder
            .baseUrl("lb://accommodation-service/api/v1/accommodations")
            .build();
    }
Cartage answered 7/5, 2020 at 15:39 Comment(2)
Since retrieve returns an private inner class in Webclient, you would have to extend Webclient with your own version that overrides retrieve() and have it return your own version of ResponseSpecAudible
Actually looks like all the classes are private in the that package for some reason so don't think you can...Audible
C
15

Found a solution: ExchangeFilterFunction.ofResponseProcessor seems to be what I was looking for.

@Configuration
public class WebClientConfig {

    @Bean
    @LoadBalanced
    public WebClient.Builder webClientBuilder(){
        return WebClient
                .builder()
                .filter(ExchangeFilterFunction.ofResponseProcessor(this::renderApiErrorResponse));
    }

    private Mono<ClientResponse> renderApiErrorResponse(ClientResponse clientResponse) {
        if(clientResponse.statusCode().isError()){
            return clientResponse.bodyToMono(ApiErrorResponse.class)
                    .flatMap(apiErrorResponse -> Mono.error(new ResponseStatusException(
                            clientResponse.statusCode(),
                            apiErrorResponse.getMessage()
                    )));
        }
        return Mono.just(clientResponse);
    }

}
Cartage answered 7/5, 2020 at 19:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.