6

In the example below from Jetty's docs, a simple method of performing an efficient, asynchronous HTTP request is described. However, it never specifies how you are actually supposed to retrieve the server's reply in this example, and I can't seem to figure it out.

The Result object has getResponse() and getRequest(), but neither of these has methods to access content.

Anyone know?


Jetty's docs

A simple asynchronous GET request can be written in this way:

httpClient.newRequest("http://domain.com/path")
        .send(new Response.CompleteListener()
        {
            @Override
            public void onComplete(Result result)
            {
                // Your logic here
            }
        });

Method Request.send(Response.CompleteListener) returns void and does not block; the Response.CompleteListener provided as a parameter is notified when the request/response conversation is complete, and the Result parameter allows you to access the response object.

Joakim Erdfelt
  • 46,896
  • 7
  • 86
  • 136
Alex
  • 18,332
  • 10
  • 49
  • 53
  • Yes I've been finding the same issues. Some of the documents show calls that are not part of the latest release interface. I am using Jetty 9.2.1 v20140609 (via maven). There's no clear way to find the content from the Result object unless one takes a _leap of faith_ to cast getResponse() as **(ContentResponse) getResponse()** which from the answer below wan't going to work ALSO. Seriously though, examples should show how to do something functional, not just "onComplete{ ... do something ... }. I'm not sure if the current answer clears it up either really. – will Jul 27 '14 at 11:31
  • @will, there is no _leap of faith_ to take, just read the documentation and understand the examples. – sbordet Jul 27 '14 at 22:12

2 Answers2

11

You may want to have the Jetty 9 HttpClient documentation as a reference.

The long answer to your question is explained here, section Response Content Handling.

If you pass a plain CompleteListener to Request.send(CompleteListener), it means that you're not interested in content, which will be thrown away.

If you are interested in content, but only at the completion of the response, you can pass provided utility classes such as BufferingResponseListener:

request.send(new BufferingResponseListener() { ... });

If you are interested in the content as it arrives, you should pass a Response.ContentListener, which will notify you of the content chunk by chunk.

You can do this in two ways: using a Response.Listener (which extends Response.ContentListener):

request.send(new Response.Listener() 
{
    public void onContent(...) { ... }

    public void onComplete(...) { ... }
});

or using multiple listeners:

request.onResponseContent(new Response.ContentListener() { ... });
request.send(new CompleteListener() { ... });

You have all the flexibility you want, and out-of-the-box utility classes that help you (no need to write complex buffering code, just use BufferingResponseListener).

Joakim Erdfelt
  • 46,896
  • 7
  • 86
  • 136
sbordet
  • 16,856
  • 1
  • 50
  • 45
  • I must be viewing different [JavaDoc-s](http://download.eclipse.org/jetty/stable-9/apidocs/index.html?org/eclipse/jetty/client/api/Request.html). The [send(Response.CompleteListener listener)](http://download.eclipse.org/jetty/stable-9/apidocs/index.html?org/eclipse/jetty/client/api/Request.html) method takes a **Response.CompleteListener**, which inherits ONLY from Response.ResponseListener ... Which has NO methods and the source code comment: _Common, empty, super-interface for response listeners_. – will Jul 27 '14 at 12:03
  • CompletedListener and ContentListener are peers. If one did pass Response.Listener that is literally the same semantics as casting one listener to another. While it _might_ work, the semantics unequivocally say do NOT do that. I believe your last suggestion is the better way, respecting the semantics of the interfaces in Jetty 9.2 (anyway). I think the second method should be recommended to Eclipse Jetty Project to changed the Send method to take Request.Listener instead of completed, _personally speaking_ – will Jul 27 '14 at 12:17
  • @will, handing send() take a `Request.Listener` would be plain wrong, so we're not going to do that. The documentation linked in the response shows clearly how to retrieve the content in both the synchronous and the asynchronous way, just read and understand the examples. – sbordet Jul 27 '14 at 22:15
  • @sbordet -- Yes that's exactly what I said, I agree, not only is it "_wrong_". In fact I advocated option #3 (the "_last suggestion_") ... "request.onResponseContent(new Response.ContentListener() { ... });" My irony doesn't translate well. – will Jul 28 '14 at 13:18
0

While the earlier answer (first date: 2013-06_Jun-24) will get you started, more is needed than present in the current (Jetty v9.2) documentation.

The first thing needed is a way to call HttpClient to close/finish processing -- You need to call HttpClient.stop() after the CompleteListener finishes. If that's all we do, the code will sometimes crash (Java Exception), one reliable method to appropriately close the HttpClient is shown here:

The HttpClient.stop() method must be called, otherwise the JVM can be starved of threads (or resources) by Jetty. This was the problem discussed here:

It's also important to do a little housework to ensure threads 'play nice' in a concurrent processing situation.

Community
  • 1
  • 1
will
  • 4,799
  • 8
  • 54
  • 90