繁体   English   中英

在同一块中使用 Flux 和 Mono 时出现 StackOverflowError

[英]Getting a StackOverflowError when Using Flux and Mono in the same block

我在我的 spring 引导项目中使用WebFlux 我有一段注册用户的代码,它首先检查提交的 email 是否存在于数据库中,如下所示

userRepository.findByEmail(userDto.getEmail())
            .flatMap(t -> {
                UserAlreadyExistException userAlreadyExistException = new UserAlreadyExistException("There is an account with this email address: " + userDto.getEmail());
                Response<?> response = Response.duplicateEntity();
                response.addErrorMsgToResponse(userAlreadyExistException.getMessage(), userAlreadyExistException);
                return Mono.<ResponseEntity<?>>just(ResponseEntity.status(HttpStatus.NOT_ACCEPTABLE)
                        .body(response));
            })

如果提供的 email 确实存在,则返回错误,如果不存在,则应用程序继续并获取分配给该用户的公司和角色列表。 由于这是一个反应式应用程序,我使用zip以便如果提供的companyroles不存在,则应用程序会给出错误,我会这样做

 .switchIfEmpty(Mono.defer(() -> Mono.zip(companyRepository.findById(userDto.getCompanyUuid()), 
                    roleRepository.findAllById(userDto.getRolesUuids()).collectList()))
                    .flatMap(t -> userRepository.save(User.builder()
                            .firstName(userDto.getFirstName())
                            .lastName(userDto.getLastName())
                            .company(t.getT1())
                            .status(userDto.isEnabled() ? BaseModel.Status.ENABLED : BaseModel.Status.DISABLED)
                            .accountStatus(User.AccountStatus.ACCOUNT_ACTIVATED)
                            .email(userDto.getEmail())
                            .profilePhoto(userDto.getProfilePhoto())
                            .roles(t.getT2()).phone(userDto.getPhone())
                            .build()))
                    .flatMap(__ -> Mono.<ResponseEntity<?>>just(ResponseEntity.status(HttpStatus.OK).body(Response.ok())))
                    .switchIfEmpty(Mono.defer(() -> Mono.just(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                            .body(Response.badRequest())))))

当我运行此代码时,它可以运行到zip Mono.zip(companyRepository.findById(userDto.getCompanyUuid()), roleRepository.findAllById(userDto.getRolesUuids()).collectList()))进入无限循环; 遍历角色直到我得到一个stackoverflow,老实说我不理解这种行为,我尝试将其更改为类似

 .switchIfEmpty(Mono.defer(() -> companyRepository.findById(userDto.getCompanyUuid())
                    .flatMap(company -> roleRepository.findAllById(userDto.getRolesUuids())
                            .collectList()
                            .flatMap(roles -> userRepository.save(User.builder()
                                    .firstName(userDto.getFirstName())
                                    .lastName(userDto.getLastName())
                                    .company(company)
                                    .status(userDto.isEnabled() ? BaseModel.Status.ENABLED : BaseModel.Status.DISABLED)
                                    .accountStatus(User.AccountStatus.ACCOUNT_ACTIVATED)
                                    .email(userDto.getEmail())
                                    .profilePhoto(userDto.getProfilePhoto())
                                    .roles(roles)
                                    .phone(userDto.getPhone())
                                    .build()))

                    )
                    .flatMap(__ -> Mono.<ResponseEntity<?>>just(ResponseEntity.status(HttpStatus.OK).body(Response.ok())))
                    .switchIfEmpty(Mono.defer(() -> Mono.just(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                            .body(Response.badRequest()))))))

无济于事,弹出相同的行为。 这里有什么问题?

首先,请尽量避免嵌套平面图 这被认为是一种不好的做法。

其次,您使用的是 zip,因此如果提供的公司或角色不存在,则应用程序会给出错误。

您可以通过以下方式简单地实现:

companyRepository.findById(userDto.getCompanyUuid()
   .switchIfEmpty(Mono.deferWithContext(context -> {
          //do some logging or something with context
          return Mono.error(new SomeException());
        }))
   .zipWith(...)
   ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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