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

[jsr339-experts] Re: Some comments about Target and Invocation

From: Sergey Beryozkin <sberyozkin_at_talend.com>
Date: Thu, 1 Sep 2011 18:33:49 +0100

On 01/09/11 15:34, Marek Potociar wrote:
> Not sure I understand what is supposed to be over-engineered here. Different (sub)resources may have different
> requirements. These requirements may be represented as different set of target configurations. Sometimes the different
> requirements may be even at the level of a single request - e.g. you need to be authenticated to do PUT or POST, but you
> can freely invoke a safe operation, such as GET. It's common use case with many existing web pages, including java.net.

I can see how the idea in general, disagree it's practical to assume the
immutability of URI is needed to address "Sometimes the different
requirements may be even at the level of a single request" because it's
difficult to imagine a case when a *single" mutable Target URI instance
is shared between multiple concurrent consumers all having diff auth
requirements. Even it's feasible, it does not warrant in itself the need
for the immutability given how highly 'esoteric' this case is IMHO.

Anyway, would you consider adding a baseURI property to Target and may
be some scoped Target constructor for passing it from the top one ? I
think it's an important Target property.

Having client.target("http://bar").path(1).path(2).path(2).path(4)
target having no clue that the baseURI is http://bar seems not right.

I don't have a real-world case to prove baseURI can be useful but I do
believe it's a handy property.

By the way, IMHO

allowing for chaining such as
client.target("http://bar").path(1).path(2).path(2).path(4)
and yet enforcing the target immutability seems non-intuitive/confusing,
at least to my eye.

Will double check if Invocation flow returns a new instance each time,
if not then having the target and invocation flows combined also seems
non-intuitive - however seeing no problem with it...
Will continue my analysis

thanks, Sergey

>
> Btw. one of the reasons why Client and Target are decoupled is that Client is supposed to do all the heavy-weight
> initialization so that Target can be as lightweight as possible. Target is a "configured resource URI able to create
> HTTP requests".
>
> Marek
>
> On 09/01/2011 03:04 PM, Sergey Beryozkin wrote:
>> Thanks, that is interesting.
>> Now, I don't want to sound too negative,
>> Just curious...Are we are seeing a bit of over-engineering in action below ?
>>
>> Is that really can happen in practice, a code like that executing where, had we not had this immutability, result in
>> multiple users a single shared mutable Target instance and messing things up with respect to a proper authentication ?
>>
>> Have to think more about Target.path() returning a new copy on the time, don't see a problem right now, accept that
>> obviously I do see why you were saying no back() was needed...
>> I guess, I was thinking it is handy for a current Target always know where it is now relative to the base URI, again
>> based on my CXF experience, which is not possible with the current approach
>>
>> Sergey
>>
>> On 01/09/11 13:49, Marek Potociar wrote:
>>> Just to clarify, target is immutable with respect to it's URI - you can update it's configuration.
>>>
>>> One reason was certainly to allow for easier transitions (e.g. iterations) in a URI hierarchy. Another reason was to
>>> make sure that you can do easy configuration scoping based on the nested URIs:
>>>
>>> Target library = client.target("http://library/")
>>>
>>> // add common filter for adding a header with my personal library API key to all requests sent to the library service
>>> library.register(new LibraryApiKeyFilter(myKey));
>>> Target books = library.path("books"); // inherits API key filter
>>>
>>> Target myAccount = library.path("users/marek"); // inherits API key filter
>>> // add the authentication filter for accessing my account resource
>>> myAccount.register(new LibraryAuthenticationFilter(myCredentials));
>>> Target myBooks = myAccount.path("books"); // inherits API key and authentication filters
>>>
>>> // everybody can access the list of available books
>>> List<Book> listOfAvailableBooks = books.request("text/plain").get(new TypeLiteral<List<Book>>(){});
>>>
>>> // only I can access the list of my books with proper authentication
>>> List<Book> listOfMyBooks = myBooks.request("text/plain").get(new TypeLiteral<List<Book>>(){});
>>>
>>> // this would fail with 401 or more safely with 404
>>> List<Book> listOfMareksBooks = library.path("users/marek/books").request("text/plain").get(new
>>> TypeLiteral<List<Book>>(){});
>>>
>>>
>>> Marek
>>>
>>>
>>> On 09/01/2011 02:01 PM, Sergey Beryozkin wrote:
>>>> Well, that was definitely a new thing to learn,
>>>> that is why you could obviously see why I typed
>>>> target.accept(...)
>>>>
>>>> What was the rationale behind making it immutable ?
>>>>
>>>> Cheers, Sergey
>>>>
>>>> On 01/09/11 12:55, Marek Potociar wrote:
>>>>> No, Target is *NOT* mutable (unlike Invocation.Builder or HttpRequest). IOW:
>>>>>
>>>>> Target t1 = client.target("http://books");
>>>>> Target t2 = t1.path("1");
>>>>> t1 != t2; // !!!
>>
>>


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