SledgeHammer
SledgeHammer

Reputation: 7681

How to structure this webClient call correctly?

I have a method that currently looks like this:

protected void doHealthCheck(Health.Builder builder) {
    try {
        VaultHealth vaultHealth = this.webClient
            .get()
            .exchange()
                .block()
                    .bodyToMono(VaultHealth.class)
                        .block();

        if (vaultHealth.isInitialized() && !vaultHealth.isSealed() && !vaultHealth.isStandby()) {
            builder.up();
            return;
        }
    }
    catch (Exception e) {
        builder.down();
        return;
    }

    builder.down();
}

My understanding is that this is wrong. So now I'm looking at fixing it and that it should really be something like:

        this.webClient
            .get()
            .exchange()
                .doOnSuccess(???)
                .doOnError(Health.Builder::down);

.doOnSuccess is going to return a ClientResponse and I need to actually check stuff in the response before I call Health.Builder::up.

if I call .flatMap() instead of doOnSuccess, is it going to throw on an error? Or do I need to put that inside of the doOnSuccess? If I put it inside of the doOnSuccess, it seems like I need to do a double doOnSuccess (that can't be right, can it?):

.doOnSuccess(x -> x.bodyToMono(VaultHealth.class).doOnSuccess(y -> if (y...) builder.up())

Also, I assume if I restructure it this way I don't need the try/catch since the doOnError will handle that?

While this particular method makes sense to execute an action when its done, what about scenarios where I need to return the object? My other understanding is that I should never be using .block, correct?

Upvotes: 0

Views: 491

Answers (1)

K.Nicholas
K.Nicholas

Reputation: 11551

Mono::flatMap is for asynchronous operations. A call to WebClient is an "asynchronous" operation so you'll generally need to use Mono:flatMap after the WebClient::exchange method. No, you should never use Mono::block in a "WebFlux" application. Instead of what you have, do it the reactive way:

    public void run(ApplicationArguments args) throws Exception {
        Health.Builder healthBuilder = new Health.Builder();
        healthBuilder.down();
        doHealthCheck(healthBuilder).onErrorReturn(healthBuilder).map(Health.Builder::build).subscribe(System.out::println);
    }
    protected Mono<Health.Builder> doHealthCheck( Health.Builder builder) {
        return webClient
            .get()
            .retrieve()
            .bodyToMono(VaultHealth.class)
            .map(vaultHealth->{
                if (vaultHealth.isInitialized() && !vaultHealth.isSealed() && !vaultHealth.isStandby())
                    builder.up();
                else 
                    builder.down();
                return builder;
            });
    }

Upvotes: 1

Related Questions