Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/402.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java springframework.data.repository.reactive.reactiveCrudepository.save()从CompletableFuture.runAsync调用时不持久化数据_Java_Spring_Database_Mongodb_Spring Data - Fatal编程技术网

Java springframework.data.repository.reactive.reactiveCrudepository.save()从CompletableFuture.runAsync调用时不持久化数据

Java springframework.data.repository.reactive.reactiveCrudepository.save()从CompletableFuture.runAsync调用时不持久化数据,java,spring,database,mongodb,spring-data,Java,Spring,Database,Mongodb,Spring Data,上下文:我想将数据异步保存到MongoDb。当Front(例如Angular/Mobile)调用控制器端点时,它将调用一个服务方法,目的是首先将数据保存到MongoDb,如果成功,将相同的数据发布到Kafka主题,并调用传递相同数据的另一个端点。为了实现这种行为,我希望使用CompletableFuture并执行“两个步骤”:首先在MongoDb上保存数据,然后(然后是AcceptsSync)将数据发布到Kafka Topic,然后将AcceptsSync发布到另一个rest服务 问题:我完全无

上下文:我想将数据异步保存到MongoDb。当Front(例如Angular/Mobile)调用控制器端点时,它将调用一个服务方法,目的是首先将数据保存到MongoDb,如果成功,将相同的数据发布到Kafka主题,并调用传递相同数据的另一个端点。为了实现这种行为,我希望使用CompletableFuture并执行“两个步骤”:首先在MongoDb上保存数据,然后(然后是AcceptsSync)将数据发布到Kafka Topic,然后将AcceptsSync发布到另一个rest服务

问题:我完全无法完成第一步:将数据保存到MongoDb。我可以同步运行一个简单的system.out.print,但永远不会得到保存数据的ReactiveCrudepository.save()。请参阅下面的代码

我很高兴,其余的都在工作,因为如果我尝试保存而不使用CompletableFuture,那么使用此方法一切都会很好:

//properly working without CompletableFuture
public void SimpleSaveMehtod(Extrato e) {
    extratoRepository.save(e); // .subscribe();
}
下面是服务方法代码,“runPrintAsync.get();”工作正常(打印消息),但“runSaveAsync.get();”根本没有保存。我通过“ForkJoinPool.commonPool().awaitquisition(3,TimeUnit.SECONDS)”进行了一次尝试,但它也不起作用(老实说,如果我用get-btw阻止了它,那么等待是没有意义的,我尝试了它)

@Async(“threadPoolTaskExecutor”)
公共无效转移已返回的无效(附加到e){
ExecutorService newFixedThreadPool=Executors.newFixedThreadPool(2);
CompletableFuture runSaveAsync=CompletableFuture.runAsync(()->extratoRepository.save(e),newFixedThreadPool);
CompletableFuture runPrintAsync=CompletableFuture.runAsync(()->System.out.print(“我被打印”),newFixedThreadPool);
试一试{
//ForkJoinPool.commonPool()等待静止(3,时间单位为秒);
runSaveAsync.get();
runprintsync.get();
}捕获(中断异常|执行异常e1){
e1.printStackTrace();
}
}
如果相关,则存储库如下:

import org.springframework.data.mongodb.repository.Query;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import com.noblockingcase.demo.model.Extrato;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.springframework.data.domain.Pageable;

public interface ExtratoRepository extends ReactiveCrudRepository<Extrato, String> {
    @Query("{ id: { $exists: true }}")
    Flux<Extrato> retrieveAllExtratosPaged(final Pageable page);
}
import org.springframework.data.mongodb.repository.Query;
导入org.springframework.data.repository.reactive.reactivecrudepository;
导入com.noblockingcase.demo.model.Extrato;
导入reactor.core.publisher.Flux;
导入reactor.core.publisher.Mono;
导入org.springframework.data.domain.Pageable;
公共接口extractorepository扩展了reactivecrudepository{
@查询(“{id:{$exists:true}}”)
流量检索AllExtratSphered(最终可分页页面);
}

tl;dr:您需要订阅
Mono

public void SimpleSaveMehtod(Extrato e) {
    extratoRepository.save(e).subscribe();
}
Background:在
Future
上使用反应式类型和类似类型的许多理由之一是,它们允许惰性地执行计算。这意味着,当您创建一个
Mono
Flux
或任何其他结构并添加一些计算时,它将在需要时才会执行


按照现在的编写方式,只要创建了
Mono
,线程就会返回到池中,因为没有更多的工作要做。因为没有订阅,所以在
Mono
中的计算永远不会执行。

您是在
runAsync
中订阅发布服务器吗?不,我知道如果我订阅,我将阻止这一点。我说得对吗?我知道save()返回Mono,subscribe返回Dispose。据我所知,处理dispose的唯一好处是如果我想取消(例如,假设它比我预期的时间长,所以我取消订阅)。因为我无论如何都不想取消,所以我不需要处理。我说得对吗?所以我得出结论,只要保存并返回一个Mono,就会触发另一个线程中的save事件,就在我返回到原始调用方之前,我得到的结果肯定会被阻塞。谢谢。你回答了我的问题。如果可能的话,作为最后一点评论,您认为我在使用响应式驱动程序(springframework.data.repository.reactive.reactivecrudepository)保存数据时使用CompletableFuture.runAsync是在利用这一优势吗?我认为这是值得的,因为我想保存到MongoDb,不要等待MongoDb返回确认。这就是我所想的“不一样地跑步”。我可以稍后检查数据是否存在,在保存过程中不要等待确认。@JimC每次都先创建线程池不是最好的解决方案。如果您不想阻止当前线程等待计算完成,我建议您使用
subscribeOn
,在这里您需要提供workeram I,以便在每次代码运行CompletableFuture.runAsync时创建线程池?我想不是。如果是这样,我真的理解错了。我知道它只是从已经创建的线程池中拾取一个线程。如果您有任何关于subscribeOn/worker的文章或博客可供阅读,以便保存数据而不必等待,我将thanked@JimC看看javadoc,线程池是在每次方法调用时创建的:@JimC我指的是运行
执行器。newFixedThreadPool(2)
,您每次都在创建线程池
public void SimpleSaveMehtod(Extrato e) {
    extratoRepository.save(e).subscribe();
}