【问题标题】:ContextNotActiveException while calling @Asynchronous method of @Stateless bean调用@Stateless bean 的@Asynchronous 方法时出现ContextNotActiveException
【发布时间】:2015-04-18 18:25:32
【问题描述】:

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

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

服务类::

@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)

我已经浏览了很多帖子,但问题仍然存在,请帮助我。

【问题讨论】:

  • 这是整个堆栈跟踪吗?另外,您如何构建项目(Maven、Ant)?您确定没有缺少某些依赖项吗? :)
  • 哪个 JBoss AS 版本?无法在 WildFly 8.2 中重现。工作得很好,所以看起来很像 JBoss AS 中使用的 Weld 版本中的错误。可能值得升级到 WildFly 或至少是 WildFly 8.2 中使用的 Weld 版本。
  • 我使用的是 jboss eap 6.1,这不会在任何服务器日志或控制台输出中产生任何错误/异常,但如果您将启动 Java 任务控制并启动 java 飞行记录器,您会看到 ContextNotActiveException在代码>>异常。
  • 您在 Flight Recorder 的异常视图中看到上面的堆栈跟踪了吗?可能是 Flight Recorder 异常事件是在创建异常时创建的,而不是在抛出异常时创建的,这可以解释 JFR 和日志之间的区别。您有实际问题,还是 JFR 中的例外?
  • 我有只在 JFR 中显示的异常,在执行流程时我没有看到任何异常。

标签: java jakarta-ee asynchronous ejb stateless-session-bean


【解决方案1】:

AsyncContext.start 的 javadoc:

用最近的异步注册给定的 AsyncListener 通过调用其中一个启动的循环 ServletRequest.startAsync() 方法。给定的 AsyncListener 将 异步循环完成时接收 AsyncEvent 成功、超时或导致错误。

暗示到此调用时

service.service(asyncContext);

生成后,httpservletrequest“上下文”可能不可用,甚至可能已提交请求,导致 CDI 无法确定您的服务使用的任何“@RequestScoped”bean。

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

您可能希望在调用 AsyncContext.start 之前添加要调用的侦听器

【讨论】:

  • 上面的代码 sn-p 工作正常我能够从 Service.service() 方法发送响应,aysncContext 在 Service.service() 中可用
  • 如果您附加更多堆栈跟踪,我们可以帮助确定 cdi 在哪个执行点失败。如果它在 service.service(asyncContext) 的执行期间,那么请求范围上下文不再处于活动状态的可能性很大。
  • 是的,根据堆栈跟踪,异常发生在 service.service(asyncontext) 调用中,你是对的@maress,因为请求上下文不活动,但不知道如何将请求上下文添加到服务手动上课。
【解决方案2】:

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

ContextNotActiveExcetion 适用于 @RequestScoped bean。您使用AsyncContext.start@Asynchronous EJB 调用启动双重异步处理。

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

当您创建 @SessionScoped bean 并在您的 Service 中注入/访问该 bean 时,您可以导致可见的 ContextNotActiveExcetion

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

【讨论】:

猜你喜欢
  • 2011-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-07
  • 1970-01-01
相关资源
最近更新 更多