在地图内调用回购操作时,爪哇反应性悬挂

发布于 2025-02-04 08:46:28 字数 2960 浏览 5 评论 0 原文

我是这个反应性世界的新手,当我想将用户映射到另一个用户时遇到问题。

因此,该代码应该转到数据库以基于用户名找到用户,然后需要创建另一个用户对象并通过调用另一个存储库来填充其权威。

然后我需要该值,因此我使用了

Mono<User> userMono = userService.findByUsername(regularUser.getUsername())
            .map(u -> {
                      User user = new User();
                      user.setUsername(u.getUsername());
                      user.setAuthority(userService.getAuthorities(u));
                      return user;
            });
User usr = userMono.block();

我发现每次代码执行块时,它都会停止工作。 DB的请求永远不会完成。我进行了调试,发现在 mono#block - blockingsinglesubscriber#blockingget getCount()是1,它将转到等待(等待( )。这永远需要。我等了,但是 getCount()没有达到0,并且没有 intruptedException 抛出。 blockingget

UserService.java

@Autowired
UserRepository userRepository;

@Autowired
AuthorityRepository authorityRepository;

public Mono<User> findByUsername(String username) {
  return userRepository.findByUsername(username);
}
public Flux<Authority> getAuthorities(User user) {
  return authorityRepository.findAllByUserId(user.getId());
}

我正在使用Spring Boot 2.7.0
io.spring。依赖性管理1.0.11.Release
弹簧启动启动器 - Webflux
Spring-boot-starter-data-mongodb反应性

在地图中调用存储库的问题,

@Bean
public PasswordEncoder passwordEncoder() {
    return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}

@Bean
public ReactiveAuthenticationManager reactiveAuthenticationManager(ReactiveUserDetailsService userDetailsService,
                                                                   PasswordEncoder passwordEncoder) {
    var authenticationManager = new UserDetailsRepositoryReactiveAuthenticationManager(userDetailsService);
    authenticationManager.setPasswordEncoder(passwordEncoder);
    return authenticationManager;
}

@Bean
public ReactiveUserDetailsService userDetailsService(UserService userService) {

    return username -> userService.findByUsername(username)
            .log()
            .map(u -> org.springframework.security.core.userdetails.User
                    .withUsername(u.getUsername()).password(u.getPassword())                                .roles(userService.getRoles(u).toArray(String[]::new))
                    .accountExpired(!u.isActive())
                    .credentialsExpired(!u.isActive())
                    .disabled(!u.isActive())
                    .accountLocked(!u.isActive())
                    .build()
            );
}

反应性用户detailservice bean,如果我硬编码角色(不去数据库),则

它效果很好。我创建了一个简单的项目来复制问题: 第57行。被称为它永远等待。

I'm new to this reactive world and having an issue when I want to map my user to another user.

So the code is supposed to go to DB to find the user based on Username, then will need to create another user object and populate its Authority by calling another repository.

Then I need the value so I used block.

Mono<User> userMono = userService.findByUsername(regularUser.getUsername())
            .map(u -> {
                      User user = new User();
                      user.setUsername(u.getUsername());
                      user.setAuthority(userService.getAuthorities(u));
                      return user;
            });
User usr = userMono.block();

I found that every time the code executes the block, it will stop working. the request to DB is never completed. I debugged and found that in Mono#block - BlockingSingleSubscriber#blockingGet the getCount() is 1, which will go to await(). This takes forever. I waited but the getCount() didn't reach 0 and there was no InterruptedException thrown.
blockingGet

UserService.java

@Autowired
UserRepository userRepository;

@Autowired
AuthorityRepository authorityRepository;

public Mono<User> findByUsername(String username) {
  return userRepository.findByUsername(username);
}
public Flux<Authority> getAuthorities(User user) {
  return authorityRepository.findAllByUserId(user.getId());
}

I'm using Spring Boot 2.7.0
io.spring.dependency-management 1.0.11.RELEASE
spring-boot-starter-webflux
spring-boot-starter-data-mongodb-reactive

Reactive UserDetailService bean that has the problem with calling repository inside a map

@Bean
public PasswordEncoder passwordEncoder() {
    return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}

@Bean
public ReactiveAuthenticationManager reactiveAuthenticationManager(ReactiveUserDetailsService userDetailsService,
                                                                   PasswordEncoder passwordEncoder) {
    var authenticationManager = new UserDetailsRepositoryReactiveAuthenticationManager(userDetailsService);
    authenticationManager.setPasswordEncoder(passwordEncoder);
    return authenticationManager;
}

@Bean
public ReactiveUserDetailsService userDetailsService(UserService userService) {

    return username -> userService.findByUsername(username)
            .log()
            .map(u -> org.springframework.security.core.userdetails.User
                    .withUsername(u.getUsername()).password(u.getPassword())                                .roles(userService.getRoles(u).toArray(String[]::new))
                    .accountExpired(!u.isActive())
                    .credentialsExpired(!u.isActive())
                    .disabled(!u.isActive())
                    .accountLocked(!u.isActive())
                    .build()
            );
}

If I hardcoded the roles (without going to the database) it works well.

I created a simple project that replicate the issue:
https://github.com/skyglassio/repository-await/blob/master/src/main/java/com/example/demo/DevInitializer.java line 57. After userMono.block(); is called it goes into a forever wait.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文