java - 使用 CompletableFutures 和 java 时的 PlayFramework 自定义执行程序

标签 java playframework concurrency completable-future

在最新版本的 PlayFramework 中,他们开始使用 CompletionStage作为将用于异步执行的 Controller 的返回类型,或者简而言之,如果返回 CompletionStage这是异步执行...

现在当我们知道我们提交给 CF 的工作时是一个长期运行的IO操作我们需要传递一个自定义执行器(否则默认会在 FJP 上执行)。

每个 Controller 执行都有一个 HTTP上下文中包含所有请求信息,并且此上下文对于拥有您的 EntityManagers 是必要的。如果您使用 JPA ...

如果我们只是创建自定义 ExecutorService并将其注入(inject)我们的 Controller 中以在 supplyAsync() 中使用我们不会拥有所有上下文信息。

以下是一些 Controller 操作返回 CompletionStage 的示例

return supplyAsync(() -> {
   doSomeWork();
}, executors.io); // this is a custom CachedThreadPool with daemon thread factory

}

如果我们尝试在doSomeWork()中运行类似的东西

Request request = request(); // getting request using Controller.request()

或使用预注入(inject)的JPAAPI jpa Controller 中的字段

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 中定义自定义执行器并从 Actor 系统查找它们,但我最终会得到 MessageDispatcher尽管得到ExecutorService的支持与 CompletableFuture 不兼容(也许我错了?如果是这样,如何将它与CF一起使用?)

最佳答案

您可以使用play.libs.concurrent.HttpExecution.fromThread方法:

An ExecutionContext that executes work on the given ExecutionContext. The current thread's context ClassLoader and Http.Context are captured when this method is called and preserved for all executed tasks.

所以,代码会是这样的:

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

关于java - 使用 CompletableFutures 和 java 时的 PlayFramework 自定义执行程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38195370/

相关文章:

java - 带有分隔符 ' -- ' 的正则表达式,没有递归

java - 从另一个apk获取资源

scala - Play Framework 2 (Scala) 模板 : see if user is logged in

concurrency - 并发编程作用于数组中的每个元素

c# - 为调用堆栈创建一个变量 last

concurrency - 任务不会同时运行

java - 如何获取在远程 Windows 计算机上运行的 java 应用程序的所有线程的堆栈跟踪

java - 如何检查 fragment 在 Activity OnBackpressed 中是否可见

java - JVM 错误? java.lang.VerifyError : Bad type on operand stack

java - Play 框架 2.7.* Java - 已弃用 HTTP 上下文 - 基于 token 的身份验证