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

[jsr339-experts] Re: Target: two new properties

From: Sergey Beryozkin <sberyozkin_at_talend.com>
Date: Thu, 8 Sep 2011 10:24:46 +0100

Comments inline,

On 07/09/11 14:22, Marek Potociar wrote:
>
>
> On 09/07/2011 11:39 AM, Sergey Beryozkin wrote:
>> On 06/09/11 19:13, Marek Potociar wrote:
>>>
>>>
>>> On 09/06/2011 06:15 PM, Sergey Beryozkin wrote:
>>>> Experts,
>>>>
>>>> I'd like to propose to get two new properties added to Target[1]
>>>>
>>>> 1. baseURI (type: URI)
>>>>
>>>> Every Target points to a specific HTTP resource. However resources are often can be considered to be part of a given
>>>> RESTful application/service. It should be possible in most cases to report what was a base Target/URI this given Target
>>>> originated from.
>>>>
>>>> Rules:
>>>>
>>>> All Targets created from absolute URIs (via Client or Target.path() factory methods) must report that absolute URI as
>>>> the base URI.
>>>>
>>>> In all other cases it must be an original absolute URI which led to the creation of the top-level Target.
>>>>
>>>> Examples:
>>>>
>>>> Target t = client.target("http://service");
>>>> assertEquals("http://service", t.getBaseURI());
>>>>
>>>> assertEquals("http://service/1", t.path("http://service/1").getBaseURI());
>>>>
>>>> Target t2 = t.path("2");
>>>> assertEquals("http://service", t2.getBaseURI());
>>>
>>> I don't have a problem with adding base URI support for a target as such, although it would help to see at least one use
>>> case for the Target.getBaseUri().
>>
>> Right... I think if we look at Target as something that identifies a dot in the WEB then there's no need for introducing
>> this and the next proposed properties. Recall my very first attempt to merge Client& Target - it may've been not a good
>> idea - but it was an attempt to get things less disjointed then they are now. Having this properties may help rectify it.
>>
>> IMHO, from a perspective of a client code attempting to consume a RESTful service, it can be helpful to get Target carry
>> around some important associated metadata. No association exists between
>> the following two targets right now:
>> Target t = client.target("http://service");
>> Target t2 = t.path("2");
>>
>> t& t2 are alien targets identifying two dots in the WEB.
>> Of course. we can have
>>
>> Target t = client.target("http://service");
>> Target t2 = client.target("http://service/2");
>>
>> But I think the former example gives an opportunity to have t2 be aware of t, it seems to me a more realistic coding
>> pattern, and thus should be utilized for the purpose of tracking the base or rather, a specific entry into a RESTful
>> application.
>>
>> I can think of a few few examples right now - but I think what is more important is to agree on whether this and next
>> props are important Target props or not. If yes then undoubtedly they'd be used.
>
> There's no doubt that objects should expose some properties in general, I guess we don't need to make an explicit
> agreement about such a generic statement. I would however most certainly argue that we need to asses all properties one
> by one and see if each of them makes sense to standardize or not (yet). Best way of doing it is to look at th use cases.
> If there are valid and strong use cases, we should standardize it right away. But if there are no good use cases
> identified, we should not standardize such a property - at least not until supporting use cases are identified.
>
> Another reason for having use cases is to be able to see the meaning of the property in the larger context - e.g. in
> this case a use case could help us decide whether it is a problem for 2 targets pointing at the same URI to have
> different base URIs or not.
>
> So, can you please share the examples you have in mind?
>

Well, I've been thinking about cases where at a certain point in the
application path a decision is made, based on say the GET response or
certain HTTP error status, that the alternative route having the same
origin as this current route has to be tried.
In this particular case we can get an origin passed along all the time -
possible. However if we generalize the problem a bit and say we want
a method like go(Target) do roam around and revert back to the prev
segment, or may be to the origin, or may be two segments back, all in
order to retry, then we'd probably have to code to pass a stack of
Targets along.
Also allows for an alternative impl of the iterations...

np if the above sounds a bit academical or non-practical. I'm not sure,
there's no 'glue' between various Targets, probably simplifies things at
the impl level.

>>
>>> Let's just wait a little and give a chance to other experts to chime in. Also, please
>>> open a new Jira issue to track this RFE.
>>>
>>> There's a one thing that bothers me though:
>>>
>>> Target t1 = client.target("http://service/1");
>>> Target t2 = client.target("http://service").path("1");
>>>
>>> assertEquals(t1.getUri(), t2.getUri()); // Targeting same resource
>>> assertEquals(t1.getBaseUri(), t2.getBaseUri()); // Still fails!!!
>>>
>>> In the code above, both targets point to the SAME resource. It therefore feels somewhat weird that a base URI might not
>>> be the same for all targets addressing the SAME resource via the SAME URI.
>>>
>>
>> I see. One option is to recognize that t1& t2 represent different flows, showing that a given WEB dot can be reached in
>> a number of ways.
>> But I agree it can be confusing nonetheless. Perhaps a cleaner and less ambiguous option is to have a
>> baseTarget(type: Target)
>>
>> property instead. Targets initialized with abs URIs will return null; others - the original Target.
>
> What do you mean when you say "property"? Static method?
>

Meant that Target class would have getter and setter for a baseTarget
property

> Btw. I am starting to think that the different base URIs for same target URIs is not a real problem. It can be seen as a
> property that falls into the similar category as configuration - it captures the context in which it was created rather
> than the target URI. But I still want to see a valid use case. :)
>
>>>>
>>>> 2. prevTarget (type: Target)
>>>>
>>>> It should be possible to start from a current Target and revert back to the original Target which initiated the chain.
>>>> Similarly how one can express a process "from this Target to the next Target", one should be able to express "from this
>>>> Target to the previous Target".
>>>
>>> There is *NO* concept of next Target in the current API. There is just a general concept of 'some other' or 'that'
>>> target. If anything, the proposal should talk about 'originating target'. 'Next target' as well as 'previous target' are
>>> IMO very confusing terms, esp. because of the potential confusion with 'Back' and 'Forward' browser actions.
>>>
>>
>> see my reasoning above. Yes - right now all we have is disjointed Targets. By the way, can you clarify please what you
>> find being confusing about Target being able to point to the root or the prev Target ?
>>
>>> Also, I don't see a use case that would justify the need for every target to hold the full history of ancestors. In
>>> larger deployments, this is a road to nasty memory leaks, I'm afraid. Seems to me that in case of Target, tracking the
>>> ancestor history should be deferred to the application layer.
>>>
>> That is a reasonable concern. I'm not proposing though to have two way links here. Hmm... If you think it's quite
>> realistic, then well...
>
> So, just to make sure we are on the same page, what would be the value of "uri" in the following example?
>
> URI uri = client.target("http://service").path("1").path("2).path("3").prevTarget().prevTarget().getUri();
>
> My point is that the code above demonstrates the need to use a stack to implement prevTarget() properly. And the problem
> I see is that you need to use this stack even in the 99.9% Target use cases where the method is not needed. Not to
> mention that the stack can grow pretty much indefinitely.
>

In the above we have t1, t2, t3 and t4 targets, where t1 corresponds to
client.target("http://service"), etc.

Here is the links, the way I see them:

t4 -> t3 (prev)
t4 -> t1 (base)

t3 -> t2 (prev)
t3 -> t1 (base)

t2 -> t1 (prev)
t2 -> t1 (base)

t1 -> null
t1 -> null

Looks like a linked list to me...

>>
>> I'm concerned I'm seeing the immutability showing its other side here...It allows for doing the explicit dynamic
>> configuration of Targets in the code - which IMHO does not belong to the application layer at all - but presents a
>> challenge to introducing properties
>> which IMHO could be explored at runtime dynamically...
>
> I am not sure I follow the above. Can you please be more specific?
>
I was referring to the possible difficulty associated with adding those
props (possible leaks ?, etc) which is a side-effect of having the
immutability in place...Immutability does have it pluses, and for me
that would probably be sharing a single Target across multiple threads
(not sure yet what would happen there in case of template vars being
used in the Target path)...

Anyway, I'm kind of easy now on having this properties added or letting
the developers deal with them if needed
Sergey

> Marek
>
>>
>>> Anyway, if you still feel strongly about this proposal, please open a new Jira issue to track this RFE too.
>>>
>> Lets see if it's worth it...
>> Sergey
>>
>>> Marek
>>>
>>>> This makes Target a more 'capable' and allows for tracing all the intermediate Targets. To some extent this can be
>>>> compared to UriInfo.getMatchedURIs property...
>>>>
>>>> Rules:
>>>>
>>>> All Targets created from absolute URIs must return null;
>>>> Those created from Target.path(relativePath); return the previous Target.
>>>>
>>>> Examples:
>>>>
>>>> Target t = client.target("http://service");
>>>> assertNull(t.getPrevTarget());
>>>>
>>>> Target t2 = t.path("2");
>>>> assertSame(t, t2.getPrevTarget());
>>>>
>>>> assertSame(t2, t2.path("3").getPrevTarget());
>>>>
>>>>
>>>> Comments ?
>>>> Sergey
>>>>
>>>> [1]
>>>> http://java.net/projects/jax-rs-spec/sources/git/content/src/jax-rs-api/src/main/java/javax/ws/rs/client/Target.java?rev=bdee7808db117198b8e611551a12a099bcf6b103
>>>>
>>>>
>>>>
>>>> Cheers, Sergey
>>
>>


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