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

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

From: Marek Potociar <marek.potociar_at_oracle.com>
Date: Wed, 07 Sep 2011 15:22:53 +0200

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?

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

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.

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

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