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

[jsr339-experts] Re: [jax-rs-spec users] Re: PLEASE READ: Resolving UriBuilder / WebTarget templates

From: Markus KARG <markus_at_headcrashing.eu>
Date: Thu, 6 Sep 2012 18:16:02 +0200

Side comment: I think it will be no good idea to fix the PR by date instead
of by content. Making stress just for the sake of a totally randomly chosen
date is no good thing. While it got rather popular in the past months in
some Oracle-led JSRs (e. g. Java SE 8 without Jigsaw, Java EE 8 without
Cloud Support), I do not think that we should go that track in general. If
you need more time to fix more API details, simply move the PR date.

 

From: Marek Potociar [mailto:marek.potociar_at_oracle.com]
Sent: Donnerstag, 6. September 2012 17:53
To: jsr339-experts_at_jax-rs-spec.java.net
Subject: [jsr339-experts] Re: [jax-rs-spec users] Re: PLEASE READ: Resolving
UriBuilder / WebTarget templates

 

Ok, thanks for support. To clarify - the urgency comes from the fact that
I'd like to make the change before we release PR version of the API.

 

Marek

 

On Sep 6, 2012, at 4:48 PM, Markus KARG <markus_at_headcrashing.eu> wrote:





While I do not see the urgent need for the proposed solution as I do not see
the urgent problem, I agree with your proposal.

 

From: Marek Potociar [mailto:marek.potociar@ <http://oracle.com> oracle.com]

Sent: Donnerstag, 6. September 2012 16:10
To: <mailto:jsr339-experts_at_jax-rs-spec.java.net>
jsr339-experts_at_jax-rs-spec.java.net
Subject: [jsr339-experts] PLEASE READ: Resolving UriBuilder / WebTarget
templates

 

Hello experts,

 

I know it's a long email, but please bear with me. I'd like to propose some
changes to the WebTarget and UriBuilder API. Following email provides the
rationale as well as the proposal.

 

Currently we have following methods in the WebTarget:

 

pathParam(String name, Object value)

pathParams(Map<String, Object> parameters)

 

Their purpose is to set values to path template variables. E.g.:

 

client.target("{a}/{b}").pathParam("a", "x") --> "x/{b}"

 

Also, we have a couple of requests in Jira to provide similar functionality
in UriBuilder as well as in general resolve the inconsistencies between
WebTarget andUriBuilder URI building API:

 

 <http://java.net/jira/browse/JAX_RS_SPEC-211>
http://java.net/jira/browse/JAX_RS_SPEC-211

 <http://java.net/jira/browse/JAX_RS_SPEC-163>
http://java.net/jira/browse/JAX_RS_SPEC-163

 

Also there is a Jersey issue filed around inconsistencies/confusion of what
WebTarget.getUriBuilder() should return:

 

 <http://java.net/jira/browse/JERSEY-1329>
http://java.net/jira/browse/JERSEY-1329

 

So while looking at the WebTarget/UriBuilder consolidation from the larger
perspective provided by all these issues, I'd like to propose some changes
in these APIs.

 

First of all, WebTarget.pathParam(s) are misleading method names, since the
actual intended purpose of the methods was to resolve a template variable to
a value. IOW the expected behavior is:

 

client.target("{a}").path("{b}").queryParam("a", "{a}").pathParam("a", "x")
--> "x/{b}?a=x"

 

Now I think you're with me, when I say that the name of the pathParam method
is misleading. Another issue, perhaps even more interesting is finding the
right answer for a question on what should WebTarget.getUriBuilder() return
- how should the returned UriBuilder be initialized. For example:

 

client.target("{a}/{b}").pathParam("a", "x").getUriBuilder()

 

In this case a few answers are possible for the internal state of the
returned UriBuilder:

 

1. URI template: "{a}/{b}", internal template values: N/A
2. URI template: "{a}/{b}", internal template values: "a" -> "x"
3. URI template: "x/{b}", internal template values: N/A

 

Now after a careful consideration, I'd argue that we should take approach
that corresponds to the answer #3 (even though it may not seem to be the
most intuitive answer). IOW, I could not find any practical use case that
would support the other 2 options and could not be solvable by 3, but I
could find use cases that would only be solvable by #3. One other indication
might be that it's hard to find a use case where following makes sense and
could be considered as a good practice:

 

client.target("{a}/{b}").pathParam("a", "x")...pathParam("a", "y")

 

So my conclusion is that typically you only set a template value only once
and once you set it you do want to overwrite it later. E.g.:

 

authors = client.target("bookstore/authors/{name}");

author = authors.pathParam("name", "Dan Ariely");

 

... /* somewhere in a different part of app */ ...

 

books = author.path("books/{name}");

book = books.pathParam("name", "Predictably Irrational");

 

In the code above the issue with overwriting template values set before is
obvious. You certainly do not want to overwrite the author's name with the
name of the book.

 

So finally, here comes my proposal:

 

* remove WebTarget.pathParam(s) methods
* introduce new WebTarget.resolveTemplate(s) methods, including method
versions that provide flag for "/" encoding in path
* introduce new UriBuilder.resolveTemplate(s) methods, including
method versions that provide flag for "/" encoding in path

 

The new resolveTemplate(s) methods would irreversibly resolve the template
values in WebTarget or UriBuilder for given template variables, e.g.:

 

client.target("{a}/{b}").resolveTemplate("a", "x").resolveTemplate("a", "y")
--> "x/{b}"

// resolveTemplate("a", "y") above is either ignored or throws
IllegalStateException

 

This proposal should make things consistent. Please provide your feedback
ASAP. I'd like to make this change before the PR release planned for next
Monday.

 

Thank you,

Marek