Collection Resource Storage Core Service

This specification allows Atom Syndication Format-based collections to be created by using a PUT request to a user-defined URI (simple resource storage). In this case the server will recognize a representation with the MIME type application/atom+xml and the root element atom:feed as a request to create a new collection. Collections are resources and collections own atom:entry resources corresponding to members of the collection. POSTing a non-entry (a Content Type other than application/atom+xml;type=entry ) representation to a collection creates a Media resource in addition to the Entry resource. The Media resource holds the client-supplied representation verbatim (except for nested collections). The Entry resource has an atom:content that links to the Media resource. The server determines the URIs that identify the Entry and Media resource. A collection may contain another, nested, collection as a Media resource. A nested collection is created by using a POST request to a collection resource URI. The server will recognize a representation with the MIME type application/atom+xml and the root element atom:feed as a request to create a new, nested, collection as a Media resource.

Motivation

The collection resource storage API described here differs from the simple resource storage API in the following ways (see Atom Syndication Format and Atom Publishing Protocol).

  1. A collection tracks membership and allows the retrieval of a feed that lists all members of the collection.
  2. New members are created with the HTTP POST and not PUT method.
  3. Clients do not specify the final URL of the POSTed resource, the server/collection assign the URL and return it to the client in the HTTP "Location" response header.
  4. Because of the ownership relationship between a collection and it's members the deletion of a collection implies the deletion of all members thereof.

The benefits for many clients is that groups of resources can be stored logically as a set, and can be deleted as a set. Also the benefit of having server-assigned URLs saves a client having to worry about generating URLs that wont clash on the server.

Specification

The specification for the simple resource storage relies on the client providing the {resource-uri} in all cases.

Method URL Comments
GET/HEAD {collection-uri} Returns either the feed resource with a status code of 200 (OK) or 204 (no content), or one of the following errors: 304 (unmodified), 401 (unauthorized), 403 (forbidden), 404 (not found), 410 (gone), 500 (server error) or 503 (service unavailable).
GET/HEAD {collection-uri}/{member} As per the simple storage specification.
POST {collection-uri} Returns the created Atom entry, with a status code of 201 (created), or one of the following errors: 400 (bad request), 401 (unauthorized), 403 (forbidden), 404 (not found), 500 (server error) or 503 (service unavailable).
POST {collection-uri}/{member} As per the simple storage specification.
PUT {collection-uri} Updating an existing feed requires that the new representation MUST also be a valid Atom feed. For status codes see the simple storage specification. It is possible to update the representation of a feed even when the feed contains elements but the representationn PUT must not contain these entries.
PUT {collection-uri}/{member} As per the simple storage specification.
DELETE {collection-uri} Deletion of a collection implies deletion of the collection and ALL members. For status codes see the simple storage specification.
DELETE {collection-uri}/{member} As per the simple storage specification.

Notes:

  1. Clients MUST have the Reader role to perform a GET or HEAD method and MUST have Writer role to perform PUT or DELETE.
  2. A successful GET or HEAD MUST return, in the Content-Location header, the revision-specific URL to the resource.
  3. A successful HEAD MAY return either 204 (no content) or 200 (OK) with Content-Length set to 0.
  4. A successful PUT which creates a new resource MUST return the URL of the resource in the Location header.
  5. A Client MUST specify a cache-conditional header on any write (PUT, DELETE) operation (see here). Failure to do so results in a bad request status code.
  6. When comparing cache-conditional headers on GET or HEAD and the resource has not changed then 304 is returned, if the cache-conditional headers do not match any resource then 412 (pre-condition failed) is returned.
  7. When comparing cache-conditional headers on PUT or DELETE and the resource has not changed the resource is updated, if the cache-conditional headers are stale a 409 (conflict) is returned. If the cache-conditional headers do not match any resource then 412 (pre-condition failed) is returned.

To successfully create a resource the cache-conditional header "If-None-Match: *" will succeed.

Media Entries

An Atom collection/feed consists primarily of Atom entries; however clients can POST non-Atom resources to a collection and in this case the POSTed resource is termed a "media resource" and the server creates an Atom entry that describes it. In the case that a client POSTS an Atom entry the server simply stores the entry as a member of the collection. If the user POSTs some other resource the server has to create two resources, the posted content as a media resource and its corresponding entry. In either of these cases the returned content and Location header on a successful POST are for the atom entry and not the media entry. This can be confusing initially, the user POSTs a JPEG image but the returned URL is to the entry that describes the JPEG. However the returned Atom entry does contain a link to the media entry, which is also true for entries in a retrieved feed

Member Naming Policies

One significant advantage of the collection resource storage, over simple resource storage, is that the URL of entries and media entries are server-assigned. Therefore, the client MUST NOT make any assumptions about how the resulting resources are identified. The Entry resource is identified by the URI in the Location header in the response to the POST. The Media resource (if any) is identified by the "src" attribute of the atom:content element in the response body.

However, some control is handed back to clients in the use of a Member Naming Policy that is used when a collection is created to denote the manner in which the server should name new members added to the collection. This naming policy is provided as a foreign element in the feed representation when the client uses a PUT request to create the feed. This policy element takes the form:

<policy:memberNamingPolicy 
    xmlns:policy="http://example.org/xmlns/openservices/v0.6"
    scheme="serial-number" />

The policy:memberNamingPolicy has a single, required, attribute in this specification and this attribute defines the actual scheme to use. An Open Services for Lifecycle Collaboration provider is at liberty to provide additional optional attributes and elements to the schemes defined here (but no additional required attributes or elements) and is at liberty to provide additional schemes. The following describes the schemes required for a Collection Storage service to provide.

UUID-rfc4122
Each member's identifier is provided as a UUID encoded in hex format, as described in RFC4122. It is Assumed that the URL would take the form {collection-url}/{uuid}; so therefore if a user posted an entry to a collection with the URL /jazz/resources/myfeed the server might respond with a Location header identifying the new URL as /jazz/resources/myfeed/f81d4fae-7dec-11d0-a765-00a0c91e6bf6.entry might be returned.
UUID
As above, but to limit the size of the URL the 128-bit value of the UUID is serialized using base-64 as opposed to hex. The same request described above might result in an entry URL of the form: /jazz/resources/myfeed/_bV9UMDBNEdq_sa2-mTt1NA.entry
serial-number
Quite simply this scheme assigns a monotonically incrementing positive integer to each new entry. This is a useful scheme to use in creating resources which users tend to refer to by it's identifier. The same request described above might result in an entry URL of the form: /jazz/resources/myfeed/1.entry
name
The "name" scheme says that the client is responsible for supplying a string that will be used in calculating the URIs of the entry and media resources. The string is passed in the Slug request header of the POST request to the collection resource. Strings wich do not conform to the "segment" production of section 3.3 of the URI specification will be translated into strings that do conform. Slug headers which do not conform to the "segment" production will be translated by replacing illegal characters with the "_" character. Omitting the Slug header is equivalent to explicitly passing the empty string. If the slug is not provided, or the resulting name is already in use the server is at liberty to construct a replacement name.
name-strict
The same as the "name" scheme, except that if the name is omitted, or the name is already in use the server will not construct a replacement but will return a status code of 400 (bad request).

Atom:entry information accepted from client

The client furnishes an atom:entry in order to create a new Entry resource in a collection, or to update an existing Entry resource. The client MUST supply a valid atom:entry element. Beyond that, the client has considerable leeway in exactly what information they provide. And the server has leeway in what information from the client is taken at face value.

The server is solely responsible for the atom:id, atom:updated, atom:author, and certain atom:link elements. The client MAY supply these; the server MUST ignore them.

  1. A client-supplied atom:id element is ignored. The id is supplied by the server as the Entry resource is being created.
  2. A client-supplied atom:updated element is ignored. This timestamp is supplied by the server, and is always the time the Entry resource was last updated.
  3. A client-supplied atom:author element is ignored. This author is filled in by the server, and always identifies the party that last updated the resource.
  4. A client-supplied atom:link with rel="self" is ignored. Self links are supplied by the server and connect the entry representation to the URI of the Entry resource.
  5. A client-supplied atom:link with rel="edit-media" is ignored for entries that correspond to Media resources. These links are supplied by the server and connect the entry representation to the URI of the Media resource.
  6. A client-supplied atom:link with rel="http://example.org/xmlns/openservices/v0.6#parent" is ignored. This link is supplied by the server, and always identifies the containing collection resource.

For an Entry resource that corresponds to a Media resource, the server is solely responsible for the atom:content element.

For Entry resources that do not correspond to a Media resource, the client is solely responsible for the atom:content element.

The client is responsible for the atom:title and atom:summary elements. For a new Entry resource that corresponds to a Media resource, the server initially uses the Slug as the atom:title and supplies an empty atom:summary.

Atom:feed information accepted from client

The client furnishes an atom:feed in order to create a new Collection resource. The client MUST supply a valid atom:feed element. Beyond that, the client has considerable leeway in exactly what other information they provide. And the server has leeway in what information from the client is taken at face value.

The server is solely responsible for the atom:id, atom:updated, atom:author, and certain atom:link elements. The client MAY supply these; the server MUST ignore them.

  1. A client-supplied atom:id element is ignored. The id is supplied by the server as the Collection resource is being created.
  2. A client-supplied atom:updated element is ignored. This timestamp is supplied by the server, and is always the time the Collection resource was last updated.
  3. A client-supplied atom:author element is ignored. This author is filled in by the server, and always identifies the party that created the Collection resource.
  4. A client-supplied atom:link with rel="self" is ignored. Self links are supplied by the server and connect the collection representation to the URI of the Collection resource.

The client is responsible for the atom:title element.

When does a Collection resource change?

When the collection resource gains or loses a member:

  1. New value for atom:updated element of atom:feed
  2. Modification propagates to any containing collection
  3. New ETag and Last-Modified for representation of collection resource
  4. New revision of collection resource

Member of a collection is updated (affects Entry or Media resource):

  1. Unchanged value for atom:updated element of atom:feed
  2. Modification does not propagate to any containing collection
  3. New ETag and Last-Modified for representation of member resource
  4. New revision of member resource

Paging of Large Collections

To support large collections the server MAY break the atom:feed into chunks using the approach specified in section 10.1 of the Atom Publishing Protocol, which employs atom:link elements in the atom:feed with relation "next", "previous", "first", and "last". All page URLs provided will expire after a server determined period of time. The server MUST return 404 Not Found on GET of an expired page URL. Page URLs are for navigation of the pages only and should be considered as opaque to the client. Clients MUST NOT attempt to construct their own paging URLs as the format of these URLs may change in the future.

For feeds that contain paging links the server MUST include an OpenSearch results element:

<opensearch:itemsPerPage>10</opensearch:itemsPerPage>

Other OpenSearch results elements MAY be provided by the server but not required. In terms of query consistency there are two models; the first is to cache the query results and the client will receive pages one by one from these cached results, the second is to re-run the query each time a client requests a particular page and navigate to the start of the requested page. To ensure consistency of implementations paging should be provided based upon a query result cache.

Server Provided Properties for Collection Members

Sometimes it is necessary to discover the collection and/or entry that a given resource belongs to. The server will support this by providing properties whose value is the URI of the collection and/or entry. Like other server properties, these properties are available as a property for queries. Queries would be able to search for a resource with values matching these properties. Property fetches (i.e, {uri}?properties) would be able to retrieve these properties. The table below defines the properties and when they are available.

Property Description
resource-collection Entries and media resources will have this property. This property will be the URI of the collection in which the resource was created.
resource-entry Media resources will have this property. This property will be the URI of the entry that was created for this resource when the resource was POSTed to the collection.

Examples