users@jersey.java.net

Re: [Jersey] Proposed breaking changes for client API for efficient async support

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Thu, 13 Aug 2009 11:47:41 +0200

On Aug 13, 2009, at 1:16 AM, Paul C. Bryan wrote:

> I guess I'm in the minority.
>
> Another option might be to have a common base class for sync and async
> client filter interfaces and when the filter is added, the specific
> type
> can be ascertained? This way new filters can be written efficiently,
> old
> filters can transition?
>

Yes, this is what i am proposing with:

   public abstract class ClientRequestResponseFilter extends
ClientFilter ...

Thus existing ClientFilter implementations will work. If a developer
wants to transition such that a filter works efficiently for async
operations then they will need to modify their filter to extend from
ClientRequestResponseFilter and following the instructions in the
JavaDoc.

Paul.

> Paul
>
> On Wed, 2009-08-12 at 14:43 -0700, Craig McClanahan wrote:
>> Paul Sandoz wrote:
>>>
>>> On Aug 12, 2009, at 7:59 PM, Craig McClanahan wrote:
>>>
>>>> Paul C. Bryan wrote:
>>>>> Okay, then FWIW, +1 from me. That's the least disruptive break I
>>>>> can
>>>>> imagine for the switch to asynchronous... :)
>>>>>
>>>>>
>>>> +1 as well. I'm not concerned about binary compatibility, as I'm
>>>> always recompiling my apps anyway.
>>>>
>>>
>>> Craig, Paul, which of the following options do you think is best ?
>>>
>>> 1) breaking changes to all filters, requiring that developers change
>>> their filter code; or
>>>
>>> 2)
>>> non-breaking changes, but any stack-based only filters utilized
>>> with an async request will result in non-optimal use
>>> of threads (if an HTTP client is capable of optimal async
>>> requests).
>>>
>>> I am leaning towards option 2.
>> #1 would be really nasty -- there's probably *way* too many existing
>> filter implementations in the world to contemplate this without going
>> through a major version change or something.
>>
>> Craig
>>
>>>
>>> Paul.
>>>
>>>
>>>> Craig
>>>>> On Wed, 2009-08-12 at 19:08 +0200, Paul Sandoz wrote:
>>>>>
>>>>>> On Aug 12, 2009, at 7:04 PM, Paul C. Bryan wrote:
>>>>>>
>>>>>>
>>>>>>> Will there be a way for the client request filter to establish
>>>>>>> context
>>>>>>> that the client response filter can in turn consume?
>>>>>>>
>>>>>>>
>>>>>> Yes, properties can be added to the request in the request filter
>>>>>> which can then be retrieved in the response filter:
>>>>>>
>>>>>> https://jersey.dev.java.net/nonav/apidocs/1.1.1-ea/jersey/com/sun/jersey/api/client/ClientRequest.html
>>>>>> #getProperties%28%29
>>>>>>
>>>>>> Paul.
>>>>>>
>>>>>>
>>>>>>> On Wed, 2009-08-12 at 14:45 +0200, Paul Sandoz wrote:
>>>>>>>
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> I mentioned before in a previous email about breaking changes
>>>>>>>> client
>>>>>>>> API to support efficient asynchronous requests/responses such
>>>>>>>> that a
>>>>>>>> response can be processed on a different thread to that of a
>>>>>>>> request.
>>>>>>>>
>>>>>>>> The current filter approach is stack-based using a general
>>>>>>>> handler
>>>>>>>> chain where the last handler is "inflection" point that sends
>>>>>>>> an HTTP
>>>>>>>> request and produces an HTTP response.
>>>>>>>>
>>>>>>>> We need to split the a filter into separate request and
>>>>>>>> response
>>>>>>>> filters:
>>>>>>>>
>>>>>>>> public interface ClientRequestFilter {
>>>>>>>> ClientRequest filter(ClientRequest request);
>>>>>>>> }
>>>>>>>>
>>>>>>>> public interface ClientResponseFilter {
>>>>>>>> ClientResponse filter(ClientRequest request, ClientResponse
>>>>>>>> response);
>>>>>>>> }
>>>>>>>>
>>>>>>>> Then we can have an abstract class as follows:
>>>>>>>>
>>>>>>>> public abstract class ClientFilter implements
>>>>>>>> ClientRequestFilter,
>>>>>>>> ClientResponseFilter {
>>>>>>>> public ClientRequest filter(ClientRequest request) {
>>>>>>>> return request;
>>>>>>>> }
>>>>>>>>
>>>>>>>> public ClientResponse filter(ClientRequest request,
>>>>>>>> ClientResponse response) {
>>>>>>>> return response;
>>>>>>>> }
>>>>>>>> }
>>>>>>>>
>>>>>>>> and modify all existing filters supported by Jersey to extend
>>>>>>>> from
>>>>>>>> the
>>>>>>>> new ClientFilter. That way we can ensure that existing source
>>>>>>>> that
>>>>>>>> uses the Jersey supplied filters to add instances to Client or
>>>>>>>> WebResource is still compatible (i strongly suspect binary
>>>>>>>> compatibility will be broken so a recompile would be required).
>>>>>>>>
>>>>>>>> The ClientHandler interface is still relevant for
>>>>>>>> implementations of
>>>>>>>> HTTP clients (HttpURLConnection, Apache HTTP clent, and in
>>>>>>>> memory-
>>>>>>>> client). But we will require an AsyncClientHandler to
>>>>>>>> implement if
>>>>>>>> async request/response processing is supported:
>>>>>>>>
>>>>>>>> public interface AsyncClientHandler {
>>>>>>>> void handler(ClientRequest r, ClientResponseListener l);
>>>>>>>> }
>>>>>>>>
>>>>>>>> public interface ClientResponseListener {
>>>>>>>> void onError(Throwable t);
>>>>>>>>
>>>>>>>> void onResponse(ClientResponse cr);
>>>>>>>> }
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> After I wrote the above I realized there is the possibility
>>>>>>>> for an
>>>>>>>> alternative solution that will limit breaking changes to the
>>>>>>>> async
>>>>>>>> parts of the API. Thus existing filters used with the non-
>>>>>>>> async parts
>>>>>>>> will not be affected.
>>>>>>>>
>>>>>>>> It should be possible to retain the stack-based approach for
>>>>>>>> non-
>>>>>>>> async
>>>>>>>> support and modify the existing filters to support stack and
>>>>>>>> non-
>>>>>>>> stack
>>>>>>>> approaches by filters extending from the following class:
>>>>>>>>
>>>>>>>> public abstract class ClientRequestResponseFilter extends
>>>>>>>> ClientFilter, ClientRequestFilter, ClientResponseFilter {
>>>>>>>> public ClientResponse handle(ClientRequest request)
>>>>>>>> throws ClientHandlerException {
>>>>>>>>
>>>>>>>> request = filter(request);
>>>>>>>>
>>>>>>>> response = getNext().handler(cr);
>>>>>>>>
>>>>>>>> return filter(response);
>>>>>>>> }
>>>>>>>>
>>>>>>>> // state associated with request filter which needs to be
>>>>>>>> accessed by response filter
>>>>>>>> // must be added as a property on the request, a thread
>>>>>>>> local
>>>>>>>> cannot be used because
>>>>>>>> // the response filter may be processed on a different
>>>>>>>> thread to
>>>>>>>> the request filter.
>>>>>>>> public ClientRequest filter(ClientRequest request) {
>>>>>>>> return request;
>>>>>>>> }
>>>>>>>>
>>>>>>>> public ClientResponse filter(ClientRequest request,
>>>>>>>> ClientResponse response) {
>>>>>>>> return response;
>>>>>>>> }
>>>>>>>> }
>>>>>>>>
>>>>>>>> However there is an issue if instances of ClientFilter (that
>>>>>>>> are not
>>>>>>>> instances of ClientRequestResponseFilter) are added to the
>>>>>>>> filter
>>>>>>>> chain of Client, which are then utilized by a
>>>>>>>> AsyncWebResource. This
>>>>>>>> will render inoperable efficient async operation. Under such
>>>>>>>> circumstances we could easily generate a warning.
>>>>>>>>
>>>>>>>> Paul.
>>>>>>>>
>>>>>>>> ---------------------------------------------------------------------
>>>>>>>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>>>>>>>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>>>>>>>
>>>>>>>>
>>>>>>> ---------------------------------------------------------------------
>>>>>>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>>>>>>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>>>>>>
>>>>>>>
>>>>>> ---------------------------------------------------------------------
>>>>>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>>>>>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>> ---------------------------------------------------------------------
>>>>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>>>>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>>>>
>>>>>
>>>>
>>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>