调用@Stateless bean 的@Asynchronous 方法时出现ContextNotActiveException

ContextNotActiveException while calling @Asynchronous method of @Stateless bean

我在异步 Servlet 中注入一个 @Stateless bean 并从 Serrvlet 调用 @Asynchronous 方法。在 jboss 的服务器日志中,我看不到任何异常,但是在启动 Java 任务控制、飞行记录器时,每当 Servlet 调用时,我都可以看到 ContextNotActiveExcetion @Asyncrhonous 方法。

Servlet::

@WebServlet(urlPatterns = { "/asyncservice" }, asyncSupported = true)
public class AsyncServiceServlet extends HttpServlet {

@Inject
private Service service;

protected void doPost(final HttpServletRequest request, final HttpServletResponse response)
        throws ServletException, IOException {
    final AsyncContext asyncContext = request.startAsync(request, response);
    asyncContext.start(new Runnable() {
        @Override
        public void run() {
            try {
                service.service(asyncContext);
            } catch (ContextNotActiveException | IOException e) {
                e.printStackTrace();
            }
        });
    }

服务class::

@Stateless
public class Service {

@Asynchronous
public void service(final AsyncContext asyncContext) throws IOException {
    HttpServletResponse res = (HttpServletResponse) asyncContext.getResponse();
    res.setStatus(200);
    asyncContext.complete();
     }
}

我可以在飞行记录器中看到的堆栈跟踪 ::

      java.lang.Throwable.<init>()  4
      java.lang.Exception.<init>()  4
      java.lang.RuntimeException.<init>()   4
      javax.enterprise.context.ContextException.<init>()    4
      javax.enterprise.context.ContextNotActiveException.<init>()   4
      org.jboss.weld.context.ContextNotActiveException.<init>(Enum,Object[])    4
      org.jboss.weld.manager.BeanManagerImpl.getContext(Class)  4
      org.jboss.as.weld.ejb.EjbRequestScopeActivationInterceptor.processInvocation(InterceptorContext)  4
     org.jboss.invocation.InterceptorContext.proceed()  4
        org.jboss.invocation.InitialInterceptor.processInvocation(InterceptorContext)   4
   org.jboss.invocation.InterceptorContext.proceed()    4
     org.jboss.invocation.ChainedInterceptor.processInvocation(InterceptorContext)  4
 org.jboss.as.ee.component.interceptors.ComponentDispatcherInterceptor.processInvocation(InterceptorContext)    4
    org.jboss.invocation.InterceptorContext.proceed()   4
      org.jboss.as.ejb3.component.pool.PooledInstanceInterceptor.processInvocation(InterceptorContext)  4
  org.jboss.invocation.InterceptorContext.proceed() 4
    org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInOurTx(InterceptorContext,TransactionManager,EJBComponent) 4
    org.jboss.as.ejb3.tx.CMTTxInterceptor.required(InterceptorContext,EJBComponent,int) 4
  org.jboss.as.ejb3.tx.CMTTxInterceptor.processInvocation(InterceptorContext)

我看了很多帖子,问题还是一样,请帮帮我。

javadoc AsyncContext.start:

Registers the given AsyncListener with the most recent asynchronous cycle that was started by a call to one of the ServletRequest.startAsync() methods. The given AsyncListener will receive an AsyncEvent when the asynchronous cycle completes successfully, times out, or results in an error.

暗示到此调用

service.service(asyncContext);

已创建,httpservletrequest "context" 可能不可用,甚至可能已提交请求,导致 CDI 无法确定您的服务使用的任何“@RequestScoped”bean。

请注意,AsyncContext.start 注册了一个 onEvent,以便在异步调用完成或出错时调用,而不是在它开始时调用。

您可能希望在调用 AsyncContext.start

之前添加要调用的侦听器

异常对功能没有影响;它在引擎盖下处理。

ContextNotActiveExcetion 适用于 @RequestScoped 个 bean。您使用 AsyncContext.start@Asynchronous EJB 调用开始双异步处理。

您在飞行记录器中看到的异常是为了测试默认 RequestScoped 上下文是否处于活动状态,如果是则继续。如果 RequestScoped 上下文未激活,则会激活新的 EjbRequestContext 并与线程相关联。

当您创建一个 @SessionScoped bean 并且 inject/access 在您的 Service

MySessionScoped.java

@SessionScoped
public class MySessionScoped implements Serializable {

    private int value;

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }
}

Service.java

@Stateless
public class Service {

    @Inject
    private MySessionScoped mySessionScoped;

    @Asynchronous
    public void service(final AsyncContext asyncContext) throws IOException {

        System.out.println(mySessionScoped.getValue());

        HttpServletResponse res = (HttpServletResponse) asyncContext.getResponse();
        res.setStatus(200);
        asyncContext.complete();
    }
}