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.
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
>>
>>
>
>