11

I am using Asynchronous Servlets to process requests,

According to Docs:(complete(),dispatch())

╔══════════════════╦═══════════════════════════════════════════════════════════╗
║ void complete()  ║ Completes the asynchronous operation and closes the       ║
║                  ║ response associated with this asynchronous context.       ║
║                  ║ You call this method after writing to the response object ║
║                  ║ inside the asynchronous context.                          ║ 
╠══════════════════╬═══════════════════════════════════════════════════════════╣
║ void dispatch()  ║ Dispatches the request and response objects               ║
║                  ║ of this AsyncContext to the servlet container.            ║
╚══════════════════╩═══════════════════════════════════════════════════════════╝

I failed to understand async.dispatch(), async.complete(), and how they work.
I have few doubts on this:

  1. What exactly the difference between async.dispatch() and async.complete()?
  2. When I called dispatch()(inside run()) the response reaches the client, that mean we can push the response asynchronously?
  3. if I call asyncContext.dispatch() first and asyncContext.complete() next what is the behaviour of the thread?
  4. If I call any method after asyncContext.complete(), what will happen to that method call, as shown below code(in the same run())?
    [when I tested this it's working fine and showing same thread id]
  5. If I am calling Asynchronous methods inside run() should I need to complete asyncContext.complete() inside callback()? (onSuccess() or onFailure())
  6. Whether any help(example source/books/online help) available regarding this? (Async Servlets and Futures Combination)

    final FutureCallback<Void> calculateTime= new CustomFuture<>(calculate);
     // start Async context.
     final AsyncContext asyncContext = request.startAsync();
    
      asyncContext.start(new Runnable() {
            @Override
            public void run() {
    
                MyObject object= null;
                try {   
                    object= myFactory.create();
                    //dispatch async context
                    asyncContext.dispatch("Object Successfully Created"); 
                } catch (final IOException e1) {
                    logger.error("logging error");      
                }
                asyncContext.complete(); //complete async context
    
                // call asynchronous method
                final ListenableFuture<Void> future = myService.doSomething();
    
                Futures.addCallback(future, calculateTime);
                // calling asyncContext.complete() here will work?
            }
        });
    

    Thanks in Advance.

Chandra Sekhar
  • 16,256
  • 10
  • 67
  • 90

1 Answers1

18

From the horse's mouth (Oracle Javadoc)

complete()

Completes the asynchronous operation that was started on the request that was used to initialze this AsyncContext, closing the response that was used to initialize this AsyncContext.

Any listeners of type AsyncListener that were registered with the ServletRequest for which this AsyncContext was created will be invoked at their onComplete method.

dispatch(String path)

Dispatches the request and response objects of this AsyncContext to the given path.

...

Control over the request and response is delegated to the dispatch target, and the response will be closed when the dispatch target has completed execution, unless ServletRequest#startAsync() or ServletRequest#startAsync(ServletRequest, ServletResponse) are called.

Q/A

  1. what's the difference between dispatch and complete?

    Calling complete tells container to fire onComplete listeners and stop the asynchronous mode, dispatch basically tells container to call complete and then forward the request (internally) to the specified path. The path can be a JSP, a synchronous servlet or even another asynchronous servlet that will trigger a new round of async processing.

  2. When I called dispatch inside run the response reached the client, does that mean we can push the response asynchronously like this?

    On the contrary dispatch closes the asynchrnonous mode and forwards the request to another servlet or JSP. To push data to the client you have to write to Response object associated with the AsyncContext.

  3. if I call dispatch first and complete next what is the behaviour of the thread ?

    Undefined, which is a nice way of saying it depends on how the container is implemented. Maybe it will throw an error, maybe onComplete handlers will be fired twice, maybe call to complete will do nothing, maybe there will be a race condition between your thread and the container in calling handlers and manipulating internal structures of AsyncContext implementation etc.

  4. If I call any method after complete what will happen to that method call

    Depends on what method you are calling. The specification states that dispatch will throw IllegalStateException if called after complete, anything else is undefined and thus implementation specific.

  5. If I am calling asynchronous methods inside run should I call complete inside callback()?

    Yes you have to call complete to finish asynchronous processing once you are done. The run method is used to schedule a task to be executed by a container managed thread pool and it can be called multiple times during the lifetime of an asynchronous request.

  6. Are there any examples of using Async Servlets and Futures Combination?

    I am not aware of any, but there are a few good examples of using async servlets linked in "See also" section. In principle I don't see much value in using futures. See: "Is async servlet a good fit for what I am doing?"

Is async servlet a good fit for what I am doing ?

The objective of an async servlet is to reduce the number of threads required to serve certain types of "push clients": HTTP request is left open until an (usually external) event occurs and then the server will push data down the channel. In a standard servlet environment each client will have a dedicated thread allocated and waiting thus consuming valuable system resources. In asynchronous mode the client connection can be put "on hold" and detached from an execution thread until an event comes in which makes it possible to do something with it. Think about an online chat application as an example. All connected clients will be idle until someone posts a message to the room. It is wasteful to keep a dedicated thread for every connected user.

If your application needs to call multiple services at the same time and you wish to use futures and executors to parallelize that operation then an asynchronous servlet is probably not a good fit: You will gain nothing and a standard servlet will be much easier to implement. On the other hand if service calls can be made in an asynchronous (non-blocking) way, without relying on threaded executors, then it's another story.

The "right" question to ask is: Do I want to have fewer threads than active connections?


See also:

Community
  • 1
  • 1
anttix
  • 7,709
  • 1
  • 24
  • 25
  • Thank you for your detailed reply, Is there any way to send/push a response/reply after starting asyncContext and continue(without `asyncContext.complete()`) asynchronous process, and after some business logic call `asyncContext.complete()`? – Chandra Sekhar Apr 11 '14 at 13:46
  • Absolutely, you can write your response to the `ServletResponse` object in multiple steps. You can also call `flushBuffer()` to force the data to be sent out to client. However if you are using AJAX on the client, then flushing is not very useful. Streaming with AJAX is tricky: Most AJAX libraries out there will not fire an event handler until the entire response has been received from the server. You have to use `XMLHttpRequest` directly to get access to incomplete response while the request is still active. – anttix Apr 11 '14 at 17:37
  • I tried sending response [Asynchronous Servlet Gist](https://gist.github.com/chandrasekhar4u/10574958) using `flushBuffer()`, but it's not working. Please correct me, If any issue in code. Thanks in advance. – Chandra Sekhar Apr 13 '14 at 08:45
  • Your code works like a charm in Tomcat 7.0.53. You have to use an unbuffered HTTP client to see the effect. When I run this code https://gist.github.com/anttix/10609104 I get: 18:09:56 Response Added. 18:10:01 Response before dispatch 18:10:06 Response final Response – anttix Apr 14 '14 at 01:10
  • Thank you anttirx, Is there any way I can test this from browser or JMeter? – Chandra Sekhar Apr 14 '14 at 03:55
  • XMLHttpRequest has a property called responseText where you can read partial response after readyState = 3. However I haven't tested it. I don't think JMeter http sampler supports reading and graphing partial response times. Best practice for push applications is to complete the request after event data is sent and then client will re-issue it immediately after receiving a response. – anttix Apr 14 '14 at 16:43
  • There is an another point of view on "Is async servlet a good fit for what I am doing ?" section. Check out this presentation http://www.slideshare.net/SimoneBordet/servlet-31-async-io – Imaskar May 28 '15 at 10:08
  • I do not understand the "On the other hand if service calls can be made in an asynchronous (non-blocking) way, without relying on threaded executors, then it's another story." Could you provide an example? I mean, I execute my task inside using a different Thread and at the end call AsyncContext#complete(). How is this NOT beneficial? – LppEdd Oct 08 '18 at 15:59
  • @LppEdd if your task is doing computations and still consumes a thread there is unlikely to be a net gain from async servlet as you're not reducing the number of threads needed to serve requests. The gains can only be realized if the worker thread would be just waiting for something to complete that is not consuming a thread itself. E.g. a message from an external system or a callback from an I/O reactor based async service (http) client. – anttix Oct 18 '18 at 19:53
  • When it comes to examples I'd recommend to refer to the excellent slide deck referenced in the comments above by @lmaskar Quoting from slide #19 - [doAsyncREST] must use async libraries to do its work – anttix Oct 18 '18 at 20:10