javamonoreactive-programmingspring-webfluxspring-reactive

Right using of mapping in WebFlux


public Mono<EmailDto> getEmail() {
Mono<EmailService> emailService = ReactiveSecurityContextHolder.getContext()
                    .map(securityContext -> (Principal) securityContext.getAuthentication().getPrincipal())
                    .map(principal -> emailServiceSelector.selectSuitable(principal.getInfo()));

return emailService.map(service -> service.findInfoByEmail(dto.getManagerEmail())) }

But I have a problem with this method, because emailService.map(service -> service.findInfoByEmail(dto.getManagerEmail())) returns Mono<Mono<EmailDto>>. Implementation of findInfoByEmail(String email) is

public Mono<EmailDto> findInfoByEmail(String email) {
        return webClient.get()
                .uri(emailServiceProperties.getUrl(), email)
                .retrieve()
                .bodyToMono(EmailDto.class);
}

My method returns Mono<EmailDto>, not Mono<Mono<EmailDto>>. So, my question is: How to tranform Mono<Mono<EmailDto>> to Mono<EmailDto>? Or mb I am totally wrong and method should return Mono<Mono<EmailDto>>? Looking forward to any help.


Solution

  • There is a difference between a flatmap and map. flatMap should be used for non-blocking operations, or in short anything which returns back Mono,Flux. map should be used when you want to do the transformation of an object /data in fixed time. The operations which are done synchronously.

    Your findInfoByEmail is making an async call.

    Thus you should use:

    return emailService.flatMap(service -> service.findInfoByEmail(dto.getManagerEmail())) }
    

    This is from the official doc

    flatmap map