简体   繁体   中英

Kotlin Spring Reactive Webflux - Handle WebClient Error

I am having troubles trying to handle different errors from calling Spring webflux's web client.

Below is my current code.

    return request
            .bodyToMono(InputMessage::class.java)
            .flatMap { inputMessage ->
                client
                        .get()
                        .uri { builder ->
                            builder.path("/message")
                                    .queryParam("message", inputMessage.message)
                                    .build()
                        }
                        .retrieve()
                        .onStatus({t: HttpStatus -> t.is5xxServerError}, {c: ClientResponse -> Mono.error(Throwable("Internal Server Error - try again later"))})
                        .bodyToMono(ListOfAddresses::class.java)
            }
            .flatMap { s -> ServerResponse.ok().syncBody(s) }

If it errors, it is still returning the full error message from the client's call.

I tried something else, like this

    return request
            .bodyToMono(InputMessage::class.java)
            .flatMap { inputMessage ->
                client
                        .get()
                        .uri { builder ->
                            builder.path("/message")
                                    .queryParam("message", inputMessage.message)
                                    .build()
                        }
                        .retrieve()
                        .onStatus({t: HttpStatus -> t.is5xxServerError}, {c: ClientResponse -> Mono.error(Throwable("Internal Server Error - try again later"))})
                        .bodyToMono(ListOfAddresses::class.java)
            }
            .flatMap { s -> ServerResponse.ok().syncBody(s) }
            .onErrorResume { e -> Mono.just("Error " + e.message)
                    .flatMap { s -> ServerResponse.ok().syncBody(s) } }

It actually works but then I want to handle different Http status codes error (different messages for each Http status code).

How can I modify my code so it will return the custom message I build?

As per WebFlux documentation, you can user the exchangeToMono() or awaitExchange { } in order to have an error handling.

Mono<Object> entityMono = client.get()
    .uri("/persons/1")
    .accept(MediaType.APPLICATION_JSON)
    .exchangeToMono(response -> {
        if (response.statusCode().equals(HttpStatus.OK)) {
            return response.bodyToMono(Person.class);
        }
        else if (response.statusCode().is4xxClientError()) {
            // Suppress error status code
            return response.bodyToMono(ErrorContainer.class);
        }
        else {
            // Turn to error
            return response.createException().flatMap(Mono::error);
        }
    });

Code copied from WebFlux link above.

Take a look at 2.3. Exchange

val entity = client.get()
  .uri("/persons/1")
  .accept(MediaType.APPLICATION_JSON)
  .awaitExchange {
        if (response.statusCode() == HttpStatus.OK) {
             return response.awaitBody<Person>()
        }
        else if (response.statusCode().is4xxClientError) {
             return response.awaitBody<ErrorContainer>()
        }
        else {
             throw response.createExceptionAndAwait()
        }
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM