dev@jsr311.java.net

Re: Content Negotation vs. Extensions

From: Stefan Tilkov <stefan.tilkov_at_innoq.com>
Date: Thu, 26 Apr 2007 16:35:24 +0200

FWIW, here's what Rails does:

def add
   company = params[:person].delete(:company)
   @company = Company.find_or_create_by_name(company[:name])
   @person = @company.people.create(params[:person])

   respond_to do |wants|
     wants.html { redirect_to(person_list_url) }
     wants.js
     wants.xml { render :xml => @person.to_xml(:include => @company) }
   end
end

Of course it's hard to translate all of the Ruby syntactic sugar
(blocks, method_missing hacks etc.) to Java, but the main different
is that in RoR, I can have a single method that returns different
representations. In my method, I don't even care whether it's the
Accept: header or the extension that was used to select the content
type.

Stefan


On Apr 26, 2007, at 2:48 PM, Paul Sandoz wrote:

> 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
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe_at_jsr311.dev.java.net
> For additional commands, e-mail: dev-help_at_jsr311.dev.java.net
>