Re: [AsyncWeb] Client redesign

2008-02-10 Thread Alan D. Cabrera


On Feb 9, 2008, at 3:22 PM, Alan D. Cabrera wrote:



On Feb 9, 2008, at 7:42 AM, David M. Lloyd wrote:


4) Future objects for any blocking operation


I was thinking that we could have a Future object that implements an  
AHC callback interface.  This would keep the client simple.  Those  
needing synchronous mechanisms could drop in an instance of this  
Future object.  Just trying to prevent something like:


ah.doThisWay().addListener(bar);

foo = ahc.doAnotherWay();
foo.await();


So, I was thinking that you would send requests like so:

ahc.send(url, listener);

I realize that URL could be in a request object but I've left that  
bit, which might need further discussion, out for the sake of this  
discussion.  I'm also starting w/ the Geronimo AHC because I am most  
familiar with it.


To use a FutureResponseV object which implements  
AsyncHttpClientCallback one would:


FutureResponseApplicationResponse futureResonse = new  
FutureResponseApplicationResponse(builderListener);


ahc.send(url, builderListener);

Here the send call would see that it's being passed an instance of  
FutureResponse and inject the information that the FutureResponse  
needs to be able to cancel the request.  The listener builderListener  
is quite different from the former listener.  It actually builds the  
ApplicationResponse from HTTP response and calls setValue(V value).   
This releases a latch for any call to V get() to proceed.  Calls that  
return nothing could always use Void.


The cool thing about this is that the API stays clean while obtaining  
much more power.


Regards,
Alan






Re: [AsyncWeb] Client redesign

2008-02-10 Thread David M. Lloyd


I think that this bit can be, and is, handled with URLs.  I don't see 
the advantage of adding complexity to the metaphor and, hence, the API.


This isn't a metaphor, it's an API.  Using a metaphor to help conceptualize
what you're trying to accomplish can be helpful, but there's no point in
carrying it any farther than that.  Once you start rejecting an idea because
it doesn't fit you metaphor, you've stepped over that line.  To properly
design a useful API, the only thing that matters are the functional
requirements (i.e., what usecases must the API support?).

In any case, yes, allowing the user to specify a URI to both a connection
and a request would be sufficient to solve this problem.  The key difference
that I want to point out is, the request URI should not be required to be
relative to the connection URI; consequently, the connection URI should not
have a path, query, or fragment part (since the URI is used only for the
purposes of extracting the scheme, host, and port).  In addition, the user-
info part should be part of the request URI (since it can change on a
per-request basis), not the connection URI.

The limitation on what would be allowed on a connection URI is the reason
that I suggested earlier that the API could accept discrete scheme, hostname,
and port parts - since the rest of the URI is not useful anyway.  But since
either method satisfies the requirements (it's just a question of aesthetics
at this point), I'm satisfied either way.

- DML



Re: [AsyncWeb] Client redesign

2008-02-10 Thread David M. Lloyd

Alan D. Cabrera wrote:


On Feb 9, 2008, at 3:22 PM, Alan D. Cabrera wrote:



On Feb 9, 2008, at 7:42 AM, David M. Lloyd wrote:


4) Future objects for any blocking operation


I was thinking that we could have a Future object that implements an 
AHC callback interface.  This would keep the client simple.  Those 
needing synchronous mechanisms could drop in an instance of this 
Future object.  Just trying to prevent something like:


ah.doThisWay().addListener(bar);

foo = ahc.doAnotherWay();
foo.await();


So, I was thinking that you would send requests like so:

ahc.send(url, listener);


This is a departure from the rest of MINA though, in which the idiom
is more like this:

  ahc.send(request).setListener(listener);  // does not block

or:

  ahc.send(request).get(); // blocks

using IoFuture and similar objects.  I think it would be wise to remain
consistent with the MINA idiom in this case.  This method has the
advantage of using java.util.concurrent-style future objects as well as
listeners as proposed above.

- DML


Re: [AsyncWeb] Client redesign

2008-02-10 Thread Tuure Laurinolli

David M. Lloyd wrote:


The limitation on what would be allowed on a connection URI is the reason
that I suggested earlier that the API could accept discrete scheme, 
hostname,

and port parts - since the rest of the URI is not useful anyway.  But since
either method satisfies the requirements (it's just a question of 
aesthetics

at this point), I'm satisfied either way.


More arguments both ways:

Requiring hostname and port instead of an URI for the connection makes 
the user of the connection do URI parsing, which is somewhat ugly, and 
quite repetitive. For the casual user, passing in the URI and letting 
the library handle the ugly bits would be easier. However, parsing the 
URI into hostname and port in the connection adds failure modes to the 
connection, and requires the library to decide what to do in ambiguous 
cases (is it actually specified somewhere that port for an HTTP URI is 
80 if not specified in the URI, for example?).


Of course, the casual user probably doesn't care about connection 
pooling, and possibly not even about pipelining and keep-alive, he just 
wants a component that takes an HttpRequest, does some magic and gets an 
HttpResponse back to the callback he gave to the component.


Re: [AsyncWeb] Client redesign

2008-02-10 Thread David M. Lloyd

Tuure Laurinolli wrote:
Of course, the casual user probably doesn't care about connection 
pooling, and possibly not even about pipelining and keep-alive, he just 
wants a component that takes an HttpRequest, does some magic and gets an 
HttpResponse back to the callback he gave to the component.


Yes, this is my thinking as well - the casual user wants a simplified API,
while the advanced user wants a more detailed interface.

- DML


Re: [AsyncWeb] Client redesign

2008-02-10 Thread Jeff Genender


David M. Lloyd wrote:
 Yes, this is my thinking as well - the casual user wants a simplified API,
 while the advanced user wants a more detailed interface.


Certainly no reason not to offer both capabilities ;-)

Jeff


 - DML


Re: [AsyncWeb] Client redesign

2008-02-10 Thread David M. Lloyd

Alan D. Cabrera wrote:

I see and take your point.  It is six of one and half a dozen of 
another.  What I'm confused about is why we need to initially specify 
anything outside of the actual request.  What problem are we trying to 
solve?  Maybe I'm misunderstanding what you are espousing so let me put 
it in my own words and you tell me if it's accurate.  Please ignore the 
argument of using URIs or discrete parameters for me moment because I 
think that they are obscuring my real concern.


HttpClient client = HttpClientFactory.create(baseURI);
client.send(/foo?pet=cat)

If this is accurate, I don't understand the need for the baseURI.  Maybe 
this is a MINA convention?


OK, I see where the disconnect is.  We agree that the high-level API should
work as you describe.  What was discussed earlier was a second, lower layer
to the API - one in which the user can take direct control over the actual
physical connection and impose their own policy.  Use cases for the lower-
level API would include load-balancing, proxies, and that sort of thing: a
lower-level API for lower-level HTTP functions.  This low-level API would,
through some mechanism, allow connections to be established and maintained
independently of the request mechanism - but in order to do so, there must
be a means to specify the actual connection information: protocol (scheme),
hostname, and port.  How this is done is unimportant, as long as the
functionality is present.  This way you get a balance of power and ease-of-use.

Hopefully this clarifies what I was trying to say.  There was a bit of prior
context to the discussion, which I guess I was relying on a bit too much. :-)

- DML


Re: [AsyncWeb] Client redesign

2008-02-10 Thread Alan D. Cabrera


On Feb 10, 2008, at 10:35 AM, David M. Lloyd wrote:


Alan D. Cabrera wrote:

On Feb 9, 2008, at 3:22 PM, Alan D. Cabrera wrote:


On Feb 9, 2008, at 7:42 AM, David M. Lloyd wrote:


4) Future objects for any blocking operation


I was thinking that we could have a Future object that implements  
an AHC callback interface.  This would keep the client simple.   
Those needing synchronous mechanisms could drop in an instance of  
this Future object.  Just trying to prevent something like:


ah.doThisWay().addListener(bar);

foo = ahc.doAnotherWay();
foo.await();

So, I was thinking that you would send requests like so:
ahc.send(url, listener);


This is a departure from the rest of MINA though, in which the idiom
is more like this:

 ahc.send(request).setListener(listener);  // does not block

or:

 ahc.send(request).get(); // blocks

using IoFuture and similar objects.  I think it would be wise to  
remain

consistent with the MINA idiom in this case.  This method has the
advantage of using java.util.concurrent-style future objects as well  
as

listeners as proposed above.


Ok, makes sense to me and there's great value at carrying on that  
convention in AHC.



Regards,
Alan



Re: [AsyncWeb] Client redesign

2008-02-10 Thread Alan D. Cabrera


On Feb 10, 2008, at 10:05 AM, David M. Lloyd wrote:



I think that this bit can be, and is, handled with URLs.  I don't  
see the advantage of adding complexity to the metaphor and, hence,  
the API.


This isn't a metaphor, it's an API.  Using a metaphor to help  
conceptualize
what you're trying to accomplish can be helpful, but there's no  
point in
carrying it any farther than that.  Once you start rejecting an idea  
because
it doesn't fit you metaphor, you've stepped over that line.  To  
properly

design a useful API, the only thing that matters are the functional
requirements (i.e., what usecases must the API support?).


We shall agreed to disagree here.

I fully understand the need for compelling use cases to drive the  
API.  A clean metaphor means a clean API.  A great metaphor helps  
users quickly and accurately assimilate an API.  Slavishly extending  
an API in an ad hoc manner, and I'm not claiming that this is what you  
are doing, to support use cases more often than not leads to a  
Byzantine API that is hard to use.  A good metaphor is very important.


In any case, yes, allowing the user to specify a URI to both a  
connection
and a request would be sufficient to solve this problem.  The key  
difference
that I want to point out is, the request URI should not be required  
to be
relative to the connection URI; consequently, the connection URI  
should not
have a path, query, or fragment part (since the URI is used only for  
the
purposes of extracting the scheme, host, and port).  In addition,  
the user-

info part should be part of the request URI (since it can change on a
per-request basis), not the connection URI.

The limitation on what would be allowed on a connection URI is the  
reason
that I suggested earlier that the API could accept discrete scheme,  
hostname,
and port parts - since the rest of the URI is not useful anyway.   
But since
either method satisfies the requirements (it's just a question of  
aesthetics

at this point), I'm satisfied either way.



I see and take your point.  It is six of one and half a dozen of  
another.  What I'm confused about is why we need to initially specify  
anything outside of the actual request.  What problem are we trying to  
solve?  Maybe I'm misunderstanding what you are espousing so let me  
put it in my own words and you tell me if it's accurate.  Please  
ignore the argument of using URIs or discrete parameters for me moment  
because I think that they are obscuring my real concern.


HttpClient client = HttpClientFactory.create(baseURI);
client.send(/foo?pet=cat)

If this is accurate, I don't understand the need for the baseURI.   
Maybe this is a MINA convention?



Regards,
Alan






Re: [AsyncWeb] Client redesign

2008-02-10 Thread Sangjin Lee
Going back on some of the points here...
On Jan 29, 2008 2:25 PM, Mike Heath [EMAIL PROTECTED] wrote:


 Connecting - Connecting is done as a blocking operation.  In Jeff
 Geneder's AHC branch in the Geronimo sandbox, thread pools are being
 used for asynchronous connecting.  This is unfortunate since MINA
 already has this functionality and does it in a much lighter weight
 manner than using a thread pool.


I'm a little confused as to what you mean when you say connecting is done
as a blocking operation.  You are not saying AHC's connect is done as a
blocking operation, right? :)  As for the thread pool, I thought Mina's
socket connector involves a thread pool (Executor) one way or the other, no?
 Is there a way to use connectors without involving a thread pool (whether
the caller supplies one or the socket connector constructors creates one)?





 Completion Notification - With the existing AHC, there's a single
 callback for the Client.  I REALLY like the observable future pattern
 that MINA uses.  With each asynchronous operation, a future object is
 returned.  This future object can be used to block until the operation
 completes.  The future is also observable so you can also register one
 or more completion listeners with the future.  This makes it real easy
 to do a fork/join like operation like:

 future1 = doAsynch1();
 future2 = doAsynch2();
 future3 = doAsynch3();

 future1.await()
 future2.await()
 future3.await()

 or use an event driven approach like:

 doAsynch1().addListener(...);
 doAsynch2().addListener(...);
 doAsynch3().addListener(...);

 This provides maximum flexibility.  This should be incorporated into
 AsyncWeb client.


If you look at the current AHC code, it actually *does* use both future
(ResponseFuture) and a callback (AsyncHttpClientCallback).  Both correspond
to the future and the future listener, so it ended up being something very
similar to what mina's future does.  It would take a trivial refactoring to
reshape it to look like Mina's future.

Another thing it supports is a completion queue.  One can fire multiple
non-blocking send() calls to multiple URLs, and sit on the completion queue
to handle the results as they arrive.  Although callers can write their own
code to do things like this, supporting it at the API level would be a nice
thing to keep.  This comes in pretty handy in a scatter-and-gather
situation...

My 2 cents...

Thanks,
Sangjin


Re: [AsyncWeb] Client redesign

2008-02-10 Thread (Trustin Lee)
First off, I agree with what's under consensus so far in this thread.
Great to see more people get involved! :)

2008-02-09 (토), 17:01 -0800, Alan D. Cabrera 쓰시길:
 On Feb 9, 2008, at 3:56 PM, Mike Heath wrote:
 
  Alan D. Cabrera wrote:
 
  snip
 
  That's a good thought.  The reason that the URL was originally put  
  in the
  HttpClient constructor (as well as the request) was to allow the
  management
  of connections to be separated from the URL request.   
  Realistically, a
  URL
  could be dropped in favor of discrete scheme/hostname/port  
  parameters on
  an connection object.  Though it's not always desirable to do  
  this, so
  specifying and maintaining a physical connection should be an  
  optional
  kind
  of thing to do.
 
  Not sure why one needs to specify the URL so far in advance.
 
  I like the idea of specifying a base URI for the HttpClient.  So you  
  use
  a base URI of something like http://somedomain.foo; and subsequent
  requests could then do something like get(/bar) which would do a GET
  on http://somedomain.foo/bar;.
 
  This would require further abstraction than what AHC has to offer  
  currently.
 
 I think that this bit can be, and is, handled with URLs.  I don't see  
 the advantage of adding complexity to the metaphor and, hence, the API.

You mean the java.net.URL class?

Trustin
-- 
what we call human nature is actually human habit
--
http://gleamynode.net/


signature.asc
Description: This is a digitally signed message part


Re: [AsyncWeb] Client redesign

2008-02-10 Thread Alex Karasulu
On Feb 11, 2008 1:28 AM, Mike Heath [EMAIL PROTECTED] wrote:

 Jeff Genender wrote:
 
  David M. Lloyd wrote:
  Yes, this is my thinking as well - the casual user wants a simplified
 API,
  while the advanced user wants a more detailed interface.
 
 
  Certainly no reason not to offer both capabilities ;-)

 I totally agree.  I think we should offer a very simple straight forward
 API for the simple cases where the developer only wants asynchronism and
 doesn't want to worry about the details.

 At the same time, there are some very complex use cases that we have to
 account for that would require a more complex API.

 I keep imaging providing a very flexible API that can accommodate large
 uploads/downloads, deal with chunked encoding and COMET technique,
 handle pipelining, etc.  We could then wrap this flexible API with a
 simpler API for dealing with simple requests.


I like this layered approach.  I also like the list of features/usage
senarios especially AJAX/COMET centric features.  At some point I think we
need to have a similar discussion about this and the server.

Alex


Re: [AsyncWeb] Client redesign

2008-02-10 Thread Mike Heath
Jeff Genender wrote:
 
 David M. Lloyd wrote:
 Yes, this is my thinking as well - the casual user wants a simplified API,
 while the advanced user wants a more detailed interface.

 
 Certainly no reason not to offer both capabilities ;-)

I totally agree.  I think we should offer a very simple straight forward
API for the simple cases where the developer only wants asynchronism and
doesn't want to worry about the details.

At the same time, there are some very complex use cases that we have to
account for that would require a more complex API.

I keep imaging providing a very flexible API that can accommodate large
uploads/downloads, deal with chunked encoding and COMET technique,
handle pipelining, etc.  We could then wrap this flexible API with a
simpler API for dealing with simple requests.  For example, if all I
want to do is a couple of simple GET requests, I should haven't to build
an HttpRequest object.  I should be able to provide a URL and do a
simple GET.

-Mike


Re: [AsyncWeb] Client redesign

2008-02-10 Thread Mike Heath
Most of the statements I made were referring to the AsyncWeb client code
and not the latest AHC code that came over from Geronimo.  There is a
huge difference here and I think that's what led to a lot of the
confusion over the statements I made.

-Mike

Sangjin Lee wrote:
 Going back on some of the points here...
 On Jan 29, 2008 2:25 PM, Mike Heath [EMAIL PROTECTED] wrote:
 
 Connecting - Connecting is done as a blocking operation.  In Jeff
 Geneder's AHC branch in the Geronimo sandbox, thread pools are being
 used for asynchronous connecting.  This is unfortunate since MINA
 already has this functionality and does it in a much lighter weight
 manner than using a thread pool.
 
 
 I'm a little confused as to what you mean when you say connecting is done
 as a blocking operation.  You are not saying AHC's connect is done as a
 blocking operation, right? :)  As for the thread pool, I thought Mina's
 socket connector involves a thread pool (Executor) one way or the other, no?
  Is there a way to use connectors without involving a thread pool (whether
 the caller supplies one or the socket connector constructors creates one)?
 
 
 

 Completion Notification - With the existing AHC, there's a single
 callback for the Client.  I REALLY like the observable future pattern
 that MINA uses.  With each asynchronous operation, a future object is
 returned.  This future object can be used to block until the operation
 completes.  The future is also observable so you can also register one
 or more completion listeners with the future.  This makes it real easy
 to do a fork/join like operation like:

 future1 = doAsynch1();
 future2 = doAsynch2();
 future3 = doAsynch3();

 future1.await()
 future2.await()
 future3.await()

 or use an event driven approach like:

 doAsynch1().addListener(...);
 doAsynch2().addListener(...);
 doAsynch3().addListener(...);

 This provides maximum flexibility.  This should be incorporated into
 AsyncWeb client.
 
 
 If you look at the current AHC code, it actually *does* use both future
 (ResponseFuture) and a callback (AsyncHttpClientCallback).  Both correspond
 to the future and the future listener, so it ended up being something very
 similar to what mina's future does.  It would take a trivial refactoring to
 reshape it to look like Mina's future.
 
 Another thing it supports is a completion queue.  One can fire multiple
 non-blocking send() calls to multiple URLs, and sit on the completion queue
 to handle the results as they arrive.  Although callers can write their own
 code to do things like this, supporting it at the API level would be a nice
 thing to keep.  This comes in pretty handy in a scatter-and-gather
 situation...
 
 My 2 cents...
 
 Thanks,
 Sangjin
 



Re: [AsyncWeb] Client redesign

2008-02-10 Thread Mike Heath
David M. Lloyd wrote:
 Alan D. Cabrera wrote:

snip

 So, I was thinking that you would send requests like so:

 ahc.send(url, listener);
 
 This is a departure from the rest of MINA though, in which the idiom
 is more like this:
 
   ahc.send(request).setListener(listener);  // does not block

To clarify, we should support send(...).addListener(listener) so that we
can have multiple completion listeners.  One of my big pet peeves with
AHC as it stands now is that it only accepts one completion listener and
you have to specify that completion listener when the request is initiated.

One of the really powerful features of MINA is that you can add a
completion listener to a future at any time as well as add as many
listeners you want.

-Mike

snip



Re: [AsyncWeb] Client redesign

2008-02-09 Thread Alan D. Cabrera


On Feb 8, 2008, at 11:27 PM, Alan D. Cabrera wrote:



On Jan 29, 2008, at 5:46 PM, Tuure Laurinolli wrote:


David M. Lloyd wrote:

So basically there's been a number of suggestions as to what to  
name these things.  Here are the two options:

Name from pastebin Option 1  Option 2
-    --
AsyncHttpClientHttpClientFactory HttpClient
HttpRequestor  HttpClientHttpConnector
HttpFuture HttpFutureHttpFuture


Going with Option 1, I took a look at what the current MINA AHC  
would look like with this API - the result is at http://www.laurinolli.fi/~tazle/http-client-trivial-implementation.patch 
 It isn't exactly like current AHC (it's not possible to close  
connections at the moment), but pretty close. The AHC tests run,  
for example.


This implementation gets rid of the resource leaks caused by  
constantly creating and not disposing NioSocketConnectors, but does  
not even try to address pipelining or large requests.


Of course nothing is decided until everyone has had a chance to  
weigh in.


Indeed - I don't particularly like the code I wrote, but I think it  
needed to be written in order to see what hoops there were to jump  
through. I think the HttpHandler and HttpFuture interfaces are bad,  
especially the way IoHandler events are converted into HttpFuture/ 
HttpHandler events. HttpClient on the other hand seems like an  
interface we should have. It seems ideal for hiding the complexity  
of possible pipelining or request pooling.




I like how this thread is going.  But I can't help but think that  
we're driving the API from the implementors' standpoint and not the  
users.  IMO, we need to start with a metaphor.  The one that I  
envision is not too far from what's being discussed but points out  
some, what I feel to be, deficiencies in what you propose Tuure.


I like the metaphor of a browser.  The HttpClientFactory is nice as  
the holder of the shared resources.  The HttpClient can be thought  
of as a browser.  It holds cookies, etc.  With that said, the URL  
belongs in the request not the HttpClient constructor.


Bah.  Catching up on other threads...


Regards,
Alan



Re: [AsyncWeb] Client redesign

2008-02-09 Thread Tuure Laurinolli

David M. Lloyd wrote:


3) Session things like cookie management should be maintained at a
higher level - maybe even a separate HttpSession object that can be
provided to each request, on a read-only or read-write basis


I hope higher level here means that people who actually use HTTP in 
stateless fashion won't be bothered by it :)



5) The (optional) ability to specify an IoConnector to the client


Hmm, IoConnector probably can only be shared by different HTTP clients, 
and not some other protocols that add their own filters to it. It think 
it's a good idea anyway, at least indirectly through some 
HttpClientFactory or whatnot.




Re: [AsyncWeb] Client redesign

2008-02-09 Thread Alan D. Cabrera


On Feb 9, 2008, at 7:42 AM, David M. Lloyd wrote:


Alan D. Cabrera wrote:
I like the metaphor of a browser.  The HttpClientFactory is nice as  
the holder of the shared resources.  The HttpClient can be thought  
of as a browser.  It holds cookies, etc.  With that said, the URL  
belongs in the request not the HttpClient constructor.


That's a good thought.  The reason that the URL was originally put  
in the
HttpClient constructor (as well as the request) was to allow the  
management
of connections to be separated from the URL request.  Realistically,  
a URL
could be dropped in favor of discrete scheme/hostname/port  
parameters on

an connection object.  Though it's not always desirable to do this, so
specifying and maintaining a physical connection should be an  
optional kind

of thing to do.


Not sure why one needs to specify the URL so far in advance.

I'm not picky as far as API goes, but I'd like to see the following  
(many

of these items have been stated by others, but here's a roundup):

1) The ability to control connections independently of requests
2) Pipelining  keepalive (which should be a direct consequence of  
[1])


Good stuff.  I'm glad these important features will most likely not  
drive the API.



3) Session things like cookie management should be maintained at a
higher level - maybe even a separate HttpSession object that can be
provided to each request, on a read-only or read-write basis
3a) HttpSession should be a interface of some type, so the user can
intercept cookie reads and writes and act on them directly


Could this not be in the HttpClient?  If we follow the metaphor of a  
browser, it makes sense to store the session there.



4) Future objects for any blocking operation


I was thinking that we could have a Future object that implements an  
AHC callback interface.  This would keep the client simple.  Those  
needing synchronous mechanisms could drop in an instance of this  
Future object.  Just trying to prevent something like:


ah.doThisWay().addListener(bar);

foo = ahc.doAnotherWay();
foo.await();


5) The (optional) ability to specify an IoConnector to the client


This could maybe be specified in the factory to use when allocating  
clients.



Regards,
Alan



Re: [AsyncWeb] Client redesign

2008-02-09 Thread Mike Heath
Alan D. Cabrera wrote:

snip

 That's a good thought.  The reason that the URL was originally put in the
 HttpClient constructor (as well as the request) was to allow the
 management
 of connections to be separated from the URL request.  Realistically, a
 URL
 could be dropped in favor of discrete scheme/hostname/port parameters on
 an connection object.  Though it's not always desirable to do this, so
 specifying and maintaining a physical connection should be an optional
 kind
 of thing to do.
 
 Not sure why one needs to specify the URL so far in advance.

I like the idea of specifying a base URI for the HttpClient.  So you use
a base URI of something like http://somedomain.foo; and subsequent
requests could then do something like get(/bar) which would do a GET
on http://somedomain.foo/bar;.

This would require further abstraction than what AHC has to offer currently.

-Mike

snip


Re: [AsyncWeb] Client redesign

2008-02-09 Thread Alan D. Cabrera


On Feb 9, 2008, at 12:13 PM, Mike Heath wrote:


David M. Lloyd wrote:

Alan D. Cabrera wrote:

I like the metaphor of a browser.  The HttpClientFactory is nice as
the holder of the shared resources.  The HttpClient can be thought  
of
as a browser.  It holds cookies, etc.  With that said, the URL  
belongs

in the request not the HttpClient constructor.


That's a good thought.  The reason that the URL was originally put  
in the
HttpClient constructor (as well as the request) was to allow the  
management
of connections to be separated from the URL request.   
Realistically, a URL
could be dropped in favor of discrete scheme/hostname/port  
parameters on
an connection object.  Though it's not always desirable to do this,  
so
specifying and maintaining a physical connection should be an  
optional kind

of thing to do.

I'm not picky as far as API goes, but I'd like to see the following  
(many

of these items have been stated by others, but here's a roundup):

1) The ability to control connections independently of requests
2) Pipelining  keepalive (which should be a direct consequence of  
[1])

3) Session things like cookie management should be maintained at a
higher level - maybe even a separate HttpSession object that can be
provided to each request, on a read-only or read-write basis
3a) HttpSession should be a interface of some type, so the user can
intercept cookie reads and writes and act on them directly
4) Future objects for any blocking operation
5) The (optional) ability to specify an IoConnector to the client

Hope I'm making sense.


There are a lot of different use cases that need to be addressed in  
the

AsyncWeb client API.  I've got a small laundry list of use cases
rattling around in my head that I would like support in AsyncWeb.   
Do we

have a wiki available for AsyncWeb where we can start posting some of
our ideas


We can drop our ideas down in this

http://cwiki.apache.org/confluence/display/AHC/Index

Regards,
Alan



Re: [AsyncWeb] Client redesign

2008-02-09 Thread David M. Lloyd

Mike Heath wrote:

I like the idea of specifying a base URI for the HttpClient.  So you use
a base URI of something like http://somedomain.foo; and subsequent
requests could then do something like get(/bar) which would do a GET
on http://somedomain.foo/bar;.

This would require further abstraction than what AHC has to offer currently.


Also, think about virtual hosts.  You may have 10 different hostnames that
all connect to the same physical host.  In this case you still need to specify
the full URL per request.  Also, proxies and load-balancers have this same
requirement - furthermore, in a load-balancing situation, you may even need to
make requests with (for example) a scheme of https to a non-SSL host.  So
this should be designed with the maximum flexibility possible.

- DML


Re: [AsyncWeb] Client redesign

2008-02-09 Thread Alan D. Cabrera


On Feb 9, 2008, at 3:56 PM, Mike Heath wrote:


Alan D. Cabrera wrote:

snip

That's a good thought.  The reason that the URL was originally put  
in the

HttpClient constructor (as well as the request) was to allow the
management
of connections to be separated from the URL request.   
Realistically, a

URL
could be dropped in favor of discrete scheme/hostname/port  
parameters on
an connection object.  Though it's not always desirable to do  
this, so
specifying and maintaining a physical connection should be an  
optional

kind
of thing to do.


Not sure why one needs to specify the URL so far in advance.


I like the idea of specifying a base URI for the HttpClient.  So you  
use

a base URI of something like http://somedomain.foo; and subsequent
requests could then do something like get(/bar) which would do a GET
on http://somedomain.foo/bar;.

This would require further abstraction than what AHC has to offer  
currently.


I think that this bit can be, and is, handled with URLs.  I don't see  
the advantage of adding complexity to the metaphor and, hence, the API.



Regards,
Alan



Re: [AsyncWeb] Client redesign

2008-02-09 Thread Alan D. Cabrera


On Feb 9, 2008, at 4:29 PM, David M. Lloyd wrote:


Mike Heath wrote:
I like the idea of specifying a base URI for the HttpClient.  So  
you use

a base URI of something like http://somedomain.foo; and subsequent
requests could then do something like get(/bar) which would do a  
GET

on http://somedomain.foo/bar;.
This would require further abstraction than what AHC has to offer  
currently.


Also, think about virtual hosts.  You may have 10 different  
hostnames that
all connect to the same physical host.  In this case you still need  
to specify
the full URL per request.  Also, proxies and load-balancers have  
this same
requirement - furthermore, in a load-balancing situation, you may  
even need to
make requests with (for example) a scheme of https to a non-SSL  
host.  So

this should be designed with the maximum flexibility possible.



Not sure if you're arguing for putting a URL in the constructor as  
well as the request.  All the above scenarios are cleanly handled w/  
URLs.



Regards,
Alan



Re: [AsyncWeb] Client redesign

2008-02-08 Thread Alan D. Cabrera


On Jan 29, 2008, at 2:25 PM, Mike Heath wrote:


Now that Alex has an AsyncWeb subproject going, I've finally taken the
time to look over the client code.  I have some feedback about the
client and what I would like to see change.  We also discussed the
client on IRC and I will summarize some of the things we talked about.

IoConnector Management - I really don't like how each AsyncHttpClient
has it's own o.a.m.core.IoConnector instance which is used for a  
single

connection.  This has been discussed quite a bit but along the same
vein, the IoHandler should also be a singleton and the state should be
stored in the IoSession.  Additionally, it should be possible to  
pass an
instance of o.a.m.core.IoConnector so that the APR transport can be  
used

(or any other transport that comes along for that matter.)

Connecting - Connecting is done as a blocking operation.  In Jeff
Geneder's AHC branch in the Geronimo sandbox, thread pools are being
used for asynchronous connecting.  This is unfortunate since MINA
already has this functionality and does it in a much lighter weight
manner than using a thread pool.


Interesting.  Can you provide more detail?


Completion Notification - With the existing AHC, there's a single
callback for the Client.  I REALLY like the observable future pattern
that MINA uses.  With each asynchronous operation, a future object is
returned.  This future object can be used to block until the operation
completes.  The future is also observable so you can also register one
or more completion listeners with the future.  This makes it real easy
to do a fork/join like operation like:

future1 = doAsynch1();
future2 = doAsynch2();
future3 = doAsynch3();

future1.await()
future2.await()
future3.await()

or use an event driven approach like:

doAsynch1().addListener(...);
doAsynch2().addListener(...);
doAsynch3().addListener(...);

This provides maximum flexibility.  This should be incorporated into
AsyncWeb client.


I also dislike the single handler for the existing AHC.  Future  
objects seem like a nice idea.



This topic came up on the IRC channel and David Lloyd (dmlloyd), Tuure
Laurinolli (tazle), and I (mike_heath) were discussing better
alternatives to the current design.  The following is a summary of our
conversation.

David posted this mockup as a possible future API
http://rafb.net/p/P8GLTg85.html  David wanted me to be sure to note  
that

the class names in the mockup are just for purposes of explanation may
change.


The paste seems to have expired.  Could you post it on to confluence?


Regards,
Alan



Re: [AsyncWeb] Client redesign

2008-02-08 Thread Alan D. Cabrera


On Jan 29, 2008, at 5:46 PM, Tuure Laurinolli wrote:


David M. Lloyd wrote:

So basically there's been a number of suggestions as to what to  
name these things.  Here are the two options:

Name from pastebin Option 1  Option 2
-    --
AsyncHttpClientHttpClientFactory HttpClient
HttpRequestor  HttpClientHttpConnector
HttpFuture HttpFutureHttpFuture


Going with Option 1, I took a look at what the current MINA AHC  
would look like with this API - the result is at http://www.laurinolli.fi/~tazle/http-client-trivial-implementation.patch 
 It isn't exactly like current AHC (it's not possible to close  
connections at the moment), but pretty close. The AHC tests run, for  
example.


This implementation gets rid of the resource leaks caused by  
constantly creating and not disposing NioSocketConnectors, but does  
not even try to address pipelining or large requests.


Of course nothing is decided until everyone has had a chance to  
weigh in.


Indeed - I don't particularly like the code I wrote, but I think it  
needed to be written in order to see what hoops there were to jump  
through. I think the HttpHandler and HttpFuture interfaces are bad,  
especially the way IoHandler events are converted into HttpFuture/ 
HttpHandler events. HttpClient on the other hand seems like an  
interface we should have. It seems ideal for hiding the complexity  
of possible pipelining or request pooling.




I like how this thread is going.  But I can't help but think that  
we're driving the API from the implementors' standpoint and not the  
users.  IMO, we need to start with a metaphor.  The one that I  
envision is not too far from what's being discussed but points out  
some, what I feel to be, deficiencies in what you propose Tuure.


I like the metaphor of a browser.  The HttpClientFactory is nice as  
the holder of the shared resources.  The HttpClient can be thought of  
as a browser.  It holds cookies, etc.  With that said, the URL belongs  
in the request not the HttpClient constructor.



Regards,
Alan




Regards,
Alan



Re: [AsyncWeb] Client redesign

2008-01-29 Thread David M. Lloyd

Mike Heath wrote:
[...]

This topic came up on the IRC channel and David Lloyd (dmlloyd), Tuure
Laurinolli (tazle), and I (mike_heath) were discussing better
alternatives to the current design.  The following is a summary of our
conversation.


And while Mike was typing up this excellent summary, the discussion 
continued, so here's the next part. :-)



David posted this mockup as a possible future API
http://rafb.net/p/P8GLTg85.html  David wanted me to be sure to note that
the class names in the mockup are just for purposes of explanation may
change.


So basically there's been a number of suggestions as to what to name 
these things.  Here are the two options:


Name from pastebin Option 1  Option 2
-    --
AsyncHttpClientHttpClientFactory HttpClient
HttpRequestor  HttpClientHttpConnector
HttpFuture HttpFutureHttpFuture

So everyone liked HttpFuture.  HttpRequestor is universally reviled (I 
don't like that one either).  Mike suggested option 2, Tuure thought of 
Option 1.  I pointed out that Option 2 might cause problems in that 
people may confuse IoConnector with HttpConnector, though they represent 
different concepts.  Tuure stated that after typing HttpClientFactory a 
few times, he started to like Option 2 some more.


Of course nothing is decided until everyone has had a chance to weigh in.

- DML


Re: [AsyncWeb] Client redesign

2008-01-29 Thread Alex Karasulu
Hi guys,

I'm fine with anything y'all select for the name.  I'm much more interested
in figuring out how to get some of these resource issues settled and the two
forks of this merged together so we have more people working together on
this.  Please see my thread on how to bring the Geronimo folks who are
developing the other fork within the Geronimo sandbox.  It would be a shame
to have both groups working on the same issues.

Perhaps you want them in on this conversation as well before we diverge on
the class names as well.

Alex

On Jan 29, 2008 5:55 PM, David M. Lloyd [EMAIL PROTECTED] wrote:

 Mike Heath wrote:
 [...]
  This topic came up on the IRC channel and David Lloyd (dmlloyd), Tuure
  Laurinolli (tazle), and I (mike_heath) were discussing better
  alternatives to the current design.  The following is a summary of our
  conversation.

 And while Mike was typing up this excellent summary, the discussion
 continued, so here's the next part. :-)

  David posted this mockup as a possible future API
  http://rafb.net/p/P8GLTg85.html  David wanted me to be sure to note that
  the class names in the mockup are just for purposes of explanation may
  change.

 So basically there's been a number of suggestions as to what to name
 these things.  Here are the two options:

 Name from pastebin Option 1  Option 2
 -    --
 AsyncHttpClientHttpClientFactory HttpClient
 HttpRequestor  HttpClientHttpConnector
 HttpFuture HttpFutureHttpFuture

 So everyone liked HttpFuture.  HttpRequestor is universally reviled (I
 don't like that one either).  Mike suggested option 2, Tuure thought of
 Option 1.  I pointed out that Option 2 might cause problems in that
 people may confuse IoConnector with HttpConnector, though they represent
 different concepts.  Tuure stated that after typing HttpClientFactory a
 few times, he started to like Option 2 some more.

 Of course nothing is decided until everyone has had a chance to weigh in.

 - DML



Re: [AsyncWeb] Client redesign

2008-01-29 Thread Tuure Laurinolli

David M. Lloyd wrote:

So basically there's been a number of suggestions as to what to name 
these things.  Here are the two options:


Name from pastebin Option 1  Option 2
-    --
AsyncHttpClientHttpClientFactory HttpClient
HttpRequestor  HttpClientHttpConnector
HttpFuture HttpFutureHttpFuture



Going with Option 1, I took a look at what the current MINA AHC would 
look like with this API - the result is at 
http://www.laurinolli.fi/~tazle/http-client-trivial-implementation.patch 
It isn't exactly like current AHC (it's not possible to close 
connections at the moment), but pretty close. The AHC tests run, for 
example.


This implementation gets rid of the resource leaks caused by constantly 
creating and not disposing NioSocketConnectors, but does not even try to 
address pipelining or large requests.



Of course nothing is decided until everyone has had a chance to weigh in.


Indeed - I don't particularly like the code I wrote, but I think it 
needed to be written in order to see what hoops there were to jump 
through. I think the HttpHandler and HttpFuture interfaces are bad, 
especially the way IoHandler events are converted into 
HttpFuture/HttpHandler events. HttpClient on the other hand seems like 
an interface we should have. It seems ideal for hiding the complexity of 
possible pipelining or request pooling.