Search code examples
javaasynchronouslistenerjetty-9resource-cleanup

How to notify "content consumed" for Jetty 9.02. ContentListener?


I have a Jetty HttpClient sending Async Requests using Jetty v9.0.2. I have a Response.ContentListener that successfully buffers-up response and a Response.CompeleteListener that is called when the call has completed.

  • Jetty 9.2 JavaDocs has a Request.AsyncContentListener which has a parameter to tell Jetty the content has been consumed:
    • callback - the callback to call when the content is consumed.

This listener type is NOT in the Jetty v9.0.2 Response api:

  • import org.eclipse.jetty.client.api.Result;

There are two questions really:

  1. Does the Response.ContentListener need to notify Jetty client that the content is consumed?
    • If so: how is that managed with Jetty v9.0.2
  2. What kind of clean-up will be required using Async calls with these two Response.ContentListener and Response.CompeleteListener set-up?
    • Are there potential gottchas using async with Jetty v9.0.2?

It seems to be working fine; I need to ensure we have no resource leaks or potential leaks, etc. And of course we need the program to be nice and clean so it can run 24x7. Thanks in advance for your welcome help.

note:


Solution

  • The short answer to this question is to call HttpClient.stop() after the async call has completed processing. A solution approach is outlined in this tutorial example:

    The main aspect is that stop() may not be called until (all) listeners have finished-up and processing has completed. In the example above, a CountdownLatch is used to synchronize the stop() call. This isn't really explained in the Jetty examples, e.g.:

    Some async interfaces use calls like "consume content", etc. However with Jetty 9 the stop() call does the clean-up.

    Our use-case was straight forward enough. In the onComplete() method in the listener, a call is made to a setCompleted() method that decrements a count down latch for the Httpclient.send(). Following the send() call, we have a synchronization method called, finished() that wait on the call for setCompleted().

    public  boolean finish(){
    
        boolean result      = false;
        int     retryCount  =  0;
    
        try
        {
            if( !this.latch.await( 5, TimeUnit.SECONDS ) )
            {
                Util.warn(LOG,"Timed-out -- msg #", String.format("%0,4d", this.msgId) );
            }
    
            this.httpClient.stop();
            result = this.httpClient.isStopped();
        }
        catch (InterruptedException ex )
        {
            log.warn("Interrupted -- msg #", String.format("%0,4d", this.msgId)" );
        }
        catch (Exception ex)
        {
            log.error(LOG,"Stop-exception -- msg #", String.format("%0,4d", this.msgId) );
        }
    
        if( !result )
        {
            log.warn(" * HttpClient NOT stopped -- msg #", String.format("%0,4d", this.msgId) );
        }
    
        return  result;
    }
    

    The stop call seems to be happy with a call as long as the setCompleted() is called at the end of our onComplete() method. I'm not clear if you can't be sure of the internal timing for onComplete. Otherwise it all seems satisfactory. I really believe API documentation should include "clean-up code" for opertations of this kind - data comms, database, etc. Hopefully this posting will save time for others.