【问题标题】:Pass request scope data to async methods in CDI将请求范围数据传递给 CDI 中的异步方法
【发布时间】:2016-03-28 19:45:36
【问题描述】:

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;
    }
}

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

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

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

提前致谢。

【问题讨论】:

  • 此外,ApplicationScoped 中有一个 RequestScoped bean。您可能想改用@Inject Instance&lt;CurrentUserService&gt; currentUserBean
  • @Gimby,你是对的。新线程可能会比原来的线程寿命更长。如您所见,我已经使用 ContextService 代理包装了调用。我希望代理将提供所需的上下文信息。无论如何,如何解决问题?我需要从新线程访问请求数据。我能以某种方式通过吗?
  • @jpkrohling,谢谢。我试过但没有运气:(
  • 您的Service.getToken() 方法基本上是同步的。它在未来调用get,这将阻塞直到未来已经实现。所以你所拥有的所有异步机器无论如何都不会完成任何事情。
  • @Steve C,这只是一个例子。

标签: java asynchronous cdi wildfly java-ee-7


【解决方案1】:

根据 Java EE Con​​currency Utilities 规范的 §2.3.2.1,您不应尝试这样做:

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

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

【讨论】:

  • 感谢您的回复。在我的情况下,可以保证任务将在请求范围被销毁之前完成。看起来这是 Wildfly 中的一个错误。我会尝试触发错误报告。感谢您的帮助。
  • CDI 2.1 支持under discussion
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-22
  • 2015-11-24
  • 1970-01-01
相关资源
最近更新 更多