[英]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
以便如果提供的company
或roles
不存在,则应用程序会给出错误,我会这样做
.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.