Re: UriInfo.getAncestorResource*()

From: Marc Hadley <Marc.Hadley_at_Sun.COM>
Date: Fri, 14 Mar 2008 11:35:40 -0400

On Mar 13, 2008, at 5:30 PM, Stephan Koops wrote:
>>> UriInfo.getAncestorResource*()
>>> I think it is better to return the root resource class (and
>>> especially the URI) as last and not as first. Did anyone think,
>>> the root resource class should be at the beginning? I remember,
>>> that Marc said, he has no special preferences.
>> No special preference, it seems logical to list the resources in
>> the order you encounter them but I could live with the reverse. Is
>> the intent to make it easier to get the direct parent ?
> Yes. My old use case :-).
> In my last email I forget, that IMO it should be possible to use
> int firstOrLastIndex = ...; // see above
> URI relParentUri =
> uriInfo.getAnchestorResourceURIs().get(firstOrLastIndex);
> uriInfo.getBaseUriBuilder().path(relParentUri); // here
> is .toString() needed now
Its a good idea to reduce this kind of friction in the API.

> Until now it is not possible, because path(URI) is not available.
> You must call relParentUri.toString(). It is easier for app
> developers, if it is possible without calling .toString().
> Two solutions come into my head: change the return type to
> List<String> instead of List<URI> or add a method
> UriBuilder.path(URI) with the same semantic as path(String). The
> available method UriBuilder.uri(URI) replaces the current path
> instead of appending the new path.

Given that we define that members will only contain a relative URI
path, the utility of List<URI> is questionable in this case. I think
switching to List<String> would be best.

>>> UriBuilder
>>> build(int...)? I think it is useful to add
>>>, because often IDs are used for the URI
>>> build, and they are often Integers (but never null). I know that
>>> we could add a lot of other methods here, but I think this is a
>>> common use case.
>> Hmmm. Rather than doing that how about changing build(String...) to
>> build(Object...) and requiring that Object.toString is used to get
>> a parameter value. Then we can take advantage of autoboxing to
>> support primitive types.
> Yes, also good. Two specialized methods are more explicit what is
> meant, but your proposal is very flexible and you could combine
> ints, Strings and whatever.
> BTW: What about null values? Forbid or tread as ""? I think forbid.
> Semanticly it is perhaps useful to remove a query or matrix
> parameter if null is given for it's value, but I think the logic get
> very complex then.

Agreed. The choice should be between "" or throwing
IllegalArgumentException. Elsewhere in the class we use null to
signify "unset" but if you are building a URI with template parameters
then having null silently mapped to "" could produce unexpected
results so I think its best to throw an exception.

>>> port(String)? If template variables should also be allowed
>>> for the port, than we need UriBuilder.port(String). I think it
>>> should only be possible to set a port (0 (or1?) until 65535
>>> (=2**16-1) ) or one template variable and nothing else. To unset
>>> the explicit port null should be used. For
>>> uriBuilder.port("808{lastPortDigit}") or something like this there
>>> is only a very little number of use cases and will complicates the
>>> algorithm to check for validity.
>> I can't see port(String) being used much - do we really need it ?
> The intention comes while implementing
> UriBuilder.schemeSpecificPart(.). There it is possible to give a
> template variable for the port. But I think it is not a useful way
> to set a port template variable by replacing the full scheme
> specific part. Is there another way to vary the port with a template
> variable?

I don't think there's another way but it really seems like an edge
case to me and not really worth the extra method.

>>> Constructors of root resource classes and providers
>>> I think it is useful to define also in the spec, that only
>>> constructors are checked, if they are valid [...]
>> I don't understand what you mean, can you explain more ?
> Sorry, I forget the word "public". Use only public constructors.


>>> JSR 250 dependency
>>> The common dependency to JSR 250 for resource classes is placed in
>>> the javadoc of @Path. In the specification it is only available in
>>> the note to Java EE container. I think it is useful to put this
>>> from the @Path javadoc to the specification file, perhaps into the
>>> section "Constructors" of chapter "Resources". I think it is also
>>> useful for the providers.
>> Agree on removing it from @Path. Some of the JSR 250 annotations
>> only really make sense in an EE context so we may want to confine
>> mention of those annotations to the EE section of the spec.
> In @Path were only @PostConstruct and @PreDestroy defined to be
> honoured. I think, some initialization is also useful on non-EE
> environments. I've already implemented this both.
It also mentioned @Resource and there was an implication that all 250
annotations should be supported. I think we need to be explicit about
exactly which annotations are supported in which environments. Given
that we allow @Context on constructor parameters, use of
@PostConstruct seems less important in environments that don't support
other injectables...


Marc Hadley <marc.hadley at>
CTO Office, Sun Microsystems.