[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: Related entries and feeds: links and link expansion



Pablo Castro wrote:
> One tricky aspect is that we need to indicate which 
> association it is. At the model level we have a "navigation 
> property" that identifies the starting "end" of the 
> association (e.g. "Attendees", "Venue"). We currently put 
> that name in the "title" attribute of the link. That solution 
> is not perfect, as we try not to overload constructs that are 
> for human-readable content. However, the alternative is to 
> use a custom attribute, and we've been trying not to 
> introduce custom attributes unless absolutely needed. Another 
> option would be to use different "rel" values to specify the 
> relationship, which feels natural but makes it much less 
> likely that generic processors will be able to do something 
> interesting with it.

There is no point in including a link to something totally unrelated to
the entry, so it is safe to assume that *any* link references related
content. rel="related" provides no useful information except to say that
the link is not an alternate link (rel="alternate" is the default).
Generic processors are unlikely to do anything with rel="related" that
they wouldn't do for some unknown link relation.

Instead of *custom* relations, we should develop common vocabularies for
different domains. But, that goes against the idea of allowing users to
shoehorn their existing ERD models into Atom documents, because it
requires them to design with Atom in mind beforehand.

> <entry>
>  <id>http://localhost:81/EventsSample/Events(456)</id>
>  <title type="text"></title>
>  <author>
>    <name />
>  </author>
>  <link rel="edit" title="Event" href="Events(456)" />
>  <link rel="related"
>        type="application/atom+xml;type=entry"
>        title="Venue"
>        href="Events(456)/Venue" />
> <link rel="related"
>       type="application/atom+xml;type=feed"
>       title="Attendees" href="Events(456)/Attendees" />
> <content type="application/xml">
>    <d:EventID m:type="Int32">456</d:EventID>
>    <d:Name>Big Party</d:Name>
>    <d:NoteToAttendees>It's going to be a great
party!</d:NoteToAttendees>
>    <d:DateAndTime
m:type="DateTime">2008-03-05T06:00:00</d:DateAndTime>
>  </content>
> </entry>

In this example, most of the elements of the Atom syntax (id, title,
author, link/@rel, link/@title, summary) are either unused or misused.
If the goal is to interoperate with other Atom implementations, I would
expect the entry to look something like this:

  <entry>
   <id>http://organization.org/events/Events(456)</id> 
   <!-- http://localhost... is never going to be a good atom:id
        because it is not even attempting to be globally unique.
        If this entry represents an event, then there is no need
        to have atom:id separate from the event ID. I actually
        recommend using urn:uuid for atom:id all the time, but
        that is a separate issue for another day... -->
   <title type="text">Big Party</title>
   <author>
     <name>A useful name</name>
   </author>
   <category scheme='http://organization.org/events' term='Event'/>
   <link rel="edit" title="Event" href="Events(456)" />
   <link rel="http://organization.org/events/Venue";
         type="application/atom+xml;type=entry"
         title="Venue"
         href="Events(456)/Venue" />
   <link rel="http://organization.org/events/Attendees";
         type="application/atom+xml;type=feed"
         title="Attendees" href="Events(456)/Attendees" />
   <summary>It's going to be a great party!</summary>
   <content type="application/xml">
     <d:DateAndTime
m:type="DateTime">2008-03-05T06:00:00Z</d:DateAndTime>
     <!--Use valid Atom date constructs to represent dates/times -->
   </content>
  </entry>

If you cannot nicely map the user's domain model into Atom's general
purpose data model then that is a really good indication that Atom
shouldn't be used. Otherwise, you aren't going to be able to
interoperate usefully with anybody except other Astoria users.

> 2. Expanding links inline
> 
> As I summarized at the beginning of this note, we want to 
> enable clients to request whole sub-graphs of data starting 
> at some resource or set of resources. There are two aspects 
> that need to be addressed: how does the client indicate that 
> it wants one or more links expanded and how are the expanded 
> links represented on the response.

> For representing expanded links we put the expanded content 
> inside the link element itself. According to section 4.2.7 of 
> RFC 4287:
> 
> "The "atom:link" element defines a reference from an entry or 
> feed to  a Web resource.  This specification assigns no 
> meaning to the content (if any) of this element."
> 
> So it seems that adding content to the link element is not 
> disallowed and at the same time it does not overlap with any 
> existing semantics given to such construct. Based on that we 
> thought it would be the perfect place for this information, 
> as the link itself already contains the metadata about the 
> link that we needed.

How do you deal with other extensions that also embed information within
the content of atom:link elements? How can you distinguish these other
extensions from the expanded data?

> I focused on the GET operations above. We think it would be 
> better to stay away from attempting to support full 
> modification operations on expanded graphs. In particular, we 
> do not handle PUT on more than one entry at a time today. We 
> do support POSTing an expanded graph, and we simply create 
> all the nested entries and link them to the parent entry, 
> creating the whole graph in a single operation.
> 
> Feedback in general about this approach would be greatly appreciated.

Instead of expanding the links within an entry, why not return a feed,
where each entry represents one entity in the result set, and make use
of link/@rel='alternate' or link/@rel='self'. For example:

 <feed>
    ...
   <entry>
     ...
     <link rel="http://organization.org/events/Venue";
           href="Events(456)/Venue"/>
     <link rel="http://organization.org/events/Attendees";
           href="Events(456)/Attendees"/>
     ...
     <category scheme='http://organization.org/events' term='Event'/>
   </entry>
   <entry>
     ...
     <link rel='self' href='Events(456)/Venue'/>
     <category scheme='http://organization.org/events' term='Venue'/>
     ...
   </entry>
   <entry>
     ...
     <link rel='self' href='Events(456)/Attendees'/>
     <category scheme='http://organization.org/events' term='Person'/>
     ...
   </entry>
 </feed>

The consumer of the feed can see that the second and third entries are
copies of the resources that are being linked to, which avoids the need
to hit the server to retrieve them. This is leveraging the pre-defined
Atom semantics instead of creating a new mechanism. In other words,
treat "$expand" as a request to include supplementary entries in the
feed. You might need a way of distinguishing the primary and
supplementary entries, but that shouldn't be too hard to come up with.

Notice that this scheme also seems to be easy to extend to support batch
updates of multiple parts of the subgraph using whatever general batch
update mechanisms become popular.

- Brian