glassfish
  1. glassfish
  2. GLASSFISH-17152

CDI HttpServletRequestContext not active for asynchronous servlet

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 3.1.1
    • Fix Version/s: 4.0_b78
    • Component/s: web_container
    • Labels:
      None
    • Environment:

      Windows 7 (x64), JDK 7 (x64), Eclipse Indigo (3.7), Glassfish Open Source 3.1.1

      Description

      I have a servlet which performs background processing using servlet 3 AsyncContext:

      final AsyncContext context = request.startAsync();
      context.addListener(this);
      context.start(new Runnable() {
      public void run()

      { // [ ... do background RPC call, store result in request ...] context.dispatch(); }

      );

      This will dispatch back to the original servlet which uses a request scoped managed bean, which causes the following exception:

      org.jboss.weld.context.ContextNotActiveException: WELD-001303 No active contexts for scope type javax.enterprise.context.RequestScoped
      at org.jboss.weld.manager.BeanManagerImpl.getContext(BeanManagerImpl.java:664)
      at org.jboss.weld.bean.proxy.ContextBeanInstance.getInstance(ContextBeanInstance.java:77)
      at org.jboss.weld.bean.proxy.ProxyMethodHandler.invoke(ProxyMethodHandler.java:87)
      at [Weld Client Proxy]
      at AuthenticateServlet.doPost(AuthenticateServlet.java:78)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:754)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
      at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1539)
      at org.apache.catalina.core.ApplicationDispatcher.doInvoke(ApplicationDispatcher.java:787)
      at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:649)
      at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:483)
      at org.apache.catalina.core.ApplicationDispatcher.doDispatch(ApplicationDispatcher.java:454)
      at org.apache.catalina.core.ApplicationDispatcher.dispatch(ApplicationDispatcher.java:350)
      at org.apache.catalina.connector.AsyncContextImpl$Handler.run(AsyncContextImpl.java:406)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
      at java.lang.Thread.run(Thread.java:722)

      After some investigation, it seems this is related to Weld ServletRequestListener not be notified of "new" request.

      This also seems to have happened under different conditions as well, both in Glassfish and Tomcat 7:

      https://issues.apache.org/bugzilla/show_bug.cgi?id=49991
      https://issues.apache.org/bugzilla/show_bug.cgi?id=50789

      http://java.net/jira/browse/GLASSFISH-11504
      http://java.net/jira/browse/GLASSFISH-12642 (this fix should have handled my case, but was reverted by change in GLASSFISH-13974)
      http://java.net/jira/browse/GLASSFISH-13974

        Activity

        Hide
        Sivakumar Thyagarajan added a comment -

        RequestScoped Beans do not seem to be available during an async invocation (running in a thread that is different from the thread that initiated the ServletRequest in the Servlet). Shingwai debugged this above and found out that this is due to the ThreadLocal usage to cache RequestScoped Beans in org.jboss.weld.context.cache.RequestScopedBeanCache.

        As per the definition of RequestScoped [3], the request scope must be active until a call to onComplete is done. So, I assume the request scoped bean must also be available in the Servlet when it was dispatched to from the async thread. I am following this up with the weld team. There already seems to be a WELD issue at https://issues.jboss.org/browse/WELD-1020

        Show
        Sivakumar Thyagarajan added a comment - RequestScoped Beans do not seem to be available during an async invocation (running in a thread that is different from the thread that initiated the ServletRequest in the Servlet). Shingwai debugged this above and found out that this is due to the ThreadLocal usage to cache RequestScoped Beans in org.jboss.weld.context.cache.RequestScopedBeanCache. As per the definition of RequestScoped [3] , the request scope must be active until a call to onComplete is done. So, I assume the request scoped bean must also be available in the Servlet when it was dispatched to from the async thread. I am following this up with the weld team. There already seems to be a WELD issue at https://issues.jboss.org/browse/WELD-1020
        Hide
        Joe Di Pol added a comment -

        Since this likely requires a new Weld integration, and it's too late in 3.1.2 for this to happen, I'm excluding from 3.1.2.

        Show
        Joe Di Pol added a comment - Since this likely requires a new Weld integration, and it's too late in 3.1.2 for this to happen, I'm excluding from 3.1.2.
        Hide
        Sivakumar Thyagarajan added a comment -

        The CDI 1.0 spec does not define this behaviour and so we can't expect this to work portably. We are discussing this with the CDI 1.1 group to clarify this in CDI 1.1 and hence this could only be fixed in Weld 2.0 builds when it becomes available. Marking this issue as weld-int-required as well.

        Show
        Sivakumar Thyagarajan added a comment - The CDI 1.0 spec does not define this behaviour and so we can't expect this to work portably. We are discussing this with the CDI 1.1 group to clarify this in CDI 1.1 and hence this could only be fixed in Weld 2.0 builds when it becomes available. Marking this issue as weld-int-required as well.
        Hide
        jjsnyder83 added a comment -

        Committed revision 59872.

        Show
        jjsnyder83 added a comment - Committed revision 59872.
        Hide
        jjsnyder83 added a comment -

        I had to make sure that the weld listener's requestInitialized method was called before the async method was called and make sure that the weld listener's requestDestroyed method was called after the async method was called. This is necessary because CDI requires that a request context is active during async method executions. Calling the Weld listener's methods sets up the request context correctly for Weld.

        Show
        jjsnyder83 added a comment - I had to make sure that the weld listener's requestInitialized method was called before the async method was called and make sure that the weld listener's requestDestroyed method was called after the async method was called. This is necessary because CDI requires that a request context is active during async method executions. Calling the Weld listener's methods sets up the request context correctly for Weld.

          People

          • Assignee:
            Shing Wai Chan
            Reporter:
            Neil Rutherford
          • Votes:
            1 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: