3 Replies Latest reply on Dec 9, 2013 5:11 PM by jameslivingston

    Execution order in async Servlet

    tobias81

      I wrote a very simple asynchronous Servlet:

       

      @WebServlet(name = "MyServlet", urlPatterns = "/myServlet", asyncSupported = true)
      public class MyServlet extends HttpServlet {
      
          @Override
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              System.out.println("Start Servlet");
      
              final AsyncContext asyncContext = request.startAsync(request, response);
              asyncContext.setTimeout(10000);
              asyncContext.start(new Runnable() {
                  @Override
                  public void run() {
                      System.out.println("Start Task");
      
                      try {
                          Thread.sleep(3000);
                          asyncContext.getResponse().getWriter().println("Task done");
                      } catch (Exception e) {
                          e.printStackTrace();
                      }
                      asyncContext.complete();
      
                      System.out.println("Stop Task");
                  }
              });
              response.getWriter().println("Servlet done");
      
              System.out.println("Stop Servlet");
          }
      }
      

       

      My expectation is that the servlets doGet() method terminates immediately and that the overwritten run() method is executed a little bit later. When I package this servlet inside of a WAR file and deploy this in JBoss 7.1.1.Final I get exactly this behaviour:

      11:42:43,323 INFO  [stdout] (http--127.0.0.1-8080-1) Start Servlet

      11:42:43,327 INFO  [stdout] (http--127.0.0.1-8080-1) Stop Servlet

      11:42:43,333 INFO  [stdout] (http--127.0.0.1-8080-1) Start Task

      11:42:46,334 INFO  [stdout] (http--127.0.0.1-8080-1) Stop Task

      But when I deploy the same WAR file in Wildfly 8.0.0.Beta1 the servlet terminates after the task execution:

       

      11:05:37,843 INFO  [stdout] (default task-2) Start Servlet

      11:05:37,854 INFO  [stdout] (default task-2) Start Task

      11:05:40,869 INFO  [stdout] (default task-2) Stop Task

      11:05:40,870 INFO  [stdout] (default task-2) Stop Servlet

      I also tested it on the current nightly build from WildFly-latest-master [Jenkins] (build number #817) but I got the same result.

        • 1. Re: Execution order in async Servlet
          jameslivingston

          Tobias Koltsch wrote:

           

          My expectation is that the servlets doGet() method terminates immediately and that the overwritten run() method is executed a little bit later.

          I can't see anything in the Servlet specification which would require that to be the case, although JBoss AS 7 may have worked that way.

          1 of 1 people found this helpful
          • 2. Re: Re: Execution order in async Servlet
            tobias81

            The Servlet specification says in section "2.3.3.3 Asynchronous processing":

            The asynchronous processing of requests is introduced to allow the thread may return to the container and perform other tasks.

            [...]

            When asyncSupported is set to true the application can start asynchronous processing in a separate thread by calling startAsync (see below), passing it a reference to the request and response objects, and then exit from the container on the original thread.

            So you are absolutely right, the specification only encourages this behaviour but doesn't require it.

            • 3. Re: Execution order in async Servlet
              jameslivingston

              If you want AS 7 style behaviour, it's not too difficult to replicate it via:

              final Object lock = new Object();

              synchronized {

                 asyncContext.start(new Runnable() { 

                  synchronized (lock) {

                    ...

                  }
                }

               

                // rest of servlet code

                ...

              }