![](/img/trans.png)
[英]PlayFramework passing execution context when using CompletableFutures and java
[英]PlayFramework custom executors when using CompletableFutures and java
在最新版本的PlayFramework中,他們開始使用CompletionStage
作為將用於異步執行的控制器的返回類型,或者簡而言之,如果返回CompletionStage
則是異步執行...
現在,當我們知道提交給CF
的工作是長時間運行的IO
操作時,我們需要傳遞一個自定義執行程序(否則它將默認在FJP
上執行)。
每個控制器執行都有一個HTTP
上下文,其中包含所有請求信息,如果使用JPA
則此上下文對於擁有EntityManagers
是必需的。
如果僅創建自定義ExecutorService
並將其注入到控制器中以便在supplyAsync()
使用,我們將不會獲得所有上下文信息。
這是一些返回CompletionStage
控制器動作的示例
return supplyAsync(() -> {
doSomeWork();
}, executors.io); // this is a custom CachedThreadPool with daemon thread factory
}
如果我們嘗試在doSomeWork()
運行類似的doSomeWork()
Request request = request(); // getting request using Controller.request()
或在控制器中使用JPAAPI jpa
字段
jpa.withTransaction(
() -> jpa.em() // we will get an exception here although we are wrapped in a transaction
...
);
像這樣的異常
No EntityManager bound to this thread. Try wrapping this call in JPAApi.withTransaction, or ensure that the HTTP context is setup on this thread.
如您所見,jpa代碼包裝在事務中,但是未找到任何上下文,因為這是一個純定制Java線程池。
使用CompletableFuture和自定義執行程序時提供所有上下文信息的正確方法是什么?
我還嘗試在application.conf
定義自定義執行application.conf
,並從actor系統中查找它們,但最終我將得到MessageDispatcher
,該MessageDispatcher
雖然由ExecutorService
支持,但與CompletableFuture
不兼容(也許我錯了?如果這樣,如何在CF中使用它? )
您可以使用play.libs.concurrent.HttpExecution.fromThread
方法:
一個
ExecutionContext
,它在給定的ExecutionContext
上執行工作。 當調用此方法並將其保留用於所有已執行任務時,將捕獲當前線程的上下文ClassLoader
和Http.Context
。
因此,代碼將類似於:
java.util.concurrent.Executor executor = getExecutorFromSomewhere();
return supplyAsync(() -> {
doSomeWork();
}, play.libs.concurrent.HttpExecution.fromThread(executor));
或者,如果您使用的是scala.concurrent.ExecutionContext
:
scala.concurrent.ExecutionContext ec = getExecutorContext();
return supplyAsync(() -> {
doSomeWork();
}, play.libs.concurrent.HttpExecution.fromThread(ec));
但是我不完全確定會保留用於JPA的EntityManager
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.