简体   繁体   中英

Safe way to “unwrap” a Mono in a webflux/reactor stream?

I am currently working with a library that makes use of Spring WebFlux and Project Reactor. The main area I am working in is where the reactive stream ends and the data needs to go back into the synchronized, blocking world again. This is unavoidable as the methods I will be interacting with are not reactive-aware (and not modifiable). I'm a newbie at reactive programming so I'm not sure how to go about fixing this.

I am using an interface that looks similar to this:

interface Resolver {
    Mono<Object> resolve(HttpRequest request);
}

I have a class that uses several implementations of the above interface to get some data. I am ultimately left with a HashMap like this:

Mono<Map<String, Mono<Object>>> resolvedData;

What I need at this point is to essentially "unwrap" the Mono<Object> values in the HashMap and have their actual values like this:

Mono<Map<String, Object>> actualResolvedData;

I can't seem to figure out a way to do this cleanly. Whenever I try to call block() directly I get the following exception:

block()/blockFirst()/blockLast() are blocking, which is not supported in thread

I sort of understand the exception but at the same time I no idea how to go about avoiding it. I get that this is not "ideal" reactive programming as the objective is to not block. This is out of my control as this is the point where this data is needed. Am I missing something simple? I've been staring at this code for a few days now and no further along to figuring this out. Any advice would be greatly appreciated. Thanks.

Many thanks to @MartinTarjányi for helping to solve my problem. I was shown a way to map the Mono<Object> output of the Resovler interface to a Tuple before it was made into a Map<String, Object> . That way I could use a regular flatMap to do the first transformation (what I called the "unwrap" in the question) and then convert the Tuple to a Map in a collectMap like before. The full answer is in the comments above but here is how the code was finally fixed:

private Mono<Map<String, Object>> getValues(List<ResolvedData> resolvedData, HttpRequest httpRequest) {
    return Flux.fromIterable(resolvedData).flatMap(data -> {
        Resolver resolver = data.getResolver();
        return resolver.resolve(httpRequest).map(resolvedValue -> Tuples.of(data.getName(), resolvedValue));
    }).collectMap(Tuple2::getT1, Tuple2::getT2);
}

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