[英]PlayFramework custom executors when using CompletableFutures and java
In latest versions of PlayFramework they started using CompletionStage
as return type for controllers that will be used for async execution or in a nutshell if you return CompletionStage
it is asynchronous execution... 在最新版本的PlayFramework中,他们开始使用
CompletionStage
作为将用于异步执行的控制器的返回类型,或者简而言之,如果返回CompletionStage
则是异步执行...
Now when we know the work we submit to CF
is a long running IO
operation we need to pass a custom executor (otherwise it will be executed on FJP
by default). 现在,当我们知道提交给
CF
的工作是长时间运行的IO
操作时,我们需要传递一个自定义执行程序(否则它将默认在FJP
上执行)。
Each controller execution has a HTTP
context which has in it all the request information also this context is necessary to have your EntityManagers
if you use JPA
... 每个控制器执行都有一个
HTTP
上下文,其中包含所有请求信息,如果使用JPA
则此上下文对于拥有EntityManagers
是必需的。
If we just create custom ExecutorService
and inject it in our controller to use in supplyAsync()
we wont have all the context information. 如果仅创建自定义
ExecutorService
并将其注入到控制器中以便在supplyAsync()
使用,我们将不会获得所有上下文信息。
Here is an example of some controller action returning CompletionStage
这是一些返回
CompletionStage
控制器动作的示例
return supplyAsync(() -> {
doSomeWork();
}, executors.io); // this is a custom CachedThreadPool with daemon thread factory
} }
and if we try to run something like this in doSomeWork()
如果我们尝试在
doSomeWork()
运行类似的doSomeWork()
Request request = request(); // getting request using Controller.request()
or use preinjected JPAAPI jpa
field in controller 或在控制器中使用
JPAAPI jpa
字段
jpa.withTransaction(
() -> jpa.em() // we will get an exception here although we are wrapped in a transaction
...
);
exception like 像这样的异常
No EntityManager bound to this thread. Try wrapping this call in JPAApi.withTransaction, or ensure that the HTTP context is setup on this thread.
As you can see the jpa code is wrapped in transaction but no context was found because this is a custome pure java threadpool. 如您所见,jpa代码包装在事务中,但是未找到任何上下文,因为这是一个纯定制Java线程池。
What is the correct way to provide all the context information when using CompletableFuture and custom executor? 使用CompletableFuture和自定义执行程序时提供所有上下文信息的正确方法是什么?
I also tried defining custom executors in application.conf
and lookup them from actor system but i will end up having MessageDispatcher
which although is backed by ExecutorService
is not compatible with CompletableFuture
(maybe i'm wrong? if so how to use it with CF?) 我还尝试在
application.conf
定义自定义执行application.conf
,并从actor系统中查找它们,但最终我将得到MessageDispatcher
,该MessageDispatcher
虽然由ExecutorService
支持,但与CompletableFuture
不兼容(也许我错了?如果这样,如何在CF中使用它? )
You can use play.libs.concurrent.HttpExecution.fromThread
method: 您可以使用
play.libs.concurrent.HttpExecution.fromThread
方法:
An
ExecutionContext
that executes work on the givenExecutionContext
.一个
ExecutionContext
,它在给定的ExecutionContext
上执行工作。 The current thread's contextClassLoader
andHttp.Context
are captured when this method is called and preserved for all executed tasks.当调用此方法并将其保留用于所有已执行任务时,将捕获当前线程的上下文
ClassLoader
和Http.Context
。
So, the code would be something like: 因此,代码将类似于:
java.util.concurrent.Executor executor = getExecutorFromSomewhere();
return supplyAsync(() -> {
doSomeWork();
}, play.libs.concurrent.HttpExecution.fromThread(executor));
Or, if you are using a scala.concurrent.ExecutionContext
: 或者,如果您使用的是
scala.concurrent.ExecutionContext
:
scala.concurrent.ExecutionContext ec = getExecutorContext();
return supplyAsync(() -> {
doSomeWork();
}, play.libs.concurrent.HttpExecution.fromThread(ec));
But I'm not entirely sure that will preserve the EntityManager
for JPA. 但是我不完全确定会保留用于JPA的
EntityManager
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.