dev@jsr311.java.net

Re: Content Negotation vs. Extensions

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Thu, 26 Apr 2007 14:48:42 +0200

Dhanji R. Prasanna wrote:
> @UriTemplate("{customer_id}")
> class Customer {
>
>
> <snip>
>
> @UriTemplate(".json")
> @HttpMethod
> JSONObject getAsJSONResource() { ... }
>
> }
>
>
> I really dont like this at all. It doesnt make clear what the resource
> names are. I have to manually concatenate all the combinations (that
> exist or dont exist on each method) in order to tell the resource names
> represented by this *single* resource class.
>

I admit at first look it is not so obvious. At least for me having
developed v1 of the prototype that had similar functionality to what you
propose then developed v2 of the prototype there are significant
advantages to the relative composition and i did not find it such an
arduous task to know what the URI path would be. I found it
significantly reduced the amount of code and classes i had to write
while dramatically increasing the reuse potential of what i had written.
And therefore it increased my productivity as a developer. That IMHO is
a big win.


I view the Customer class not as a single resource because it serves a
whole bunch of customers so in effect the Java class corresponds to a
class of resources associated with some common application logic. When
the Java class is instantiated only then does it become specific to a
particular resource.

Is it such a stretch to think of a Java class not only operating on
/customers/1, /customers/2, /customers/3 .. etc. but also
/customers/1.xml, /customers/2.xml, /customers/3.xml ... ?


Relative resources make it possible to reuse application logic or Java
classes at different places in the URI path hierarchy. Thus the
Customer class can be referred to from other Java classes that have
different base paths.

Sorry for the long winded response below but i think it worth
highlighting why this can be so useful and how it naturally fits into
the Java programming model. For example, if the we have following 3
templates where a customer may be accessed:

    /customers/lastCustomer
    /customers/{id}
    /order/{id}/subcustomers/{id}


@UriTemplate("/customers/")
class Customers {

    // customers/lastCustomer
    @UriTemplate("lastCustomer")
    Customer getLastCustomerResource() { return new Customer(...); }

    // customers/{id}
    @UriTemplate("{id}")
    Customer getCustomerResource(...) { return new Customer(...); }
}

@UriTemplate("/orders/")
class Orders {

    // order/{id}
    @UriTemplate("{id}")
    Order getOrdersResource(...) { return new Order(...); }

}

class Order {

    // order/{id}/subcustomers/
    // order/{id}/subcustomers/lastCustomer
    // order/{id}/subcustomers/{id}
    @UriTemplate("subcustomers")
    Customers getCustomersResource() {
       // Extended version Customers taking into account
       // the association with orders id
       return new CustomersForOrder(...);
    }
}

public CustomersForOrder extends Customers { ... }


So Customers can reuse Customer in 2 different contexts, and Order can
reuse Customers and extend Customers for another 2 slightly different
contexts. This includes the reuse of .xml and .json (and any future
modifications) in all these contexts. Note that CustomerOrders could
also provide additional sub-resources because the Customer is now
polymorphic (while still being able to reuse the .xml and .json
functionality).


> Although i do like the way '_at_UriTemplates("", ".xml")' expresses things
> but could not think of anything better in the few minutes of thought
> about it.
>
>
> If you meant "dont" like, im with you--I think its very ugly. =(
>

I seem to be unconsciously removing "not"'s today! I meant what you say :-)


>
> I suggest the following (rather straightforward) approach:
>
> //resource at "default" name
> @URITemplate("/peeps/{person_id}")
> public class PersonResource {
>
> Person getPerson() {
> //...
> }
>
> @HttpMethod @Produces(TEXT_HTML)
> public Person get() { return getPerson(); }
>
> }
>
> //resource at alternate name
> @URITemplate("/peeps/{person_id}.xml")
> public class XmlPersonResource {
> @RsResource PersonResource res;
>
> @HttpMethod @Produces(TEXT_XML)
> public Person get() { return res.getPerson(); }
> }
>
> //etc.
>

That would work but I do not like the class explosion possibilities,
duplication of the template values and the way it limits reuse and
polymorphism. IMHO sub-resources solves the problem with less code and
better reuse.


>
> To me, this is a logical analog of the HTTP idiom: each resource name
> (in our case "name-template") has its own resource backing it. Alternate
> representations can delegate to the default resource impl (injected by
> the runtime), but this is a trivial implementation detail.
>
>
> So we would need a way to distinguish between path segments and non-path
> segments for HTTP methods that are marked as sub-resources, perhaps
> requiring things to being with a "/" ? (which just for URI
> template-based HTTP methods is a very easy fix to the implementation of
> the algorithm).
>
>
> Such impositions seem arbitrary and intrusive; and are a bit subtle to
> learn easily imo.

Yes, i agree that it is subtle, i think we can definitely improve on that.

Paul.


> At first blush, I think your matcher could be made to work nicely with
> the resource class-per-extension approach.
>


-- 
| ? + ? = To question
----------------\
    Paul Sandoz
         x38109
+33-4-76188109