在将CDI添加到我们的应用程序之前,我创建了一个使用@Suspended AsyncResponse
对象实现聊天客户端长轮询的资源。我所做的是为其创建一个新的newSingleThreadExecutor()
和submit
一个Runnable
,在消息列表中使用.wait(30000)
,直到通知新消息已发送。在这个任务中,我使用了HttpServletRequest
,它是使用@Context
获得的,一切都运行得很好。
然而,一旦我们将CDI添加到我们的应用程序中,即使没有使资源类成为bean(仅扫描带注释的bean并且我们没有给它任何范围注释),我得到了一个运行时异常,请求对象INSIDE {{1由于非法状态异常,无法访问任务:
方法抛出'java.lang.IllegalStateException'异常。无法评估com.sun.proxy。$ Proxy74.toString()
我不确定为什么会发生这种情况,但我知道它与CDI有关,因为它引用了代理对象。一个猜测是资源类本身已成为CDI作用域,并且无法从不同的线程访问该作用域?我在某处读到手动启动的线程不受管理,因此无法访问任何与范围相关的对象。但是,在CDI实施之前,这是如何使用的?
现在我认为我已经解决了问题(即释放线程服务请求I / O并让工作人员接管等待通知),使用jersey的Runnable
注释,据说整个方法是在内部球衣执行者服务中运行。它是否正确?同样在这种情况下,是否需要@ManagedAsync
对象?
编辑:我还没有解决这个问题。当资源类未定义为CDI bean时,AsyncResponse
起作用。在设置@ManagedAsync
之后,每当我尝试调用该方法时,我都会得到以下异常
org.jboss.weld.context.ContextNotActiveException:WELD-001303:范围类型javax.enterprise.context.RequestScoped没有活动的上下文
我认为这是因为请求可以在异步线程完成之前结束,这意味着所有范围对象(如HttpServletRequest)都将被销毁,因此我们将无法访问它们。有没有办法在@RequestScoped
bean中使用@ManagedAsync
并使用@RequestScoped
??
TL; DR:
@Context HttpServletRequest
cdi bean中使用@ManagedAsync
?旧方法:
@RequestScoped
目前的非工作方法:
@GET
@Path("method")
public void method(@Context HttpServletRequest request, @Suspended AsyncResponse ar) {
//request object was accessible here
Executors.newSingleTHreadExecutor().submit(() -> {
//request object was also accessible here but lost access after implementing CDI.
Object o = foo.bar(request);
ar.resume(Response.ok(o).build());
});
}
答案 0 :(得分:2)
回答你的问题 - 不。您不能使用异步和请求范围对象。 CDI缺乏异步支持 - 另见https://issues.jboss.org/browse/CDI-452