This example demonstrates a simple in-memory web storage service.
The web storage service enables clients to create and delete containers. Containers are used to create, read, update, and delete items of arbitrary content, and to search for items containing certain content. A container can be thought of as a hash map of items. The key of an item is a URI path.
The web storage service ensures that content can be cached (by browsers
and proxies) by supporting the HTTP features Last-Modified
and ETag
.
The example consists of three web resources implemented by the following:
com.sun.jersey.samples.storageservice.resources.ContainersResource
com.sun.jersey.samples.storageservice.resources.ContainerResource
com.sun.jersey.samples.storageservice.resources.ItemResource
The mapping of the URI path space is presented in the following table:
URI path | Resource class | HTTP methods |
---|---|---|
/containers | ContainersResource | GET |
/containers/{container} | ContainerResource | GET, PUT, DELETE |
/containers/{container}/{item} | ItemResource | GET, PUT, DELETE |
Run the example as follows:
mvn clean compile exec:java
This deploys the web storage service using Grizzly
A WADL description may be accessed at the URL:
http://127.0.0.1:9998/storage/application.wadl
Following steps are using cURL command line tool:
Get the containers:
curl http://127.0.0.1:9998/storage/containers
This returns the following XML document:
<containers/>
No containers are present.
Create a container:
curl -X PUT http://127.0.0.1:9998/storage/containers/quotes
This creates a container called 'quotes'. Getting the containers:
curl http://127.0.0.1:9998/storage/containers
returns information about the 'quotes' container:
<containers> <container> <name>quotes</name> <uri>http://127.0.0.1:9998/storage/containers/quotes</uri> </container> </containers>
Create some content:
curl -X PUT -HContent-type:text/plain --data "Something is rotten in the state of Denmark" http://127.0.0.1:9998/storage/containers/quotes/1 curl -X PUT -HContent-type:text/plain --data "I could be bounded in a nutshell" http://127.0.0.1:9998/storage/containers/quotes/2 curl -X PUT -HContent-type:text/plain --data "catch the conscience of the king" http://127.0.0.1:9998/storage/containers/quotes/3 curl -X PUT -HContent-type:text/plain --data "Get thee to a nunnery" http://127.0.0.1:9998/storage/containers/quotes/4
The 'quotes' container has four items associated with keys 1, 2, 3, and 4 when GETing the quotes container:
curl http://127.0.0.1:9998/storage/containers/quotes
it returns:
<container> <item> <digest>7a54c57975de11bffcda5bc6bd92a0460d17ad03</digest> <lastModified>2007-01-10T15:07:48+01:00</lastModified> <mimeType>text/plain</mimeType> <name>1</name> <uri>http://127.0.0.1:9998/storage/containers/quotes/1</uri> </item> <item> <digest>4769363fcf4d0513619c6a30724daab396a1d196</digest> <lastModified>2007-01-10T15:08:37+01:00</lastModified> <mimeType>text/plain</mimeType> <name>2</name> <uri>http://127.0.0.1:9998/storage/containers/quotes/2</uri> </item> <item> <digest>-71240529c42b5b92e3086e624618d19164658616</digest> <lastModified>2007-01-10T15:11:51+01:00</lastModified> <mimeType>text/plain</mimeType> <name>3</name> <uri>http://127.0.0.1:9998/storage/containers/quotes/3</uri> </item> <item> <digest>493388267529403c84628e12141ffe9a013205a4</digest> <lastModified>2007-01-10T15:12:08+01:00</lastModified> <mimeType>text/plain</mimeType> <name>4</name> <uri>http://127.0.0.1:9998/storage/containers/quotes/4</uri> </item> <name>quotes</name> <uri>http://127.0.0.1:9998/storage/containers/quotes</uri> </container>
Search the container for all items containing the word 'king':
curl "http://127.0.0.1:9998/storage/containers/quotes?search=king"
which returns the following XML document containing one item, 3:
<container> <item> <digest>-71240529c42b5b92e3086e624618d19164658616</digest> <lastModified>2007-01-10T15:11:51+01:00</lastModified> <mimeType>text/plain</mimeType> <name>3</name> <uri>http://127.0.0.1:9998/storage/containers/quotes/3</uri> </item> <name>quotes</name> <uri>http://127.0.0.1:9998/storage/containers/quotes</uri> </container>
Get the contents of item 3:
curl http://127.0.0.1:9998/storage/containers/quotes/3
which returns the following:
catch the conscience of the king
Update the contents of item 3:
curl -X PUT -HContent-type:text/plain --data "The play's the thing Wherein I'll catch the conscience of the king" http://127.0.0.1:9998/storage/containers/quotes/3
A new search shows that the content has been updated, because the digest is different and the last modified time is more recent:
<container> <item> <digest>36d586647af7886aadbc21f238cee7740cf319e9</digest> <lastModified>2007-01-10T15:46:46+01:00</lastModified> <mimeType>text/plain</mimeType> <name>3</name> <uri>http://127.0.0.1:9998/storage/containers/quotes/3</uri> </item> <name>quotes</name> <uri>http://127.0.0.1:9998/storage/containers/quotes</uri> </container>
Get the updated contents of item 3:
curl http://127.0.0.1:9998/storage/containers/quotes/3
which returns the following:
The play's the thing Wherein I'll catch the conscience of the king
Delete item 3:
curl -X DELETE http://127.0.0.1:9998/storage/containers/quotes/3
A new search using 'king' returns no items.
Delete container 'quotes':
curl -X DELETE http://127.0.0.1:9998/storage/containers/quotes
The state of the service is now equivalent to that of a newly started storage service.
The getting of item 3 in the previous example supports the HTTP features Last-Modified
and ETag
. The following shows a set of HTTP requests and responses
from the Firefox web browser to the web storage service that highlights the
caching mechanism. (The headers can be viewed using Firefox's LiveHTTPHeaders plugin,
available from the Firefox Tools menu after installation.)
Request, initial query to http://127.0.0.1:9998/storage/containers/quotes/3:
GET /storage/containers/quotes/3 HTTP/1.1 Host: 127.0.0.1:9998 User-Agent: Mozilla/5.0 (X11; U; SunOS i86pc; en-US; rv:1.8.1) Gecko/20061024 Firefox/2.0 Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive
Response
HTTP/1.1 200 OK Last-modified: Wed, 10 Jan 2007 15:12:05 GMT Content-type: text/plain Etag: "-71240529c42b5b92e3086e624618d19164658616" Transfer-encoding: chunked 21 catch the conscience of the king 0
The response includes the Last-Modified
and ETag
header fields in the response.
Getting the same item again:
Request
GET /storage/containers/quotes/3 HTTP/1.1 Host: 127.0.0.1:9998 User-Agent: Mozilla/5.0 (X11; U; SunOS i86pc; en-US; rv:1.8.1) Gecko/20061024 Firefox/2.0 Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive If-Modified-Since: Wed, 10 Jan 2007 15:12:05 GMT If-None-Match: "-71240529c42b5b92e3086e624618d19164658616"
Response
HTTP/1.1 304 Not Modified Content-length: 0 Etag: "-71240529c42b5b92e3086e624618d19164658616"
The request contains the Last-Modified
and ETag
returned in the first response in the If-Modified-Since
and If-None-Match
header fields. The response contains
no content, and a 304 status code is returned because the item has not
been modified (updated).
Getting the updated item:
Request
GET /storage/containers/quotes/3 HTTP/1.1 Host: 127.0.0.1:9998 User-Agent: Mozilla/5.0 (X11; U; SunOS i86pc; en-US; rv:1.8.1) Gecko/20061024 Firefox/2.0 Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive If-Modified-Since: Wed, 10 Jan 2007 15:12:05 GMT If-None-Match: "-71240529c42b5b92e3086e624618d19164658616"
Response
HTTP/1.1 200 OK Last-modified: Wed, 10 Jan 2007 15:14:17 GMT Content-type: text/plain Etag: "36d586647af7886aadbc21f238cee7740cf319e9" Transfer-encoding: chunked 43 The play's the thing Wherein I'll catch the conscience of the king 0
Since item 3 has been updated, the If-Modified-Since
and If-None-Match
of the request do not result in
a 304 response being returned. The updated content is returned
with the latest Last-Modified
and ETag
values.