Подтвердить что ты не робот

ContextNotActiveException при вызове @Asynchronous метод @Stateless bean

Я вставляю a @Stateless bean в асинхронный сервлет и вызывая метод @Asynchronous из Serrvlet. В журналах сервера jboss я не могу видеть какое-либо из Исключений, но когда я запускаю Java Mission Control, Flight Recorder, я могу видеть ContextNotActiveExcetion, когда Servlet делает вызов метода @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();
            }
        });
    }

Класс обслуживания::

@Stateless
public class Service {

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

трассировка стека, которую я могу видеть в полете Recorder::

      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)

Я проходил много сообщений, но проблема осталась прежней, пожалуйста, помогите мне.

4b9b3361

Ответ 1

Исключение не влияет на функциональность; он обрабатывался под капотом.

ContextNotActiveExcetion применяется к @RequestScoped beans. Вы начинаете двойную асинхронную обработку с помощью AsyncContext.start и вызова @Asynchronous EJB.

Исключением, которое вы видите в полете, является проверка, активен ли контекст по умолчанию RequestScoped и, если это так, действовать. Если контекст RequestScoped не активен, новый EjbRequestContext активируется и ассоциируется с потоком.

Вы можете вызвать видимый ContextNotActiveExcetion при создании @SessionScoped bean и добавить/получить доступ к этому в своем 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();
    }
}

Ответ 2

javadoc для AsyncContext.start:

Регистрирует данный AsyncListener с последним асинхронным цикл, который был инициирован вызовом одной из ServletRequest.startAsync(). Данный AsyncListener будет получить AsyncEvent, когда асинхронный цикл завершается успешно, время ожидания или приводит к ошибке.

Предположим, что к моменту, когда этот вызов

service.service(asyncContext);

Сделано, контекст httpservletrequest может быть недоступен, и запрос может быть даже выполнен, в результате CDI не сможет определить какой-либо "@RequestScoped" beans, используемый вашей службой.

Обратите внимание, что AsyncContext.start регистрирует onEvent для вызова при завершении асинхронного вызова или при ошибке, а не при его запуске.

Возможно, вам захочется добавить прослушиватели, которые будут вызываться перед вызовом AsyncContext.start