One thing that might not be clear is that the UriTemplate values are
relative to a deployment context. Essentially the set of UriTemplates
define a subtree within a URI space that can be re-rooted as required.
Marc.
On Apr 24, 2007, at 6:27 AM, Jan Algermissen wrote:
> Hi Paul,
>
> maybe i am missing something, but I do not see how e.g. the
> InvoiceResource is matched on a request URI?
>
> Something else:
>
> I think that the actual paths (e.g. /invoice) are a configuration
> time issue and that dispatching from a request URI to
> a handler class should be done by a seperate component; it should
> not be part of the handler classes' source code
> (even if it's just an annotation).
>
> Suppose I hand the class files for the code below to someone else
> that really does not want the path to be '/invoices'; what then?
>
> Jan
>
> On 24.04.2007, at 10:44, Paul Sandoz wrote:
>
>> Hi
>>
>> Given the blink sale example (see below for Java classes presented
>> in another email) i thought it would be useful to describe how the
>> matching algorithm works (which Marc and I have implemented and
>> experimented with).
>>
>> See attached for a description that i hope helps explain things in
>> more detail.
>>
>> Paul.
>>
>> @UriTemplate("/invoices")
>> @SubResources({InvoiceResource.class})
>> class InvoicesResource {
>>
>> Date start, end;
>> String status, tags;
>>
>> public InvoicesResource(
>> @QueryParam("start") Date start,
>> @QueryParam("end") Date end,
>> @QueryParam("status") String status,
>> @QueryParam("tags") String tags)
>> ...
>> }
>>
>> @ProduceMime("application/vnd.blinksale+xml")
>> @HttpMethod
>> Invoices getInvoices() {
>> ...
>> }
>>
>> @ProduceMime("application/atom+xml")
>> @HttpMethod
>> Feed getInvoicesAsFeed() {
>> ...
>> }
>>
>> @ProduceMime("text/calendar")
>> @HttpMethod
>> Calendar getInvoicesAsCalendar() {
>> ...
>> }
>>
>> @ConsumeMime("application/vnd.blinksale+xml'")
>> @HttpMethod
>> Created postInvoice(Invoice i) {
>> ...
>> }
>>
>> }
>>
>>
>> @UriTemplate("{invoice_Id}")
>> class InvoiceResource {
>>
>> int id;
>>
>> public InvoiceResource(
>> @UriParam("invoice_Id}" int id) {
>> if (id not recognized)
>> throw NotFoundException(...);
>>
>> this.id = id;
>> }
>>
>> @ProduceMime("application/vnd.blinksale+xml'")
>> @HttpMethod
>> Invoice getInvoice() {
>> ...
>> }
>>
>> @ProduceMime("application/atom+xml")
>> @HttpMethod
>> Entry getInvoicesAsEntry() {
>> ...
>> }
>>
>> @ConsumeMime("application/vnd.blinksale+xml'")
>> @HttpMethod
>> void putInvoice(Invoice i) {
>> ...
>> }
>>
>> @HttpMethod
>> void deleteInvoice() {
>> ...
>> }
>>
>> @UriTemplate("deliveries")
>> DeliveriesResource getDeliveriesResource () {
>> return new DeliveriesResource(i);
>> }
>>
>> @UriTemplate("payments")
>> PaymentsResource getPaymentsResource () {
>> return new PaymentsResource(i);
>> }
>> }
>>
>> --
>> | ? + ? = To question
>> ----------------\
>> Paul Sandoz
>> x38109
>> +33-4-76188109
>> Static resource: a resource whose corresponding concrete Java
>> class is known statically to the runtime. Such resources are:
>>
>> Java classes annotated with @UriTemplate that has an absolute URI
>> template (begins with a '/');
>>
>> Java classes referenced by a @SubResources declared on a Java
>> class that is a resource.
>>
>> Dynamic resource: a resource whose corresponding to a concrete
>> Java class cannot be determined statically and is determined
>> dynamically by the application. Such a resource is the concrete
>> Java class of a Java object returned from a Java method annotated
>> with a @UriTemplate.
>>
>> The resource matching algorithm is a recursive algorithm that
>> consumes the URI path, from left to right, in accordance to the
>> matching URI templates of resources and the sub-relationship
>> between resources corresponding to the hierarchy of the URI path.
>>
>> The algorithm can be specified using regular expressions since a
>> URI template can be converted to a regular expression.
>>
>> NOTE The algorithm can be easily implemented using regular
>> expressions but can also be implemented using more optimal
>> mechanisms as long as the results are the same. Furthermore
>> regular expressions may be coalesced for statically determined sub-
>> relationships as long as the results are the same.
>>
>> For a resource containing sub-resources the regular expression
>> generated from the URI template associated with that resource is
>> augmented with the expression (/.*)? that represents the
>> matching group for the right-hand-side of the URI path that will
>> be matched against sub-resources. This matching group will always
>> be the last matching group, matching groups for template values
>> will always occur before. For a resource containing no sub-
>> resources the regular expression is augmented with (/)?.
>>
>> NOTE Using (/.*)? or (/)? enables the runtime to perform
>> automatic redirection for cases where a URI template ends with a
>> slash but the URI path does not. For example if a resource has the
>> URI template /invoices/ and the URI path is /invoices then the
>> runtime can detect this and automatically send an HTTP redirect to
>> /invoices/.
>>
>> A resource having one or more sub-resources will have one or more
>> URI templates and therefore one or more regular expressions to
>> match against. The regular expressions are ordered as follows:
>>
>> The regular expression with the most matching groups is ordered
>> first; and
>>
>> If two regular expressions have the same number of matching groups
>> then the most explicit expression is ordered first.
>>
>> The URI path is matched against each regular expressions (in
>> order) until a matching expression is found. If no matching
>> expression is found then a resource cannot be found for the URI
>> path. If a matching expression is found then the matching right-
>> hand path (the last matching group) is obtained and this becomes
>> the new URI path to match against a new set of URI templates
>> obtained from the matching sub-resource.
>>
>> The algorithm terminates when the URI path is consumed. A Java
>> method that is capable of processing the HTTP request will then be
>> invoked on the last matched resource obtained by the algorithm.
>>
>> The following table presents an example using the BlinkSale API
>> for the URI path /invoices/1/deliveries/2 where each segment of
>> the path corresponds to a resource and a Java class corresponding
>> to a resource references its sub-resources using static or dynamic
>> mechanisms.
>>
>> Step
>>
>> URI path
>>
>> URI templates
>>
>> Matching regular expression
>>
>> Matching groups
>>
>> 1
>>
>> /invoices/1/deliveries/2
>>
>> /clients
>>
>> /invoices
>>
>> /invoices(/.*)?
>>
>> (/1/deliveries/2)
>>
>> 2
>>
>> /1/deliveries/2
>>
>> {invoice_id}
>>
>> /(.*?)(/.*)?
>>
>> (1, /deliveries/2)
>>
>> 3
>>
>> /deliveries/2
>>
>> /deliveries
>>
>> /payments
>>
>> /deliveries(/.*)?
>>
>> (/2)
>>
>> 4
>>
>> /2
>>
>> {delivery_id}
>>
>> /(.*?)(/.*)?
>>
>> (2, null)
>>
>> 5
>>
>> null
>>
>>
>>
>>
>>
>>
>>
>> At step 5 the Java method that is capable of processing the HTTP
>> request will be invoked on the instance of the Java class that is
>> the resource associated with delivery 2 of invoice 1.
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: dev-unsubscribe_at_jsr311.dev.java.net
>> For additional commands, e-mail: dev-help_at_jsr311.dev.java.net
>
---
Marc Hadley <marc.hadley at sun.com>
CTO Office, Sun Microsystems.
- application/pkcs7-signature attachment: smime.p7s