jsr339-experts@jax-rs-spec.java.net

[jsr339-experts] Re: Removing command pattern simplifies things

From: Sergey Beryozkin <sberyozkin_at_talend.com>
Date: Thu, 1 Sep 2011 13:17:06 +0100

Sorry - something strange is going on with the server,
this is an email I sent yesterday morning - please ignore emails please
sent by me yesterday, on 31st

On 01/09/11 13:13, Marek Potociar wrote:
>
>
> On 08/31/2011 01:19 PM, Sergey Beryozkin wrote:
>> Hi Marek
>> On 31/08/11 12:08, Marek Potociar wrote:
>>>
>>>
>>> On 08/31/2011 12:09 PM, Sergey Beryozkin wrote:
>>>> I think it's good to try and model a nice and very clean process such as
>>>> "Have a target URI created first", next go "Request" - set headers there, may be an entity and do a call, this is all
>>>> sounds good.
>>>> But I think it proves a bit too rigid/inflexible.
>>>
>>> That's how it is supposed to be. The fluent API should gently prod you in the direction of writing a well-formed HTTP
>>> requests. If you need to write something that is not well-formed, you certainly can, but it may not look nice. And
>>> that's actually a good thing.
>>>
>>> An if you really need a lot of extra flexibility, you can always use the Invocation API. It may be more verbose, but
>>> that's the tax for the flexibility. You should not use that API if you really need only something simple anyway.
>>>
>> +1 to the above thoughts.
>>
>> IMHO the current version is inflexible. I don't understand how disallowing for an explicit CT setter or enforcing an
>> entity wrapper, without having to resort to Invocation, and not being able to build a simple iteration logic, can
>> protect a user from creating non-well formed requests.
>
> IMHO, you did not do your homework and did not look at the examples at all. I have provided you some iteration examples
> in a separate thread.
>
>>
>> Are you concerned about POSTs containg no CT ?
>
> It's not just POSTs. I think that we should hint user that ANY request that contains entity SHOULD contain CT. That's
> what th API does.
>
>> I can kind of get that, but this is a low-level API, obviously users have to get some ideas of what formats are
>> supported by the end receiver ? By adding this tight entity wrapper and not letting set a CT as is is not cool -
>> likewise the fact I can't get back to resetting some bits of the current URI once I moved to a request stage is a big
>> limitation IMHO
>
> This is a low-level RESTful client API. Low-level HTTP client API is a lower layer and is going to be submitted as a
> separate JSR sometime soon AFAIK.
>
> Also, we are, again, running into the problem with your homework. It's simply not true that you cannot set CT without
> sending entity. I don't see a use-case where it would make sense, but this is possible:
>
> client.target(...).request().header("Content-Type", "text/plain").post(null);
>
> It's not nice, but who cares. It's an ill-formed request, there's no reason why it should look nice. Btw. the fact that
> the above is possible is a proof that the API *IS* low-level.
>
> Marek
>
>>
>> Thanks, Sergey
>>
>>> Marek
>>>
>>>>
>>>> Anyway, going to do some homework with the examples and provide more feedback :-)
>>>>
>>>> Sergey
>>>>
>>>> On 31/08/11 11:03, Sergey Beryozkin wrote:
>>>>> On 31/08/11 10:48, Marek Potociar wrote:
>>>>>>
>>>>>>
>>>>>> On 08/31/2011 11:08 AM, Sergey Beryozkin wrote:
>>>>>>> Hi,
>>>>>>>
>>>>>>> On 30/08/11 17:04, Marek Potociar wrote:
>>>>>>>> Hi Sergey
>>>>>>>>
>>>>>>>> On 08/30/2011 12:53 PM, Sergey Beryozkin wrote:
>>>>>>>>> On 29/08/11 17:04, Marek Potociar wrote:
>>>>>>>>>> to do a typical GET request, which most likely will be the most
>>>>>>>>>> prevailing use case, you SHOULD:
>>>>>>>>>>
>>>>>>>>>> - specify URI,
>>>>>>>>>> - specify acceptable response media types
>>>>>>>>>> - specify method (GET)
>>>>>>>>>>
>>>>>>>>>> With the current API proposal you can do:
>>>>>>>>>>
>>>>>>>>>> client.target(uri).request(accepted/type1, accepted/type2,
>>>>>>>>>> ...).get();
>>>>>>>>>>
>>>>>>>>>> to me, it's as simple as it gets.
>>>>>>>>>
>>>>>>>>> Would you consider allowing for
>>>>>>>>>
>>>>>>>>>> client.target(uri).request(contentType, accepted/type1,
>>>>>>>>>> accepted/type2, ...)
>>>>>>>>> ?
>>>>>>>>
>>>>>>>> I did consider it in fact, but after playing with it for a while I
>>>>>>>> concluded that multiple input arguments of the same
>>>>>>>> type with different meaning based entirely on the order of strings
>>>>>>>> (and in a vararg method) do not seem like a good
>>>>>>>> idea. The above example looks quite ok, but cosider a real-life usage:
>>>>>>>>
>>>>>>>> client.target(uri).request("text/plain", "application/xml,
>>>>>>>> "application/json").post(item); // which is which?
>>>>>>>>
>>>>>>>> It's not very readable IMO.
>>>>>>>>
>>>>>>>
>>>>>>> You clipped there my comment about dropping a var support for
>>>>>>> multiple accept headers in a transitional request() :-).
>>>>>>> Is it really close to a common use case, having a programmatic client
>>>>>>> setting multiple accepts ?
>>>>>>> So what about
>>>>>>> request(String ct);
>>>>>>> request(String ct, String at);
>>>>>>>
>>>>>>> as I said your example above can be handle by using request() and
>>>>>>> then setting multiple accept headers
>>>>>>
>>>>>> Varargs just add extra confusion but the problem "which is which" is
>>>>>> there even for a method(String, String).
>>>>>
>>>>> what do you "which is which" ? I'm proposing to bin the option to
>>>>> specify multiple accepts in a request(...) and have two well-document
>>>>> option, one which tales a single arg - that is accept, the one which
>>>>> takes 2 options takes Content-Type as the 1st param, Accept - as a 2nd one
>>>>>
>>>>>> Additionally, as I said, content type really belongs to the part where
>>>>>> entity is provided).
>>>>>>
>>>>>
>>>>> This is just too rigid - request is a transitional method and it does
>>>>> make an exception for Accept, presumably to let people avoid typing
>>>>> request(). I'm proposing to do another shortcut
>>>>>
>>>>>>>
>>>>>>>> Also, I prefer keeping content type close to the entity:
>>>>>>>
>>>>>>>> client.target(uri).request("application/xml,
>>>>>>>> "application/json").post(text(item));
>>>>>>>>
>>>>>>>> or generically:
>>>>>>>>
>>>>>>>> client.target(uri).request("application/xml,
>>>>>>>> "application/json").post(entity(item, "text/plain"));
>>>>>>>>
>>>>>>>
>>>>>>> Do you really like the above ?
>>>>>>
>>>>>> Yes I do :)
>>>>>>
>>>>>>> client.target(uri).request("text/plain", "application/json").post(item);
>>>>>>>
>>>>>>> Seems more readable to me.
>>>>>>
>>>>>> Not to me. It's perhaps a matter of taste, but I interpret the above
>>>>>> as "Give me text or json in return for the posted
>>>>>> item (represented as unknown media type)".
>>>>>>
>>>>>
>>>>> Why you keep saying that :-) ? I've said twice that I proposed to drop a
>>>>> request(String... accept) because IMHO it's not the most common case.
>>>>> And have 2 methods one taking Accept only and one - Ct and Accept only
>>>>> and thus in the latter case CT would still be close enough to post...
>>>>>
>>>>>>> By the way, does one really has to use entity wrapper all the time or
>>>>>>> one of its static
>>>>>>> helpers, no way to set content-type freely ?
>>>>>>> I'm presuming the following is allowed
>>>>>>> inv.header("Content-Type", "text/xml").accept("text/xml").post(new
>>>>>>> Book()) ?
>>>>>>
>>>>>> Yes, if you want the extra freedom, there's the Invocation you can
>>>>>> use. The difference is that invocation does not have
>>>>>> named HTTP methods. It only has generic invoke/submit. Also, it does
>>>>>> not have any header/entity mutators, but it
>>>>>> provides access to HttpRequest. So the above code would need to be
>>>>>> written as:
>>>>>>
>>>>>> invocation.asRequest().type("text/xml").accept("text/xml").entity(new
>>>>>> Book()).method("POST"); // modify request freely
>>>>>> invocation.invoke(); // invoke the modified request
>>>>>>
>>>>>> Yes, it's more verbose. But this is not the target use case of th API,
>>>>>> although it's certainly good we provide the
>>>>>> flexibility for users that truly need it.
>>>>>>
>>>>> Well, well...As said I was warming up but seeing these example makes me
>>>>> dizzy...Having no explicit setter for CT without having to resort to the
>>>>> above unreadable sequence ? I'm sorry - I do appreciate you are working
>>>>> very hard - I honestly do.
>>>>>
>>>>>> Please, kindly look at the latest version of the API and the samples.
>>>>>> I know there have been several changes in the API
>>>>>> lately, but what I describe above is almost a week old stuff. To make
>>>>>> it simpler, I just added a special example
>>>>>> covering the Invocation API in larger detail.
>>>>>>
>>>>> Thanks for that
>>>>> Sergey
>>>>>
>>>>>> Marek
>>>>>
>>>>>
>>>>
>>>>
>>
>>


-- 
Sergey Beryozkin
http://sberyozkin.blogspot.com
Talend - http://www.talend.com