Re: [AsyncWeb] Client redesign
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
David M. Lloyd wrote: > Alan D. Cabrera wrote: > 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
Re: [AsyncWeb] Client redesign
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
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
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: > > > > > > > >>> 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
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
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
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
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
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
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
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
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
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
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 FutureResponse object which implements AsyncHttpClientCallback one would: FutureResponse futureResonse = new FutureResponse(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
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
On Feb 9, 2008, at 3:56 PM, Mike Heath wrote: Alan D. Cabrera wrote: 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
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
Alan D. Cabrera wrote: >> 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
Re: [AsyncWeb] Client redesign
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
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
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? -Mike
Re: [AsyncWeb] Client redesign
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
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. - DML
Re: [AsyncWeb] Client redesign
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
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
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
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.
Re: [AsyncWeb] Client redesign
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
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
[AsyncWeb] Client redesign
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. 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. 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 AsyncHttpClient would hold the IoConnector implementation and default configuration. It would create HttpRequester objects that would use the IoConnector from AsyncHttpClient. This solves the IoConnector management problem I mentioned above. This pattern would also work with existing IoC containers. The HttpRequest object would then be used for sending the actual asynchronous request. It would get its default configuration from AsyncHttpClient. The HttpRequest could use keepAlive to pool connections to a particular host. When a request is sent, an HttpFuture object is returned. HttpFuture could be used for blocking until the request is done or an event handler could be registered. Special care needs to be taken to ensure that we can handle LARGE responses without loading the entire request into memory. We also need to provide an elegant way to deal with chunked-encoding in an event-driven fashion. We also discussed that all these classes should be interfaces and we will provide a default implementation of the interfaces. This gives us and users the flexibility to implement AsyncWeb client however we may want. A possible alternative name for AsyncHttpClient would be HttpConnector. David and Tuure please reply to this email with anything I may have missed or additional clarification. -Mike