Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Asynchronous Servlets and the behaviour of dispatch() and complete() methods while processing request

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.

like image 748
Chandra Sekhar Avatar asked Apr 04 '14 15:04

Chandra Sekhar


1 Answers

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:

  • A state diagram in AsyncStateMachine javadoc (Tomcat implementation).
  • https://blogs.oracle.com/enterprisetechtips/entry/asynchronous_support_in_servlet_3
  • Servlet-3 Async Context, how to do asynchronous writes?
like image 160
anttix Avatar answered Oct 27 '22 05:10

anttix