Uploaded image for project: 'Weld'
  1. Weld
  2. WELD-1774

"Conversation already active" problem on tomcat when asynchronous processing

XMLWordPrintable

    • Hide
      1. dispatch request to the server
      2. switch the request to the async mode (e.g. return a WebAsyncTask on the spring MVC controller with some long running job)
      3. create request which is processed by the same thread as the request from previous point (there is no deterministic way how to achieve this, just trial and error is the way of doing this)
      4. in case the long running job has not finished yet, the exception "Context is already active" is thrown
      Show
      dispatch request to the server switch the request to the async mode (e.g. return a WebAsyncTask on the spring MVC controller with some long running job) create request which is processed by the same thread as the request from previous point (there is no deterministic way how to achieve this, just trial and error is the way of doing this) in case the long running job has not finished yet, the exception "Context is already active" is thrown

      The problem resides inside the standard tomcat valve which processes every incoming request. At the very beginning the valve evaluates whether the request is already considered as asynchronous or not. In the latter case the init event is fired which activates the weld context:

      org.apache.catalina.core.StandardHostValve.java
      if (asyncAtStart || context.fireRequestInitEvent(request)) {
      ...
      }
      

      The if block also contains the execution of the business code which switches the request to the async mode. The following valve code checks the request mode after its procession is finished. In case it has become asynchronous, no destroy event is dispatched which unfortunately keeps the weld context initialized within the running thread:

      org.apache.catalina.core.StandardHostValve.java
      if (!(request.isAsync() || (asyncAtStart &&
                          request.getAttribute(
                                  RequestDispatcher.ERROR_EXCEPTION) != null))) {
          // Protect against NPEs if context was destroyed during a
          // long running request.
          if (context.getState().isAvailable()) {
              ...
              context.fireRequestDestroyEvent(request);
          }
      }
      

      Once the same thread is chosen to serve a request, the "Conversation already active" exception is thrown. Is there any workaround for this? Unfortunately this problem makes it impossible to use the jsf 2.2 on tomcat when using the asynchronous tasks. It's definitely possible to change the weld code to the behaviour that in case the context is already active, it is at first deactivated and subsequentially activated, but it is an awful hack.

              mkouba@redhat.com Martin Kouba
              davido_53 Ondřej David (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

                Created:
                Updated:
                Resolved: