Examples of Collection Storage Resources
Last modified 12:50 ET January 7, 2008
Assumptions:
- Jazz is running at http://example.com
- client has already been authenticated as a user named Zoe
- existing project /jazz/projects/main
- zoe is authorized to work in project main
- extant collection resource at /jazz/resources/main/root
- strings like "[xxx]" indicate a specific value, like a timestamp or e-tag. The particulars are less interesting that the fact that these values reoccur in various requests and response in predictable ways.
Each step shows 1 round trip from client to server.
==========================================
Note that the Text in [TestCase.Operation] represents a cross-reference into the Open Resource Services test suite to ensure coverage of the examples below.
These examples show the AtomPub style of resource creation. Rather than start with collection creation, the example begins by assuming that a collection already exists at the path "/jazz/resources/main/root", and shows how new non-collection resources can be added to the collection.
STEP 1
Use GET to retrieve a representation of the collection resource (and atom:feed document). [AtomTests.testCreateNewFeed]
GET /jazz/resources/main/root HTTP/1.1
Host: example.com
Authorization: [zoe's credential]
Date: [t10]
HTTP/1.1 200 OK
Date: [t10]
Content-Type: application/atom+xml
Content-Length: [nnn]
ETag: [tag0]
Last-Modified: [t0]
[urn:uuid identifying /jazz/resources/main/root
collection resource]root[t0][somebody]
The representation shows that the collection is empty (no atom:entry elements in the atom:feed). A POST of a regular resource creates a pair of resources. The Entry resource shows up in the collection, and the Media resource is the one that holds the resource representation.
STEP 2
Create a resource in the collection /jazz/resources/main/root using POST, suggesting that "file1" be its simple name. [AtomTests.testAddToFeed]
POST /jazz/resources/main/root HTTP/1.1
Host: example.com
Date: [t20]
Authorization: [zoe's credentials]
Content-Type: text/plain
Content-Length: [nnn]
Slug: file1
Whiter shade of pale.
HTTP/1.1 201 CREATED
Date: [t20]
Content-Length: [nnn]
Content-Type: application/atom+xml;type=entry
Location: /jazz/resources/main/root/file1.entry
Content-Location /jazz/resources/main/root/file1.entry
ETag: [tag20]
Last-Modified: [t20]
[urn:uuid identifying
/jazz/resources/main/root/file1.entry resource]file1[t20]Zoe
The server creates the Entry resource at /jazz/resources/main/root/file1.entry, adds it to the collection, and returns its representation. The server also creates the Media resource at /jazz/resources/main/root/file1, and links to it from the Entry resource.
STEP 3
Retrieve the Entry resource at /jazz/resources/main/root/file1.
GET /jazz/resources/main/root/file1 HTTP/1.1
Host: example.com
Date: [t30]
Authorization: [zoe's credentials]
HTTP/1.1 200 OK
Date: [t30]
Content-Type: text/plain
Content-Length: [nnn]
ETag: [tag20-media]
Last-Modified: [t20]
Whiter shade of pale.
A representation of the media resource was successfully retrieved.
STEP 3A
Retrieve the Media resource at /jazz/resources/main/root/file1.entry.
GET /jazz/resources/main/root/file1.entry HTTP/1.1
Host: example.com
Date: [t31]
Authorization: [zoe's credentials]
HTTP/1.1 200 OK
Date: [t31]
Content-Type: application/atom+xml;type=entry
Content-Length: [nnn]
ETag: [tag20]
Last-Modified: [t20]
[urn:uuid identifying
/jazz/resources/main/root/file1.entry resource]file1[t20]Zoe
A representation of the entry resource was successfully retrieved.
STEP 3B
The client now updates the Entry resource at /jazz/resources/main/root/file1.entry adding an atom:category element.
PUT /jazz/resources/main/root/file1.entry HTTP/1.1
Host: example.com
Date: [t32]
Authorization: [zoe's credentials]
Content-Type: application/atom+xml;type=entry
Content-Length: [nnn]
If-Match: [tag20]
If-Unmodified-Since: [t20]
file1
HTTP/1.1 200 OK
Date: [t32]
Content-Length: [nnn]
Location: /jazz/resources/main/root/file1.entry
Content-Location: /jazz/resources/main/root/file1.entry
ETag: [tag32]
Last-Modified: [t32]
[urn:uuid identifying
/jazz/resources/main/root/file1.entry
resource]file1[t32]Zoe
The representation shows that the collection now has a member resource, /jazz/resources/main/root/file1.entry.
STEP 4
Retrieve the collection at /jazz/resources/main/root.
GET /jazz/resources/main/root HTTP/1.1
Host: example.com
Authorization: [zoe's credentials]
Date: [t40]
HTTP/1.1 200 OK
Date: [t40]
Content-Type: application/atom+xml
Content-Length: [nnn]
ETag: [tag32]
Last-Modified: [t32]
[urn:uuid identifying /jazz/resources/main/root
collection resource]root[t20][somebody][urn:uuid identifying resource
/jazz/resources/main/root/file1.entry]file1[t32]Zoe
The representation shows that the collection now has a member resource. Note that although the atom:entry was last modified at t32, the atom:feed itself was considered to have been last modified at t20 when an entry was added. Updating an entry is not considered a significant update to the containing collection.
STEP 5
Update the Media resource at /jazz/resources/main/root/file1.
PUT /jazz/resources/main/root/file1 HTTP/1.1
Host: example.com
Date: [t50]
Authorization: [zoe's credentials]
If-Match: [tag20-media]
If-Unmodified-Since: [t20]
Content-Type: text/plain
Content-Length: [nnn]
Walk away Renee.
HTTP/1.1 204 No content
Date: [t50]
Content-Length: [nnn]
The resource was successfully updated.
STEP 6
Retrieve the collection at /jazz/resources/main/root.
GET /jazz/resources/main/root HTTP/1.1
Host: example.com
Authorization: [zoe's credentials]
Date: [t60]
HTTP/1.1 200 OK
Date: [t60]
Content-Type: application/atom+xml
Content-Length: [nnn]
ETag: [tag50]
Last-Modified: [t50]
[urn:uuid identifying /jazz/resources/main/root
collection resource]root[t20][somebody][urn:uuid identifying resource
/jazz/resources/main/root/file1.entry]file1[t50]Zoe
The representation has an atom:entry with an atom:updated element changed since last time (but is otherwise the same). The atom:updated element of the atom:feed itself is unchanged.
STEP 7
Delete the resource at /jazz/resources/main/root/file1, using preconditions which fail.
DELETE /jazz/resources/main/root/file1 HTTP/1.1
Host: example.com
Date: [t70]
Authorization: [zoe's credentials]
If-Match: [tag20]
If-Unmodified-Since: [t20]
HTTP/1.1 409 CONFLICT
Date: [t70]
Content-Length: [nnn]
The operation fails because the resource has been updated in between.
STEP 8
Delete the resource at /jazz/resources/main/root/file1 again, using preconditions which pass.
DELETE /jazz/resources/main/root/file1 HTTP/1.1
Host: example.com
Date: [t80]
Authorization: [zoe's credentials]
If-Match: [tag50-media]
If-Unmodified-Since: [t50]
HTTP/1.1 204 No content
Date: [t80]
Content-Length: [nnn]
The resource was successfully deleted.
STEP 9
Check that the resource at /jazz/resources/main/root/file1 has gone away (without a trace).
HEAD /jazz/resources/main/root/file1 HTTP/1.1
Host: example.com
Date: [t90]
Authorization: [zoe's credentials]
HTTP/1.1 404 Not found
Date: [t90]
Content-Length: [nnn]
It Worked.
STEP 10
Retrieve the collection /jazz/resources/main/root.
GET /jazz/resources/main/root HTTP/1.1
Host: example.com
Authorization: [zoe's credentials]
Date: [t60]
HTTP/1.1 200 OK
Date: [t100]
Content-Type: application/atom+xml
Content-Length: [nnn]
ETag: [tag80]
Last-Modified: [t80]
[urn:uuid identifying /jazz/resources/main/root
collection resource]root[t80][somebody]
The resource has disappeared from the collection.
==========================================
These are the basic mechanics of adding a non-collection resource to a collection, updating the resource, and deleting it.
The following steps show how new collection resources are created.
There are 2 different ways in which a collection resource can be created.
Create a collection by PUTing to a client-supplied URI.
Create a collection by POSTing to an existing collection.
We'll show case (2) first, since it's the more similar to above.
STEP 11
Create a new collection resource in the collection /jazz/resources/main/root using POST, suggesting that "bin1" be its simple name.
POST /jazz/resources/main/root HTTP/1.1
Host: example.com
Date: [t110]
Authorization: [zoe's credentials]
Content-Type: application/atom+xml
Content-Length: [nnn]
Slug: bin1
bin1
HTTP/1.1 201 CREATED
Date: [t110]
Content-Length: [nnn]
Location: /jazz/resources/main/root/bin1
Content-Type: application/atom+xml;type=entry
Location: /jazz/resources/main/root/bin1.entry
Content-Location /jazz/resources/main/root/bin1.entry
ETag: [tag110]
Last-Modified: [t110]
[urn:uuid identifying
/jazz/resources/main/root/bin1.entry resource]bin1[t110]Zoe
The server creates the collection resource at /jazz/resources/main/root/bin1 and the Entry resource /jazz/resources/main/root/bin1.entry, adds the resource to the root collection, and returns a representation of the Entry resource.
STEP 12
Retrieve the new collection resource at /jazz/resources/main/root/bin1.
GET /jazz/resources/main/root/bin1 HTTP/1.1
Host: example.com
Date: [t120]
Authorization: [zoe's credentials]
HTTP/1.1 200 OK
Date: [t120]
Content-Type: application/atom+xml
Content-Length: [nnn]
ETag: [tag110-media]
Last-Modified: [t110]
[urn:uuid identifying the new
collection resource]bin1[t110]Zoe
A representation of the new collection resource was successfully retrieved.
STEP 13
Retrieve the collection /jazz/resources/main/root.
GET /jazz/resources/main/root HTTP/1.1
Host: example.com
Authorization: [zoe's credentials]
Date: [t130]
HTTP/1.1 200 OK
Date: [t130]
Content-Type: application/atom+xml
Content-Length: [nnn]
ETag: [tag110]
Last-Modified: [t110]
[urn:uuid identifying /jazz/resources/main/root
collection resource]root[t110][somebody][urn:uuid identifying resource
/jazz/resources/main/root/bin1.entry]bin1[t110]Zoe
The representation shows that the root collection now has the new collection resource as a member.
STEP 14
Create a resource in the collection /jazz/resources/main/root/bin1 using POST, suggesting that "file2" be its simple name.
POST /jazz/resources/main/root/bin1 HTTP/1.1
Host: example.com
Date: [t140]
Authorization: [zoe's credentials]
Content-Type: text/plain
Content-Length: [nnn]
Slug: file2
Sitting on the dock of the bay.
HTTP/1.1 201 CREATED
Date: [t140]
Content-Length: [nnn]
Location: /jazz/resources/main/root/bin1/file2.entry
Content-Location:
/jazz/resources/main/root/bin1/file2.entry
ETag: [tag140]
Last-Modified: [t140]
[urn:uuid identifying
/jazz/resources/main/root/bin1/file2.entry resource]file2[t140]Zoe
The server creates the Entry resource at /jazz/resources/main/root/bin1/file2.entry and adds it to the collection. It also creates the Media resource at /jazz/resources/main/root/bin1/file2.
STEP 15
Slam the collection resource at /jazz/resources/main/root/bin1 to be a non-collection. [ClobberTests.testSafeSimpleOverAtom]
PUT /jazz/resources/main/root/bin1 HTTP/1.1
Host: example.com
Date: [t150]
Authorization: [zoe's credentials]
Content-Type: text/plain
Content-Length: [nnn]
If-Match: [tag140-media]
If-Unmodified-Since: [t140]
These boots are made for walkin'.
HTTP/1.1 405 Method not allowed
Date: [t50]
Allow: GET, HEAD, POST, DELETE
Content-Length: [nnn]
The server disallows a change that would replace the collection resource with a non-collection resource. To do this, the client would need to delete the existing collection resource, and then create a non-collection resource in its place.
STEP 16
Slam the non-collection resource at /jazz/resources/main/root/bin1/file2 to be a collection. [ClobberTests.testSafeAtomOverSimple]
PUT /jazz/resources/main/root/bin1/file2 HTTP/1.1
Host: example.com
Date: [t160]
Authorization: [zoe's credentials]
Content-Type: application/atom+xml
Content-Length: [nnn]
If-Match: [tag140-media]
If-Unmodified-Since: [t140]
file2
HTTP/1.1 405 Method not allowed
Date: [t160]
Allow: GET, HEAD, POST, DELETE
Content-Length: [nnn]
The server disallows a change that would replace the non-collection resource with a collection resource. The client must delete the existing resource, and then create a collection resource in its place.
STEP 17
Create a new collection resource at /jazz/resources/main/root/bin1/folder3 using PUT (the 2nd way to create collections). [AtomTests.testCreateUsingArbitraryUrl]
PUT /jazz/resources/main/root/bin1/folder3 HTTP/1.1
Host: example.com
Date: [t170]
Authorization: [zoe's credentials]
Content-Type: application/atom+xml
Content-Length: [nnn]
If-None-Match: *
folder3
HTTP/1.1 201 CREATED
Date: [t110]
Location: /jazz/resources/main/root/bin1/folder3
Content-Length: [nnn]
The server creates the collection resource at /jazz/resources/main/root/bin1/folder3. Since the new resource was not created by POSTing it to the collection at /jazz/resources/main/root/bin1, it is unaffiliated with that collection, despite the similar URIs.
STEP 18
Delete the collection at /jazz/resources/main/root/bin1. [AtomTests.testCreateUsingArbitraryUrl]
DELETE /jazz/resources/main/root/bin1 HTTP/1.1
Host: example.com
Date: [t180]
Authorization: [zoe's credentials]
If-Unmodified-Since: [t140]
If_Match: [tag140-media]
HTTP/1.1 204 No content
Date: [t180]
Content-Length: [nnn]
The collection /jazz/resources/main/root/bin1 is successfully deleted along with its member resource /jazz/resources/main/root/bin1/file2. Note that the resource at /jazz/resources/main/root/bin1/file3 is unaffected.
STEP 19
The client POSTs an Entry document to a collection resource. [AtomTests.testAddToFeed]
POST /jazz/resources/main/root HTTP/1.1
Host: example.com
Date: [t190]
Authorization: [zoe's credentials]
Content-Type: application/atom+xml;type=entry
Slug: entry5
Content-Length: [nnn]
entry5The official US
time
HTTP/1.1 201 CREATED
Date: [t190]
Content-Length: [nnn]
Location: /jazz/resources/main/root/entry5
Content-Location: /jazz/resources/main/root/entry5
ETag: [tag190]
Last-Modified: [t190]
[urn:uuid identifying
/jazz/resources/main/root/entry5 resource]entry5[t190]ZoeThe official US
time
The server creates the Entry resource at /jazz/resources/main/root/entry5. The response includes the representation of the Entry resource.
STEP 20
The client now updates the Entry resource at /jazz/resources/main/root/entry5 with out-of-line content.
PUT /jazz/resources/main/root/entry5 HTTP/1.1
Host: example.com
Date: [t200]
Authorization: [zoe's credentials]
Content-Type: application/atom+xml;type=entry
Content-Length: [nnn]
Slug: entry5
If-Match: [tag190]
If-Unmodified-Since: [t190]
entry5Good morning
starshine.
HTTP/1.1 204 No data
Date: [t200]
Content-Length: [nnn]
STEP 21
The client retrieves the resource-collection property for the Entry resource
at /jazz/resources/main/root/entry5.
GET /jazz/resources/main/root/entry5?properties=resource-collection HTTP/1.1
Host: example.com
Date: [t210]
Authorization: [zoe's credentials]
/jazz/resources/main/root
(End of examples.)