doOnNext()不会被调用 Spring Webflux

huangapple go评论62阅读模式
英文:

doOnNext() won't get called Spring Webflux

问题

这是我的方法:

@Override
public Mono<RegistrationVerificationResDTO> verifyCustomerAndGenerateToken(Mono<VerifyOtpReqDTO> verifyOtpReqDTO) {
    return verifyOtpReqDTO
            .flatMap(verifyDTO -> reactiveRedisOperations
                    .opsForValue()
                    .get(RedisDictionary.OTP_KEY + verifyDTO.getPhoneNumber())
                    .filter(otp -> otp.equalsIgnoreCase(verifyDTO.getOtp()))
                    .switchIfEmpty(Mono.error(ForbiddenException::new))
                    .then(Mono.just(verifyDTO))) // Continue with verifyDTO
            .flatMap(verifyDTO -> customerRepository.findById(verifyDTO.getId())
                    .switchIfEmpty(Mono.error(() -> new NotFoundException("Customer not found"))))
            .flatMap(customer -> {
                customer.setVerified(true);
                return customerRepository.save(customer)
                        .thenReturn(customer);
            })
            .map(customer -> new RegistrationVerificationResDTO()
                    .setAccessToken("accessToken")
                    .setRefreshToken("refreshToken")
                    .setCustomer(customer));
}

更新:
我意识到如果我们在 doOnNext 方法内部创建另一个发布者,因为 Spring 只会订阅最外层的发布者,内部的发布者不会被触发。我已经更新了我的代码,但它仍然不起作用。

英文:

I'm a newbie in reactive programming and also Spring Webflux
I have a method to get some key from Redis and if this key is null or is not equals to the specified string i want to throw an exception but the nested donOnNext method won't get called and customerRepository.save(customer) get triggered while the exception must be thrown and break the chain. Can someone explain to me how the reactor API behaves in my case?

this is my method:

@Override
public Mono&lt;RegistrationVerificationResDTO&gt; verifyCustomerAndGenerateToken(Mono&lt;VerifyOtpReqDTO&gt; verifyOtpReqDTO) {
    return verifyOtpReqDTO
            .doOnNext(verifyDTO -&gt; reactiveRedisOperations
                    .opsForValue()
                    .get(RedisDictionary.OTP_KEY + verifyDTO.getPhoneNumber())
                    .filter(otp -&gt; otp.equalsIgnoreCase(verifyDTO.getOtp()))
                    .switchIfEmpty(Mono.error(ForbiddenException::new)))
            .map(verifyDTO -&gt; customerRepository.findById(verifyDTO.getId())
                    .orElseThrow(() -&gt; new NotFoundException(&quot;Customer not found&quot;)))
            .doOnNext(customer -&gt; {
                customer.setVerified(true);
                customerRepository.save(customer);
            })
            .map(customer -&gt; new RegistrationVerificationResDTO().setAccessToken(&quot;accessToken&quot;)
                    .setRefreshToken(&quot;refreshToken&quot;)
                    .setCustomer(customer));
}

UPDATE:
I realized if we create another publisher inside the doOnNext method because the spring just subscribes to the most outer publisher the inner one won't get triggered I have updated my code but it still doesn't work.

答案1

得分: 4

我猜您是在说这个“不起作用”,因为您无法观察到已保存的customer在数据库中,即使在您对第二个(最内层)doOnNext 进行了(正确的)更改后也是如此。

第三个doOnNext 是有问题的:假设customerRepository是一个响应式存储库,customerRepository.save(customer) 是一个无操作操作,因为(惰性的)Mono 既没有连接到主序列,也没有被订阅。

只需将该doOnNext 替换为 flatMap(并且也保留您对最内层的doOnNext 进行的更改,使用switchIfEmpty),以使其成为Spring将订阅的响应式链的一部分。

英文:

I'm guessing you're saying this "doesn't work" because you can't observe the saved customer in DB, even after the (correct) changes you've made to the second (innermost) doOnNext?

The third doOnNext is problematic: customerRepository.save(customer) is a NO-OP assuming customerRepository is a reactive repository, because the (lazy) Mono is neither attached to the main sequence nor subscribed to.

Simply replace that doOnNext with flatMap (and keep your changes to the innermost doOnNext with switchIfEmpty as well) to make it part of the reactive chain that Spring will subscribe to.

huangapple
  • 本文由 发表于 2020年3月4日 03:49:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/60514490.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定