将请求范围数据传递给 CDI 中的异步方法

Iar*_*kyi 6 java asynchronous cdi java-ee-7 wildfly

Java EE 7 应用程序在 Wildfly 9.0.2.Final 上运行。从@Asynchronous 方法中访问请求范围的数据存在问题。

在 Web 过滤器中,数据(例如令牌)被设置到 RequestScoped CDI bean 中。稍后我们要访问这些数据。如果我们在一个线程中工作,则一切正常。但是如果需要异步运行代码,就会出现问题。CDI 注入空 bean,请求数据丢失。

这是示例:

@RequestScoped
public class CurrentUserService implements Serializable {
  public String token;
}

@Stateless
public class Service {
   @Inject
   private RestClient client;

    @Resource
    private ManagedExecutorService executorService;

    @Resource
    private ContextService contextService;

    @Asynchronous
    private <T> Future<T> getFuture(Supplier<T> supplier) {
        Callable<T> task = supplier::get;
        Callable<T> callable = contextService.createContextualProxy(task, Callable.class);
        return executorService.submit(callable);
    }

   public String getToken() throws Exception {
      return getFuture(client::getToken).get();
   }
}

@ApplicationScoped
public class RestClient {
    @Inject
    private CurrentUserService currentUserBean;

    public String getToken() {
        return currentUserBean.token;
    }
}
Run Code Online (Sandbox Code Playgroud)

在给定的示例中,我们希望从异步 Service.getToken 方法访问当前用户令牌 (CurrentUserService#token)。结果,我们将收到 null。

预计“请求范围”数据应该可以从请求范围内执行的任务中访问。应该使用像 InheritableThreadLocal 这样的东西来允许评估来自新线程的原始线程数据。

这是一个错误吗?可能是我做错了什么?如果是 - 将此类数据传播到异步调用中的正确方法是什么?

提前致谢。

Ste*_*e C 4

根据 Java EE Con​​currency Utilities 规范的 \xc2\xa72.3.2.1,您不应尝试执行此操作:

\n\n
\n
    \n
  • 提交到 ExecutorService 托管实例的任务可能在提交组件的生命周期结束后仍在运行。因此,不建议将范围为@RequestScoped@SessionScoped或 的CDI bean@ConversationScoped用作任务,因为无法保证任务在 CDI 上下文被销毁之前完成。
  • \n
\n
\n\n

无论您使用并发实用程序还是 @Asynchronous 方法,您都需要收集请求范围的数据并在创建异步任务时将其传递给异步任务。

\n