Re: Review of new Http client API

2012-11-02 Thread Michael McMahon

Richard,

It is not part of JDK 8 yet, but you can download and build the source
against JDK7 in Netbeans. We have been running it as a java.net project
at http://java.net/projects/http-client

If you'd prefer me to send you a pre-built jar file I could do that.
However, the API has moved on a bit since the javadoc that you probably 
have.

I could probably send you the javadoc as well though.

- Michael

On 02/11/2012 10:52, Richard Bair wrote:

Hi Michael,

Is there a build of JDK that already has this code in it? The best API review I 
think will come from actually trying to build something with it, which I'd be 
happy to give a try at.

Thanks
Richard

On Aug 14, 2012, at 5:01 AM, Michael McMahon  
wrote:


Hi,

(apologies for sending this again)
We have just published a draft of a proposed new Http client API [1] for JDK 8.

This message has been cc'd to jdk8-dev so that as many people as possible
know about it, but the discussion will be on the net-dev list 
(net-dev@openjdk.java.net).
So, folks will have to join that list [2], in order to take part.

Thanks,
Michael.

[1] http://cr.openjdk.java.net/~michaelm/httpclient/v0.3/

[2] http://mail.openjdk.java.net/mailman/listinfo/net-dev




Re: Review of new Http client API

2012-08-23 Thread Chris Hegarty



On 23/08/2012 16:34, Paul Sandoz wrote:

...

OK, i would be inclined to separate out the instance used for building from the 
instance passed around, so one cannot muck around with the state of the latter.


Agreed, HttpResponse could use a builder pattern.


Then user code may do:

  AsyncHttpRequest request.async()
   .onHeaders(r ->  dumpHeaders(r))
   .onError((r,t) ->  handleError(r,t));
   .onBodyPart((r,bb,c) ->  transformBody(r,bb,t));
  client.sendRequest(request);



If these calls are on* calls are optional and one is not interested in when the 
headers have been received one could omit the onHeaders call, infact all those 
methods could be optional. That certainly simplifies things.


Right.


  

  void dumpHeaders(HttpResponse r) {
  System.out.println(r);
  }
  void handleError(HttpResponse r, t) {
  throw t;
  }
  void transformBody(HttpResponse r, bb, boolean complete) {
  System.out.println("Hello there!");
  }



FWIW you could use method references:

AsyncHttpRequest request.async()
   .onHeaders(whateverthatclassiscalled::dumpHeaders)


Ok, great.

-Chris.


   ...

Paul.



Some experimentation is necessary to find a good balance here.

-Chris.


Re: Review of new Http client API

2012-08-23 Thread Paul Sandoz

On Aug 23, 2012, at 5:16 PM, Michael McMahon  
wrote:

> Paul,
> 
> Thanks for looking at it. Yes, this is an area that needs some more work.
> The current thinking is along the lines that Chris just posted and I hope to
> have another version of the API to look at tomorrow.
> 
> What you suggest seems like an unusual usage of Future<>  as we have tried to 
> provide
> a mode of operation where applications can get a Future
> which would work in the conventional way of returning the result "in the 
> future".

Agreed, it fit well with the underlying asynchronous support in Jersey, which 
was already using the Future, and it bugged me using callback interfaces with 
two methods, where most of the time the error would be swallowed. If there was 
a listener concept for Future in the JDK I would have used that instead.

I think the approach Chris shows easily allows for a default handler when one 
is not supplied.


> But, it raises a question in that while we currently have callback interfaces 
> for both
> headers and data, we only have a Future based interface for headers (but not 
> data).
> 

Indeed!

Paul.


> - Michael
> 
> On 23/08/12 15:20, Paul Sandoz wrote:
>> Hi,
>> 
>> A potential simplification of the HttpResponseHeadersHandler interface is to 
>> turn it into a functional interface:
>> 
>>   HttpResponseHandler onHeaders(Future  dresp) throws 
>> InterruptedException, ExecutionException;
>> 
>> [Chris, i am not sure if an interface with two methods, one default, is 
>> classified as a functional interface.]
>> 
>> - mirrors the pull-based asynchronous approach
>> 
>> - dresp.isDone() always returns true
>> 
>> - the Future encapsulates the underling exception, if any
>> 
>> - harder to swallow errors, since the exception from drep.get() will 
>> propagate if not caught.
>> 
>> - a return of a null HttpResponseHandler means "not interested in the body".
>> 
>> FWIW the use of Future is the approach i chose for the Jersey client.
>> 
>> HttpResponseHandler would also be a functional interface:
>> 
>> void onBodyPart(Future  bb) throws InterruptedException, 
>> ExecutionException
>> 
>> - there is no inheritance relationship between HttpResponseHeadersHandler 
>> and HttpResponseHandler.
>> 
>> - a "bb" with a capacity of 0 indicates the last part.
>> 
>> - the HttpResponse is not required as a parameter because the implementation 
>> can obtain it from the onHeaders method.
>> 
>> If the use of Future is a bit extreme for some :-) then things can still be 
>> simplified by following the above approach with an additional, and optional, 
>> functional interface to handle errors when HttpClient.sendRequest is called.
>> 
>> --
>> 
>> Rather than setting the bytes on the HttpRequest with numerous methods i 
>> wonder if it is better to have a functional interfaces for both OutputStream 
>> and the NIO equivalent:
>> 
>>   interface EntityWriter  { // Oh for disjunct types!
>> /**
>>  * @return true if there is more to write
>>  */
>> boolean write(T t) throws IOException;
>>   }
>> 
>> I believe the above can support all the existing functionality currently 
>> expressed as methods, including the Iterable/Iterator. There can be 
>> instances of EntityWriter for common functionality:
>> 
>>   EntityWriters.fromBytes(byte[] b, ...);
>> 
>> The same might be applicable to HttpResponse with an EntityReader:
>> 
>>   interface EntityReader  {
>> U read(T t) throws IOException;
>>   }
>> 
>> Of course i might be missing something obvious here in terms of optimisation 
>> currently performed by the implementation!
>> 
>> --
>> 
>> It somewhat bugs me that blocking and asynchronous pull/push functionality 
>> is all defined using the same artifacts. But, my imagination is currently is 
>> failing me on how to improve on such matters. Perhaps something better may 
>> come out of fluent-based API?
>> 
>> Paul.
>> 
>> On Aug 14, 2012, at 2:01 PM, Michael McMahon  
>> wrote:
>> 
>>> Hi,
>>> 
>>> (apologies for sending this again)
>>> We have just published a draft of a proposed new Http client API [1] for 
>>> JDK 8.
>>> 
>>> This message has been cc'd to jdk8-dev so that as many people as possible
>>> know about it, but the discussion will be on the net-dev list 
>>> (net-dev@openjdk.java.net).
>>> So, folks will have to join that list [2], in order to take part.
>>> 
>>> Thanks,
>>> Michael.
>>> 
>>> [1] http://cr.openjdk.java.net/~michaelm/httpclient/v0.3/
>>> 
>>> [2] http://mail.openjdk.java.net/mailman/listinfo/net-dev
> 



Re: Review of new Http client API

2012-08-23 Thread Paul Sandoz

On Aug 23, 2012, at 5:05 PM, Chris Hegarty  wrote:

> Paul,
> 
> All good feedback, and I will leave it to Michael to reply to the specifics. 
> On thought I had on separation of modes is something list this:
> 
>  interface HeaderHandler {
>  onHeaders(HttpResponse);
>  }
>  interface ErrorHandler {
>  onError(HttpResponse, Throwable);
>  }
>  interface BodyHandler {
>  onBodyPart(HttpResponse, ByteBuffer, boolean);
>  }
> 
>  class HttpRequest {
>  
>  AsyncHttpRequest async(HttpRequest);
>  
>  }
> 
>  class AsyncHttpRequest extends HttpRequest {
>  // no public constructors
>  
>  AsyncHttpRequest onHeaders(HeaderHandler);
>  AsyncHttpRequest onError(ErrorHandler);
>  AsyncHttpRequest onBodyPart(BodyHandler);
>  }
> 
>  class HttpClient {
>  
>  OutputStream sendHeaders(HttpRequest request, long contentLength)
>  Future sendRequest(HttpRequest req)
>  void sendRequest(AsyncHttpRequest req)
>  }
> 

OK, i would be inclined to separate out the instance used for building from the 
instance passed around, so one cannot muck around with the state of the latter.


> Then user code may do:
> 
>  AsyncHttpRequest request.async()
>   .onHeaders(r -> dumpHeaders(r))
>   .onError((r,t) -> handleError(r,t));
>   .onBodyPart((r,bb,c) -> transformBody(r,bb,t));
>  client.sendRequest(request);
> 

If these calls are on* calls are optional and one is not interested in when the 
headers have been received one could omit the onHeaders call, infact all those 
methods could be optional. That certainly simplifies things.


>  
> 
>  void dumpHeaders(HttpResponse r) {
>  System.out.println(r);
>  }
>  void handleError(HttpResponse r, t) {
>  throw t;
>  }
>  void transformBody(HttpResponse r, bb, boolean complete) {
>  System.out.println("Hello there!");
>  }
> 

FWIW you could use method references:

   AsyncHttpRequest request.async()
  .onHeaders(whateverthatclassiscalled::dumpHeaders)
  ...

Paul.


> Some experimentation is necessary to find a good balance here.
> 
> -Chris.


Re: Review of new Http client API

2012-08-23 Thread Michael McMahon

Paul,

Thanks for looking at it. Yes, this is an area that needs some more work.
The current thinking is along the lines that Chris just posted and I hope to
have another version of the API to look at tomorrow.

What you suggest seems like an unusual usage of Future<>  as we have 
tried to provide

a mode of operation where applications can get a Future
which would work in the conventional way of returning the result "in the 
future".
But, it raises a question in that while we currently have callback 
interfaces for both
headers and data, we only have a Future based interface for headers (but 
not data).


- Michael

On 23/08/12 15:20, Paul Sandoz wrote:

Hi,

A potential simplification of the HttpResponseHeadersHandler interface is to 
turn it into a functional interface:

   HttpResponseHandler onHeaders(Future  dresp) throws 
InterruptedException, ExecutionException;

[Chris, i am not sure if an interface with two methods, one default, is 
classified as a functional interface.]

- mirrors the pull-based asynchronous approach

- dresp.isDone() always returns true

- the Future encapsulates the underling exception, if any

- harder to swallow errors, since the exception from drep.get() will propagate 
if not caught.

- a return of a null HttpResponseHandler means "not interested in the body".

FWIW the use of Future is the approach i chose for the Jersey client.

HttpResponseHandler would also be a functional interface:

 void onBodyPart(Future  bb) throws InterruptedException, 
ExecutionException

- there is no inheritance relationship between HttpResponseHeadersHandler and 
HttpResponseHandler.

- a "bb" with a capacity of 0 indicates the last part.

- the HttpResponse is not required as a parameter because the implementation 
can obtain it from the onHeaders method.

If the use of Future is a bit extreme for some :-) then things can still be 
simplified by following the above approach with an additional, and optional, 
functional interface to handle errors when HttpClient.sendRequest is called.

--

Rather than setting the bytes on the HttpRequest with numerous methods i wonder 
if it is better to have a functional interfaces for both OutputStream and the 
NIO equivalent:

   interface EntityWriter  { // Oh for disjunct types!
 /**
  * @return true if there is more to write
  */
 boolean write(T t) throws IOException;
   }

I believe the above can support all the existing functionality currently 
expressed as methods, including the Iterable/Iterator. There can be instances 
of EntityWriter for common functionality:

   EntityWriters.fromBytes(byte[] b, ...);

The same might be applicable to HttpResponse with an EntityReader:

   interface EntityReader  {
 U read(T t) throws IOException;
   }

Of course i might be missing something obvious here in terms of optimisation 
currently performed by the implementation!

--

It somewhat bugs me that blocking and asynchronous pull/push functionality is 
all defined using the same artifacts. But, my imagination is currently is 
failing me on how to improve on such matters. Perhaps something better may come 
out of fluent-based API?

Paul.

On Aug 14, 2012, at 2:01 PM, Michael McMahon  
wrote:


Hi,

(apologies for sending this again)
We have just published a draft of a proposed new Http client API [1] for JDK 8.

This message has been cc'd to jdk8-dev so that as many people as possible
know about it, but the discussion will be on the net-dev list 
(net-dev@openjdk.java.net).
So, folks will have to join that list [2], in order to take part.

Thanks,
Michael.

[1] http://cr.openjdk.java.net/~michaelm/httpclient/v0.3/

[2] http://mail.openjdk.java.net/mailman/listinfo/net-dev




Re: Review of new Http client API

2012-08-23 Thread Chris Hegarty

Paul,

All good feedback, and I will leave it to Michael to reply to the 
specifics. On thought I had on separation of modes is something list this:


  interface HeaderHandler {
  onHeaders(HttpResponse);
  }
  interface ErrorHandler {
  onError(HttpResponse, Throwable);
  }
  interface BodyHandler {
  onBodyPart(HttpResponse, ByteBuffer, boolean);
  }

  class HttpRequest {
  
  AsyncHttpRequest async(HttpRequest);
  
  }

  class AsyncHttpRequest extends HttpRequest {
  // no public constructors
  
  AsyncHttpRequest onHeaders(HeaderHandler);
  AsyncHttpRequest onError(ErrorHandler);
  AsyncHttpRequest onBodyPart(BodyHandler);
  }

  class HttpClient {
  
  OutputStream sendHeaders(HttpRequest request, long contentLength)
  Future sendRequest(HttpRequest req)
  void sendRequest(AsyncHttpRequest req)
  }

Then user code may do:

  AsyncHttpRequest request.async()
   .onHeaders(r -> dumpHeaders(r))
   .onError((r,t) -> handleError(r,t));
   .onBodyPart((r,bb,c) -> transformBody(r,bb,t));
  client.sendRequest(request);

  

  void dumpHeaders(HttpResponse r) {
  System.out.println(r);
  }
  void handleError(HttpResponse r, t) {
  throw t;
  }
  void transformBody(HttpResponse r, bb, boolean complete) {
  System.out.println("Hello there!");
  }

Some experimentation is necessary to find a good balance here.

-Chris.

On 23/08/2012 15:20, Paul Sandoz wrote:

Hi,

A potential simplification of the HttpResponseHeadersHandler interface is to 
turn it into a functional interface:

   HttpResponseHandler onHeaders(Future  dresp) throws 
InterruptedException, ExecutionException;

[Chris, i am not sure if an interface with two methods, one default, is 
classified as a functional interface.]

- mirrors the pull-based asynchronous approach

- dresp.isDone() always returns true

- the Future encapsulates the underling exception, if any

- harder to swallow errors, since the exception from drep.get() will propagate 
if not caught.

- a return of a null HttpResponseHandler means "not interested in the body".

FWIW the use of Future is the approach i chose for the Jersey client.

HttpResponseHandler would also be a functional interface:

 void onBodyPart(Future  bb) throws InterruptedException, 
ExecutionException

- there is no inheritance relationship between HttpResponseHeadersHandler and 
HttpResponseHandler.

- a "bb" with a capacity of 0 indicates the last part.

- the HttpResponse is not required as a parameter because the implementation 
can obtain it from the onHeaders method.

If the use of Future is a bit extreme for some :-) then things can still be 
simplified by following the above approach with an additional, and optional, 
functional interface to handle errors when HttpClient.sendRequest is called.

--

Rather than setting the bytes on the HttpRequest with numerous methods i wonder 
if it is better to have a functional interfaces for both OutputStream and the 
NIO equivalent:

   interface EntityWriter  { // Oh for disjunct types!
 /**
  * @return true if there is more to write
  */
 boolean write(T t) throws IOException;
   }

I believe the above can support all the existing functionality currently 
expressed as methods, including the Iterable/Iterator. There can be instances 
of EntityWriter for common functionality:

   EntityWriters.fromBytes(byte[] b, ...);

The same might be applicable to HttpResponse with an EntityReader:

   interface EntityReader  {
 U read(T t) throws IOException;
   }

Of course i might be missing something obvious here in terms of optimisation 
currently performed by the implementation!

--

It somewhat bugs me that blocking and asynchronous pull/push functionality is 
all defined using the same artifacts. But, my imagination is currently is 
failing me on how to improve on such matters. Perhaps something better may come 
out of fluent-based API?

Paul.

On Aug 14, 2012, at 2:01 PM, Michael McMahon  
wrote:


Hi,

(apologies for sending this again)
We have just published a draft of a proposed new Http client API [1] for JDK 8.

This message has been cc'd to jdk8-dev so that as many people as possible
know about it, but the discussion will be on the net-dev list 
(net-dev@openjdk.java.net).
So, folks will have to join that list [2], in order to take part.

Thanks,
Michael.

[1] http://cr.openjdk.java.net/~michaelm/httpclient/v0.3/

[2] http://mail.openjdk.java.net/mailman/listinfo/net-dev




Re: Review of new Http client API

2012-08-23 Thread Paul Sandoz
Hi,

A potential simplification of the HttpResponseHeadersHandler interface is to 
turn it into a functional interface:

  HttpResponseHandler onHeaders(Future dresp) throws 
InterruptedException, ExecutionException;

[Chris, i am not sure if an interface with two methods, one default, is 
classified as a functional interface.]

- mirrors the pull-based asynchronous approach

- dresp.isDone() always returns true

- the Future encapsulates the underling exception, if any

- harder to swallow errors, since the exception from drep.get() will propagate 
if not caught.

- a return of a null HttpResponseHandler means "not interested in the body".

FWIW the use of Future is the approach i chose for the Jersey client.

HttpResponseHandler would also be a functional interface:

void onBodyPart(Future bb) throws InterruptedException, 
ExecutionException

- there is no inheritance relationship between HttpResponseHeadersHandler and 
HttpResponseHandler.

- a "bb" with a capacity of 0 indicates the last part.

- the HttpResponse is not required as a parameter because the implementation 
can obtain it from the onHeaders method.

If the use of Future is a bit extreme for some :-) then things can still be 
simplified by following the above approach with an additional, and optional, 
functional interface to handle errors when HttpClient.sendRequest is called.

--

Rather than setting the bytes on the HttpRequest with numerous methods i wonder 
if it is better to have a functional interfaces for both OutputStream and the 
NIO equivalent:

  interface EntityWriter { // Oh for disjunct types!
/**
 * @return true if there is more to write
 */
boolean write(T t) throws IOException;
  }

I believe the above can support all the existing functionality currently 
expressed as methods, including the Iterable/Iterator. There can be instances 
of EntityWriter for common functionality:

  EntityWriters.fromBytes(byte[] b, ...);

The same might be applicable to HttpResponse with an EntityReader:

  interface EntityReader {
U read(T t) throws IOException;
  }

Of course i might be missing something obvious here in terms of optimisation 
currently performed by the implementation!

--

It somewhat bugs me that blocking and asynchronous pull/push functionality is 
all defined using the same artifacts. But, my imagination is currently is 
failing me on how to improve on such matters. Perhaps something better may come 
out of fluent-based API?

Paul.

On Aug 14, 2012, at 2:01 PM, Michael McMahon  
wrote:

> Hi,
> 
> (apologies for sending this again)
> We have just published a draft of a proposed new Http client API [1] for JDK 
> 8.
> 
> This message has been cc'd to jdk8-dev so that as many people as possible
> know about it, but the discussion will be on the net-dev list 
> (net-dev@openjdk.java.net).
> So, folks will have to join that list [2], in order to take part.
> 
> Thanks,
> Michael.
> 
> [1] http://cr.openjdk.java.net/~michaelm/httpclient/v0.3/
> 
> [2] http://mail.openjdk.java.net/mailman/listinfo/net-dev



Re: Review of new Http client API

2012-08-23 Thread Michael McMahon

On 22/08/12 22:09, Sam Pullara wrote:

On Aug 22, 2012, at 1:17 PM, Chris Hegarty wrote:

On 22/08/12 21:05, Michael McMahon wrote:

On 22/08/12 15:29, Chris Hegarty wrote:

Michael what you have looks good.

But, I think what Sam is suggesting ( or maybe not, but I like it ;-)
), is something like this. (I'd need to think more about what effect
this has on the different modes, async/blocking )

Yep, this is exactly what I was suggesting. Thanks for clarifying with code.


class HttpResponse {
   HttpResponse onHeaders(Block);
   HttpResponse onError(BiBlock);
   HttpResponse onBodyPart(BiBlock);
}


Right. I see what you mean in terms of making the setting of the callbacks
fluent. I assume that Block and BiBlock are types associated with Lambda

Right, these are types defined in the lambda repo, that will most likely be 
part of JDK8. Worth a look, and we should also confirm with the lambda folks 
before build them into this API.

Briant Goetz would be the right person to ask. In the meantime, there shouldn't 
be an issue using custom interfaces with a single method (HeaderCallback, 
ErrorCallback, BodyCallback, etc).


Yes, I think that gives us a good fall back in case things develop 
differently in Lambda. For the moment, I will use three
different interfaces, and put some text in the apidoc suggesting they 
might be replaced with standard Lambda types

before JDK8 is finished.

Thanks
Michael.


Sam


somehow,
but otherwise this is unfamiliar territory to me 

response.onHeaders(r ->  headers(r))
 .onError((r,t) ->  error(t))
 .onBodyPart((r,bb) ->  body(r, bb));


So,  headers() and body() would be methods on HttpResponse ... Right ?
What is error()?

No, sorry for the confusion. headers(), error(), and body() are just examples 
of what some user code could be ( rather than cluttering the example with too 
much code ).

-Chris.


- Michael.

Alternatively, I believe something like this would also be compatible
with lambda (since there is a default implementation for on Error):

  interface HTTPResponseHandler {
public void onHeaders(HttpResponse resp);

public void onError(HttpRequest request, Throwable exception)
default { throw exception; }
}

-Chris.


On 21/08/2012 14:57, Michael McMahon wrote:

Sam,

Thanks for the comments. Some discussion below.


On 17/08/12 00:13, Sam Pullara wrote:

I suggest that you make it a more fluent API rather than having
multiple callback methods in your callback interface. As it stands it
isn't compatible with lambdas. You might take some inspiration for the
asynchronous callbacks from my work porting Twitter's Future/Promise
to JDK8:

I agree with the above. In a previous version of the API the main
callback was lambda compatible.
Originally we used HttpResponse to encapsulate everything related to a
response
including errors. But, some preferred to keep HttpResponse aligned to an
actual response
from a server in all cases. There might be other ways to get around that
by combining
HttpResponseHeadersHandler.{onError(), onHeaders()} back into a single
method.
Maybe, drop the onError() method and add the exception/throwable as a
parameter to onHeaders()

But, we also wanted to provide notification of body data (through the
sub-interface HttpResponseHandler).
Keeping the two interfaces distinct meant that applications could get
asynchronous notification of
the response headers, but then possibly read the response body in a
blocking manner.
Or alternatively, applications can use the handler to be notified of
both headers and body.

So, if we revert HttpResponseHeadersHandler back to having a single
method, the sub-interface
now would have two methods (instead of three).

One way around that could be to have two unrelated interfaces:

interface HttpResponseHeadersHandler {
public void onHeaders(HttpResponse response, Exception e);
}

interface HttpResponseBodyHandler {
public void onBodyPart(HttpResponse resp, ByteBuffer buffer, boolean
last);
}

// Then a HttpResponseBodyHandler would be added to
HttpClient.sendRequest() as below:

public void sendRequest(HttpRequest, HttpResponseHeadersHandler,
HttpResponseBodyHandler);


Both of the interfaces would be lambda compatible (again) though at the
cost
of having to specify two separate handlers. So, the following might
be how
it could be used (and using a builder for HttpClient)

HttpClient client = HttpClient.createBuilder()
.setAsynchronousChannelGroup (..)
.setCookieManager(..)
.setDefaultTimeout(..)
.setProxy(...)
.addFilter(...)
.buildClient();

HttpRequest request = client.createRequest(new
URI("http://www.foo.com/";))
.setBody("Hello world".getBytes())
.setMethod(HttpMethod.POST);

client.sendRequest (
request,

// handle headers
(HttpResponse response, Exception e) ->  {
if (response.getResponseCode() != 200) {
// handle error response
}
// handle normal case
},

// handle body
(HttpResponse response, ByteBuffer buf, boolean last) ->  {
// handle data in buf
}
);

It seems fairly r

Re: Review of new Http client API

2012-08-22 Thread Chris Hegarty

On 22/08/12 21:05, Michael McMahon wrote:

On 22/08/12 15:29, Chris Hegarty wrote:

Michael what you have looks good.

But, I think what Sam is suggesting ( or maybe not, but I like it ;-)
), is something like this. (I'd need to think more about what effect
this has on the different modes, async/blocking )

 class HttpResponse {
   HttpResponse onHeaders(Block);
   HttpResponse onError(BiBlock);
   HttpResponse onBodyPart(BiBlock);
 }


Right. I see what you mean in terms of making the setting of the callbacks
fluent. I assume that Block and BiBlock are types associated with Lambda


Right, these are types defined in the lambda repo, that will most likely 
be part of JDK8. Worth a look, and we should also confirm with the 
lambda folks before build them into this API.



somehow,
but otherwise this is unfamiliar territory to me 

 response.onHeaders(r -> headers(r))
 .onError((r,t) -> error(t))
 .onBodyPart((r,bb) -> body(r, bb));


So,  headers() and body() would be methods on HttpResponse ... Right ?
What is error()?


No, sorry for the confusion. headers(), error(), and body() are just 
examples of what some user code could be ( rather than cluttering the 
example with too much code ).


-Chris.



- Michael.

Alternatively, I believe something like this would also be compatible
with lambda (since there is a default implementation for on Error):

  interface HTTPResponseHandler {
public void onHeaders(HttpResponse resp);

public void onError(HttpRequest request, Throwable exception)
default { throw exception; }
 }

-Chris.


On 21/08/2012 14:57, Michael McMahon wrote:

Sam,

Thanks for the comments. Some discussion below.


On 17/08/12 00:13, Sam Pullara wrote:

I suggest that you make it a more fluent API rather than having
multiple callback methods in your callback interface. As it stands it
isn't compatible with lambdas. You might take some inspiration for the
asynchronous callbacks from my work porting Twitter's Future/Promise
to JDK8:


I agree with the above. In a previous version of the API the main
callback was lambda compatible.
Originally we used HttpResponse to encapsulate everything related to a
response
including errors. But, some preferred to keep HttpResponse aligned to an
actual response
from a server in all cases. There might be other ways to get around that
by combining
HttpResponseHeadersHandler.{onError(), onHeaders()} back into a single
method.
Maybe, drop the onError() method and add the exception/throwable as a
parameter to onHeaders()

But, we also wanted to provide notification of body data (through the
sub-interface HttpResponseHandler).
Keeping the two interfaces distinct meant that applications could get
asynchronous notification of
the response headers, but then possibly read the response body in a
blocking manner.
Or alternatively, applications can use the handler to be notified of
both headers and body.

So, if we revert HttpResponseHeadersHandler back to having a single
method, the sub-interface
now would have two methods (instead of three).

One way around that could be to have two unrelated interfaces:

interface HttpResponseHeadersHandler {
public void onHeaders(HttpResponse response, Exception e);
}

interface HttpResponseBodyHandler {
public void onBodyPart(HttpResponse resp, ByteBuffer buffer, boolean
last);
}

// Then a HttpResponseBodyHandler would be added to
HttpClient.sendRequest() as below:

public void sendRequest(HttpRequest, HttpResponseHeadersHandler,
HttpResponseBodyHandler);


Both of the interfaces would be lambda compatible (again) though at the
cost
of having to specify two separate handlers. So, the following might
be how
it could be used (and using a builder for HttpClient)

HttpClient client = HttpClient.createBuilder()
.setAsynchronousChannelGroup (..)
.setCookieManager(..)
.setDefaultTimeout(..)
.setProxy(...)
.addFilter(...)
.buildClient();

HttpRequest request = client.createRequest(new
URI("http://www.foo.com/";))
.setBody("Hello world".getBytes())
.setMethod(HttpMethod.POST);

client.sendRequest (
request,

// handle headers
(HttpResponse response, Exception e) -> {
if (response.getResponseCode() != 200) {
// handle error response
}
// handle normal case
},

// handle body
(HttpResponse response, ByteBuffer buf, boolean last) -> {
// handle data in buf
}
);

It seems fairly readable still, I think.

Another thing that this usage points to, is the usefulness of being able
to hang some user context
off of the HttpResponse or HttpRequest objects. That would be the only
way to share some user state
between the two handlers above, in this Lambda style.

https://github.com/spullara/java-future-jdk8

Another consideration might be to make sure that it is compatible with
an implementation that is using SPDY under the covers for connectivity
as I suspect that HTTP as a wire protocol has peaked though the HTTP
semantics will survive.

Right. This is important. One area where there will be changes is with
pipe-lining.
We

Re: Review of new Http client API

2012-08-22 Thread Michael McMahon

On 22/08/12 15:29, Chris Hegarty wrote:

Michael what you have looks good.

But, I think what Sam is suggesting ( or maybe not, but I like it ;-) 
), is something like this. (I'd need to think more about what effect 
this has on the different modes, async/blocking )


 class HttpResponse {
   HttpResponse onHeaders(Block);
   HttpResponse onError(BiBlock);
   HttpResponse onBodyPart(BiBlock);
 }


Right. I see what you mean in terms of making the setting of the callbacks
fluent. I assume that Block and BiBlock are types associated with Lambda 
somehow,

but otherwise this is unfamiliar territory to me 

 response.onHeaders(r -> headers(r))
 .onError((r,t) -> error(t))
 .onBodyPart((r,bb) -> body(r, bb));


So,  headers() and body() would be methods on HttpResponse ... Right ?
What is error()?

- Michael.
Alternatively, I believe something like this would also be compatible 
with lambda (since there is a default implementation for on Error):


  interface HTTPResponseHandler {
public void onHeaders(HttpResponse resp);

public void onError(HttpRequest request, Throwable exception)
default { throw exception; }
 }

-Chris.


On 21/08/2012 14:57, Michael McMahon wrote:

Sam,

Thanks for the comments. Some discussion below.


On 17/08/12 00:13, Sam Pullara wrote:

I suggest that you make it a more fluent API rather than having
multiple callback methods in your callback interface. As it stands it
isn't compatible with lambdas. You might take some inspiration for the
asynchronous callbacks from my work porting Twitter's Future/Promise
to JDK8:


I agree with the above. In a previous version of the API the main
callback was lambda compatible.
Originally we used HttpResponse to encapsulate everything related to a
response
including errors. But, some preferred to keep HttpResponse aligned to an
actual response
from a server in all cases. There might be other ways to get around that
by combining
HttpResponseHeadersHandler.{onError(), onHeaders()} back into a single
method.
Maybe, drop the onError() method and add the exception/throwable as a
parameter to onHeaders()

But, we also wanted to provide notification of body data (through the
sub-interface HttpResponseHandler).
Keeping the two interfaces distinct meant that applications could get
asynchronous notification of
the response headers, but then possibly read the response body in a
blocking manner.
Or alternatively, applications can use the handler to be notified of
both headers and body.

So, if we revert HttpResponseHeadersHandler back to having a single
method, the sub-interface
now would have two methods (instead of three).

One way around that could be to have two unrelated interfaces:

interface HttpResponseHeadersHandler {
public void onHeaders(HttpResponse response, Exception e);
}

interface HttpResponseBodyHandler {
public void onBodyPart(HttpResponse resp, ByteBuffer buffer, boolean 
last);

}

// Then a HttpResponseBodyHandler would be added to
HttpClient.sendRequest() as below:

public void sendRequest(HttpRequest, HttpResponseHeadersHandler,
HttpResponseBodyHandler);


Both of the interfaces would be lambda compatible (again) though at the
cost
of having to specify two separate handlers. So, the following might 
be how

it could be used (and using a builder for HttpClient)

HttpClient client = HttpClient.createBuilder()
.setAsynchronousChannelGroup (..)
.setCookieManager(..)
.setDefaultTimeout(..)
.setProxy(...)
.addFilter(...)
.buildClient();

HttpRequest request = client.createRequest(new 
URI("http://www.foo.com/";))

.setBody("Hello world".getBytes())
.setMethod(HttpMethod.POST);

client.sendRequest (
request,

// handle headers
(HttpResponse response, Exception e) -> {
if (response.getResponseCode() != 200) {
// handle error response
}
// handle normal case
},

// handle body
(HttpResponse response, ByteBuffer buf, boolean last) -> {
// handle data in buf
}
);

It seems fairly readable still, I think.

Another thing that this usage points to, is the usefulness of being able
to hang some user context
off of the HttpResponse or HttpRequest objects. That would be the only
way to share some user state
between the two handlers above, in this Lambda style.

https://github.com/spullara/java-future-jdk8

Another consideration might be to make sure that it is compatible with
an implementation that is using SPDY under the covers for connectivity
as I suspect that HTTP as a wire protocol has peaked though the HTTP
semantics will survive.

Right. This is important. One area where there will be changes is with
pipe-lining.
We need to ensure that our pipe-lining API is not restricted to only
Http 1.1 pipe-lining
Are you aware of other areas that could have an impact on the API?

Thanks
Michael.


Sam

On Tue, Aug 14, 2012 at 5:01 AM, Michael McMahon
 wrote:

Hi,

(apologies for sending this again)
We have just published a draft of a proposed new Http client API [1]
for JDK
8.

This message has been cc'd to jdk8-dev so that as m

Re: Review of new Http client API

2012-08-22 Thread Chris Hegarty

Michael what you have looks good.

But, I think what Sam is suggesting ( or maybe not, but I like it ;-) ), 
is something like this. (I'd need to think more about what effect this 
has on the different modes, async/blocking )


 class HttpResponse {
   HttpResponse onHeaders(Block);
   HttpResponse onError(BiBlock);
   HttpResponse onBodyPart(BiBlock);
 }

 response.onHeaders(r -> headers(r))
 .onError((r,t) -> error(t))
 .onBodyPart((r,bb) -> body(r, bb));

Alternatively, I believe something like this would also be compatible 
with lambda (since there is a default implementation for on Error):


  interface HTTPResponseHandler {
public void onHeaders(HttpResponse resp);

public void onError(HttpRequest request, Throwable exception)
default { throw exception; }
 }

-Chris.


On 21/08/2012 14:57, Michael McMahon wrote:

Sam,

Thanks for the comments. Some discussion below.


On 17/08/12 00:13, Sam Pullara wrote:

I suggest that you make it a more fluent API rather than having
multiple callback methods in your callback interface. As it stands it
isn't compatible with lambdas. You might take some inspiration for the
asynchronous callbacks from my work porting Twitter's Future/Promise
to JDK8:


I agree with the above. In a previous version of the API the main
callback was lambda compatible.
Originally we used HttpResponse to encapsulate everything related to a
response
including errors. But, some preferred to keep HttpResponse aligned to an
actual response
from a server in all cases. There might be other ways to get around that
by combining
HttpResponseHeadersHandler.{onError(), onHeaders()} back into a single
method.
Maybe, drop the onError() method and add the exception/throwable as a
parameter to onHeaders()

But, we also wanted to provide notification of body data (through the
sub-interface HttpResponseHandler).
Keeping the two interfaces distinct meant that applications could get
asynchronous notification of
the response headers, but then possibly read the response body in a
blocking manner.
Or alternatively, applications can use the handler to be notified of
both headers and body.

So, if we revert HttpResponseHeadersHandler back to having a single
method, the sub-interface
now would have two methods (instead of three).

One way around that could be to have two unrelated interfaces:

interface HttpResponseHeadersHandler {
public void onHeaders(HttpResponse response, Exception e);
}

interface HttpResponseBodyHandler {
public void onBodyPart(HttpResponse resp, ByteBuffer buffer, boolean last);
}

// Then a HttpResponseBodyHandler would be added to
HttpClient.sendRequest() as below:

public void sendRequest(HttpRequest, HttpResponseHeadersHandler,
HttpResponseBodyHandler);


Both of the interfaces would be lambda compatible (again) though at the
cost
of having to specify two separate handlers. So, the following might be how
it could be used (and using a builder for HttpClient)

HttpClient client = HttpClient.createBuilder()
.setAsynchronousChannelGroup (..)
.setCookieManager(..)
.setDefaultTimeout(..)
.setProxy(...)
.addFilter(...)
.buildClient();

HttpRequest request = client.createRequest(new URI("http://www.foo.com/";))
.setBody("Hello world".getBytes())
.setMethod(HttpMethod.POST);

client.sendRequest (
request,

// handle headers
(HttpResponse response, Exception e) -> {
if (response.getResponseCode() != 200) {
// handle error response
}
// handle normal case
},

// handle body
(HttpResponse response, ByteBuffer buf, boolean last) -> {
// handle data in buf
}
);

It seems fairly readable still, I think.

Another thing that this usage points to, is the usefulness of being able
to hang some user context
off of the HttpResponse or HttpRequest objects. That would be the only
way to share some user state
between the two handlers above, in this Lambda style.

https://github.com/spullara/java-future-jdk8

Another consideration might be to make sure that it is compatible with
an implementation that is using SPDY under the covers for connectivity
as I suspect that HTTP as a wire protocol has peaked though the HTTP
semantics will survive.

Right. This is important. One area where there will be changes is with
pipe-lining.
We need to ensure that our pipe-lining API is not restricted to only
Http 1.1 pipe-lining
Are you aware of other areas that could have an impact on the API?

Thanks
Michael.


Sam

On Tue, Aug 14, 2012 at 5:01 AM, Michael McMahon
 wrote:

Hi,

(apologies for sending this again)
We have just published a draft of a proposed new Http client API [1]
for JDK
8.

This message has been cc'd to jdk8-dev so that as many people as
possible
know about it, but the discussion will be on the net-dev list
(net-dev@openjdk.java.net).
So, folks will have to join that list [2], in order to take part.

Thanks,
Michael.

[1]http://cr.openjdk.java.net/~michaelm/httpclient/v0.3/

[2]http://mail.openjdk.java.net/mailman/listinfo/net-dev





Re: Review of new Http client API

2012-08-21 Thread Michael McMahon

Sam,

Thanks for the comments. Some discussion below.


On 17/08/12 00:13, Sam Pullara wrote:

I suggest that you make it a more fluent API rather than having
multiple callback methods in your callback interface. As it stands it
isn't compatible with lambdas. You might take some inspiration for the
asynchronous callbacks from my work porting Twitter's Future/Promise
to JDK8:


I agree with the above. In a previous version of the API the main 
callback was lambda compatible.
Originally we used HttpResponse to encapsulate everything related to a 
response
including errors. But, some preferred to keep HttpResponse aligned to an 
actual response
from a server in all cases. There might be other ways to get around that 
by combining
HttpResponseHeadersHandler.{onError(), onHeaders()} back into a single 
method.
Maybe, drop the onError() method and add the exception/throwable as a 
parameter to onHeaders()


But, we also wanted to provide notification of body data (through the 
sub-interface HttpResponseHandler).
Keeping the two interfaces distinct meant that applications could get 
asynchronous notification of
the response headers, but then possibly read the response body in a 
blocking manner.
Or alternatively, applications can use the handler to be notified of 
both headers and body.


So, if we revert HttpResponseHeadersHandler back to having a single 
method, the sub-interface

now would have two methods (instead of three).

One way around that could be to have two unrelated interfaces:

interface HttpResponseHeadersHandler  {
public void onHeaders(HttpResponse response, Exception e);
}

interface HttpResponseBodyHandler {
public void onBodyPart(HttpResponse resp, ByteBuffer buffer, boolean last);
}

// Then a HttpResponseBodyHandler would be added to HttpClient.sendRequest() as 
below:

public void sendRequest(HttpRequest, HttpResponseHeadersHandler, 
HttpResponseBodyHandler);


Both of the interfaces would be lambda compatible (again) though at the cost
of having to specify two separate handlers. So, the following might be how
it could be used (and using a builder for HttpClient)

HttpClient client = HttpClient.createBuilder()
.setAsynchronousChannelGroup (..)
.setCookieManager(..)
.setDefaultTimeout(..)
.setProxy(...)
.addFilter(...)
.buildClient();

HttpRequest request = client.createRequest(new URI("http://www.foo.com/";))
.setBody("Hello world".getBytes())
.setMethod(HttpMethod.POST);

client.sendRequest (
request,

// handle headers
(HttpResponse response, Exception e) ->  {
if (response.getResponseCode() != 200) {
// handle error response
}
// handle normal case
},

// handle body
(HttpResponse response, ByteBuffer buf, boolean last) ->  {
// handle data in buf
}
);

It seems fairly readable still, I think.

Another thing that this usage points to, is the usefulness of being able 
to hang some user context
off of the HttpResponse or HttpRequest objects. That would be the only 
way to share some user state

between the two handlers above, in this Lambda style.

https://github.com/spullara/java-future-jdk8

Another consideration might be to make sure that it is compatible with
an implementation that is using SPDY under the covers for connectivity
as I suspect that HTTP as a wire protocol has peaked though the HTTP
semantics will survive.
Right. This is important. One area where there will be changes is with 
pipe-lining.
We need to ensure that our pipe-lining API is not restricted to only 
Http 1.1 pipe-lining

Are you aware of other areas that could have an impact on the API?

Thanks
Michael.


Sam

On Tue, Aug 14, 2012 at 5:01 AM, Michael McMahon
  wrote:

Hi,

(apologies for sending this again)
We have just published a draft of a proposed new Http client API [1] for JDK
8.

This message has been cc'd to jdk8-dev so that as many people as possible
know about it, but the discussion will be on the net-dev list
(net-dev@openjdk.java.net).
So, folks will have to join that list [2], in order to take part.

Thanks,
Michael.

[1]http://cr.openjdk.java.net/~michaelm/httpclient/v0.3/

[2]http://mail.openjdk.java.net/mailman/listinfo/net-dev





Review of new Http client API

2012-08-14 Thread Michael McMahon

Hi,

(apologies for sending this again)
We have just published a draft of a proposed new Http client API [1] for 
JDK 8.


This message has been cc'd to jdk8-dev so that as many people as possible
know about it, but the discussion will be on the net-dev list 
(net-dev@openjdk.java.net).

So, folks will have to join that list [2], in order to take part.

Thanks,
Michael.

[1] http://cr.openjdk.java.net/~michaelm/httpclient/v0.3/

[2] http://mail.openjdk.java.net/mailman/listinfo/net-dev


Review of new Http client API

2012-08-13 Thread Michael McMahon

Hi,

We have just published a draft of a proposed new Http client API [1] for 
JDK 8.


This message has been bcc'd to jdk8-dev so that as many people as possible
know about it, but the discussion will be on the net-dev list 
(net-dev@openjdk.java.net).

So, folks will have to join that list [2], in order to take part.

Thanks,
Michael.

[1] http://cr.openjdk.java.net/~michaelm/httpclient/v0.3/

[2] http://mail.openjdk.java.net/mailman/listinfo/net-dev