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

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

From: Marek Potociar <marek.potociar_at_oracle.com>
Date: Fri, 02 Sep 2011 17:49:30 +0200

On 09/02/2011 04:27 PM, Sergey Beryozkin wrote:
> On 02/09/11 14:08, Marek Potociar wrote:
>>
>>
>> On 09/02/2011 01:48 PM, Sergey Beryozkin wrote:
>>>>>> Consider looking at it in the following perspective:
>>>>>>
>>>>>> 1. Target is a link to a particular resource
>>>>>> 2. The invocation above, in terms of resources captures a resource transition:
>>>>>>
>>>>>> client.target("http://bar").path(1).path(2).path(2).path(4)
>>>>>> R1 ----------> R2 ---> R3 ---> R4 ---> R5
>>>>>>
>>>>>> So, the Target.path() tells you "from here, go there", not "change this resource into that resource".
>>>>>>
>>>>> OK. This looks OK. I guess I'm saying that .path(1).path(2).path(2).path(4) does look like a classical builder
>>>>> chain to
>>>>> me and perhaps it might be a bit confusing...Assuming you want to keep the immutability, then may be rename path() to
>>>>> toPath() or next() or forward(), to capture "from here, go there" better.
>>>>
>>>> I just used the names from UriBuilder, since JAX-RS 1.x users should be familiar with those names.
>>>>
>>> UriBuilder is a mutable one, isn't it ? That is what I'm trying to say, path().path() is associated with the state being
>>> mutated - for me at least. You can have path() unchanged - JavaDocs will be there, but recall your argument about
>>> revert(String, String) :-)
>>
>> State being mutated does not necessarily mean that objects holding the state are mutated too, e.g.:
>>
>> String s1 = "a";
>> String s2 = s1.replace('a', 'b'); // s1 "state" is being mutated
>> s1 != s2; // the instances do not mutate with the state!!!
>
> OK. I see what you and Santiago are saying...
>
>>
>> In case of UriBuilder, the mutability wrt. URI is understandable. In case of Target it is not.
>
> this is due to to your position on how API should be done - I'm fine with it though. A week earlier, I'd reply 'What ?'
> - but I'm getting a clearer picture why some design decisions have been made this or that way - not that I agree with
> them - but I see why at least
>
> And I really don't see
>> how my arguments about request(String, String) apply in this context.
>>
> When we talked about it earlier, I was saying JavaDocs would help to make it plain obvious that the 1st String is CT,
> and one of your counter-arguments was that it was confusing nonetheless when looking at the code what was where...That
> is why I referred to it when indicating JavaDocs would help to understand that path().path() is not mutable

Ok, at least I understand now what you meant.

>
>> Anyway, I do understand that you are pointing out at the potential confusion. Still, I'd rather live with such risk than
>> to change the 'path()' method name to 'toPath()', 'next()' or 'forward()'. First one is just longer, but does not really
>> deal with the potential confusion, and the latter two ones seem just even more confusing.
>>
>
> OK
>
>>>>>
>>>>>> Another example to illustrate that the resources are really different is here - consider which of the following reads
>>>>>> better:
>>>>>>
>>>>>> A)
>>>>>> Target library = Client.target("http://library");
>>>>>> Target books = library.path("books");
>>>>>> Target dantesDivineComedy = books.queryParam("ISBN-13", "978-0451208637");
>>>>>>
>>>>>> B)
>>>>>> Target library = Client.target("http://library");
>>>>>> library = library.path("books");
>>>>>> library = books.queryParam("ISBN-13", "978-0451208637");
>>>>>>
>>>>>> I hope we can agree that A) makes more sense.
>
> Funny we are still talking about A & B :-)
>
>>>>>>
>>>>> A) looks fine, but a bit unusual, when I type a URI in the browser, I'm still working with the same URI string,
>>>>> which I
>>>>> guess B) captures pretty well.
>>>>
>>>> What are you trying to say? We don't work here with strings, we work with resources and their URIs. This is not a text
>>>> editor API.
>>>>
>>> I'm simply giving you my feedback. You cleverly chose the naming of Target in A) to demo the immutability and yes, the
>>> fact we have 3 individual resources there.
>>
>> It's not me being clever.
> It was a positive statement on my behalf.
>
>> Those 3 different URIs represent different resources. In general different URIs typically
>> represent different resources or different resource representations or at least different contexts of the same resource.
>> It's not a hard rule, but that's how it typically is, especially in a single-rooted URI hierarchies, which is what we
>> are talking about.
>>
>>> I said that B) can also be used to reflect the actual way a user works with
>>> the service.
>>
>> IMHO, anyone who would use the API as described in B is just a fool with a tool, who sooner or later will hit the wall
>> with the code he wrote. There's unfortunately no protection against fools. We can only strongly encourage people to read
>> some good books on designing and consuming RESTful services and the principles behind REST before using our API. Our
>> users don't need to be REST gurus, but I think it is appropriate to assume at least a basic level of understanding of
>> the REST problem domain. Relationship between URIs and Resources IMHO belongs to the very basic REST/ROA concepts.
>>
> ?
> Just wondering why I haven't heard CXF users hitting a wall yet, given that we support the mutability...

I made my comment solely in the context of our API. Perhaps, in a context of a different API, similar constructs would
make more sense. If you in your API have a concept of a "fluid uri" that can move back and forth, fine, in such case B
might make some sense. In our proposal, however, Target is a client side pointer to a particular resource. And that's a
completely different concept, in which mutable URI state just does not make sense.

>
>> Sure, one can chain the path() methods and ignore the intermediate resource targets in the code, that's perfectly valid.
>> But that does not mean that those intermediate resources were suddenly all merged into one library resource. And when I
>> say "library resource" I mean *library* resource, not some other esoteric meaning of "library resource" expression.
>>
> I don;t see how the above relates to my earlier comments. Merged ? Just because a single var is used ?
> Is this totally wrong :
> URI lib;
> lib = UriBuilder.fromURI(lib).path(books).path(1).build() ?

Please, stop comparing apples to oranges.

The purpose of a mutable URI builder is to build a URI. Any URI.

The purpose of the Target is to point at a particular resource, hold configuration associated with the resource and
provide a ways how to easily derive targets for the sub-resources, inheriting the parent resource configuration. That's
how the concept is designed.

>
> Does it mean we have merged a /books/1 resource into a lib one ?

No. It does mean, that you have used a mutable URI builder to build some URI assigned to lib variable. I don't know why
did you decide to call the variable 'lib' as it does not make much sense to me in the context of those 2 code lines, but
I guess you had a reason that might be visible in the larger context.

>
> Are we at the stage where we can agree to disagree :-) ?

Yes. Let's do it. I can't believe I have spent so much effort in order to explain things that should be obvious from
javadoc:
http://jsr311.java.net/nonav/javadoc/javax/ws/rs/core/UriBuilder.html

>>>
>>>>> A is more naturally readable - but you can't get from the books section back to the
>>>>> library entry. Which is possible with B...
>>>>
>>>> Are you really suggesting, that in the example A, after executing line 2 you cannot refer to the library, but in the
>>>> (corrected) example B you can?? Are we both still talking about Java code? :)
>>>>
>>> I clearly said that you can't move back from
>>> books to library - are you suggesting that is possible ?
>>
>> Yes, in A you still have the reference to the original library resource in the library variable, don't you.
>>
> Are always keeping all the variables we ever need in scope ?

This is ridiculous, you can't just ignore the context of the example just to prove you are right. Btw. answer to your
question is 'yes'. What you probably wanted to ask is "Are we always keeping all the variable *definitions* we ever need
in scope?" The answer to that question is: 'No. Why should we? Every modern language provides mechanisms for passing
around important variable information among collaborating execution scopes. Typically in a form of constructor or method
input parameters.'

Let's just really agree to disagree.

Marek