Mar*_*dik 8 mongodb spring-data-mongodb spring-boot project-reactor spring-webflux
我选择了,和,创建了一个Spring Springizr的新项目.KotlinGradleM7Web-reactive
我做了一个小项目:
data class Person (val id: String)
@Component class PersonHandler(val template: ReactiveMongoTemplate)
{
init
{
println("Initializing")
val jim: Mono<Person> = template.save(Person("Jim"))
val john: Mono<Person> = template.save(Person("John"))
val jack: Mono<Person> = template.save(Person("Jack"))
launch(jim)
launch(john)
launch(jack)
println("Finished Initializing")
}
fun launch(mono: Mono<Person>)
{
mono.subscribe({println(it.id)}, {println("Error")}) // This works
// mono.block() This just hangs
}
}
Run Code Online (Sandbox Code Playgroud)
我尝试将三个人保存到数据库中.该save方法只返回Mono需要执行的操作.如果我尝试通过简单的订阅来执行它,一切都很好:
Initializing
Finished Initializing
2017-12-21 13:14:39.513 INFO 17278 --- [ Thread-13] org.mongodb.driver.connection : Opened connection [connectionId{localValue:3, serverValue:158}] to localhost:27017
2017-12-21 13:14:39.515 INFO 17278 --- [ Thread-12] org.mongodb.driver.connection : Opened connection [connectionId{localValue:4, serverValue:159}] to localhost:27017
2017-12-21 13:14:39.520 INFO 17278 --- [ Thread-14] org.mongodb.driver.connection : Opened connection [connectionId{localValue:5, serverValue:160}] to localhost:27017
Jim
Jack
John
Run Code Online (Sandbox Code Playgroud)
但是,当我使用block而不是subscribe应用程序挂起时:
Initializing
2017-12-21 13:16:47.200 INFO 17463 --- [ Thread-14] org.mongodb.driver.connection : Opened connection [connectionId{localValue:3, serverValue:163}] to localhost:27017
Run Code Online (Sandbox Code Playgroud)
如果我手动查询数据库,我看到Jim已被保存,但杰克和约翰没有.
这是一个错误,还是我做错了什么?我希望保证用户在代码进一步发展之前都在数据库中,所以我真的很想使用block.
我不确定它是否相关,但我收到编译器警告
template在构造函数中访问非最终属性
有一个最小的工作示例.它包含两个分支.一个是该问题的解决方法.
小智 6
我有一个类似的情况,通过调用“reactiveMongoTemplate.save(model) .block() ”应用程序挂起。
该问题是由我的一个类中的 @PostConstruct 引起的,该类旨在在应用程序初始化后创建我的系统用户。我认为它是在完整的 Spring 上下文初始化之前调用的。
@Configuration
public class InitialDataPostLoader {
private Logger logger = LogManager.getLogger(this.getClass());
@PostConstruct
public void init() {
logger.info(String.format(MSG_SERVICE_JOB, "System Metadata initialization"));
createDefaultUsers();
}
Run Code Online (Sandbox Code Playgroud)
通过用 ContextRefreshEvent 监听器替换 @PostConstruct 问题得到解决。
@Configuration
public class InitialDataPostLoader implements
ApplicationListener<ContextRefreshedEvent> {
private Logger logger = LogManager.getLogger(this.getClass());
@Override
public void onApplicationEvent(ContextRefreshedEvent arg0) {
logger.info(String.format(MSG_SERVICE_JOB, "System Metadata initialization"));
createDefaultUsers();
}
Run Code Online (Sandbox Code Playgroud)
我认为这可能是Spring Framework错误/可用性问题。
首先,我要强调的区别subscribe和block:
subscribe方法开始工作并立即返回。因此,您无法保证在应用程序的其他部分运行时该操作已完成。block 是一个阻塞操作:它触发该操作并等待其完成。对于初始化工作,一次编写操作和调用块可能是最佳选择:
val jim: Mono<Person> = template.save(Person("Jim"))
val john: Mono<Person> = template.save(Person("John"))
val jack: Mono<Person> = template.save(Person("Jack"))
jim.then(john).then(jack).block();
Run Code Online (Sandbox Code Playgroud)
如前所述,使用会block挂起应用程序。我怀疑这可能是Spring上下文初始化问题-如果我没记错的话,此过程可能会在某些部分假设一个线程,并使用反应性管道来安排在多个线程上的工作。
您能否创建一个最小的示例应用程序(仅使用Java / Spring Boot / Spring Data Reactive Mongo)并在https://jira.spring.io上报告该应用程序?
| 归档时间: |
|
| 查看次数: |
2467 次 |
| 最近记录: |