dev@jersey.java.net

Re: How to make caching work?

From: Marc Hadley <Marc.Hadley_at_Sun.COM>
Date: Wed, 26 Sep 2007 16:40:02 -0400

On Sep 26, 2007, at 4:15 PM, Peter Liu wrote:
>
> Thanks for the pointers. I am starting to understand how caching
> works.
> Here is my understanding of how we should generate code to support
> caching in the resource classes we generate from entity classes.
>
> First, we need to generate a memory store similar to the one in
> the Storage sample. This memory store will keep track of the
> digest and lastModified date of an resource.
>
PMFJI. If you want to avoid hitting the database and the resource
class is the only means of updating the data then an in-memory cache
makes sense. However you can run into problems if the database can be
updated by other means (e.g. some background process or other
external access) since the cache and database can then get out of
sync and you'll run into problems that preconditions were meant to
solve. In general you should check the etag and/or last modified
against the database within the same transaction as the update if you
want complete consistency.

> Second, we need to change the return type for all the http methods
> to Response. We will then use the precondition evaluator to
> determine what response to send back. We will also us the CacheControl
> to specify the caching policy for the resource.
>
Right.

> Here are some questions:
>
> 1. Regarding etag (digest) and lastModified data, do we need both?
> We will lose
> all the lastModified dates after each restart but we can always
> recompute
> the etags from the resource itself. So etag seems to be a more
> reliable method.

Right. Etag is preferable to last modified since the latter only has
a granularity of 1 second which might not be sufficient in a rapidly
changing dataset.

Also note that the etag value doesn't have to be a digest of the
representation, it can be anything that generates a unique value for
a particular representation of the resource. E.g. the database might
include a version or update timestamp field for each record and you
could concatenate either of those with the representation format to
make the etag and save a costly digest calculation.

If the tooling allowed a developer to specify that a particular field
(or combination of fields) was suitable for etag generation that
would be quite powerful. The tooling could then default to the more
expensive digest calculation when the developer doesn't specify an
alternative.

> 2. If I call Response.Builder.representation(jaxbInstance) without
> the mime type,
> will it automatically serialize the jaxb instance into xml or json
> depending on the
> mime type in the request header? The reason I ask this is because
> we currently
> specify a list of mime types in the ConsumeMime and ProduceMime
> annotations.

Yes, I believe that is how it should work.

Marc.

> Paul Sandoz wrote:
>> Paul Sandoz wrote:
>>>> Paul, you mentioned about etags and preconditions in jsr311,
>>>> could you elaborate on this
>>>
>>> I will do better and defer to Mark Nottingham's caching tutorial
>>> [2].
>>>
>>> There are also a couple of other related things like using 100
>>> (Continue) for POST'ing or PUT'ing large files (unfortunately
>>> this is not possible using Servlet) and using ETags/Last-Modified
>>> with PUT to avoid the lost update problem.
>>>
>>>
>>>> and show how developers can program
>>>> the caching behavior in the resource classes?
>>>>
>>>
>>> I will send an email tomorrow how to support caching and
>>> preconditions.
>>>
>>
>> A bit late....
>>
>>
>> javax.ws.rs.core.CacheControl [1] can be created and set uding
>> Response.Builder.cacheControl [2].
>>
>> Preconditions can be evaluated by using an injected
>> PreconditionEvaluator [3].
>>
>>
>> First you need to obtain the etag and/or last-modified date from
>> somwhere. Call PreconditionEvaluator.evaluate with etag and/or
>> date. If the call returns a non-null Response then preconditions
>> have been met and you can return the response. Otherwise a
>> response needs to be returned and you should set the etag and/or
>> last-modified on a response and include any CacheControl instance
>> as required.
>>
>> We can probably improve this behaviour by
>> PreconditionEvaluator.evaluate returning an instance of
>> Response.Builder so that this can be reused if preconditions are
>> not met.
>>
>>
>> Note that this will also work for 409 (Conflict) responses, so you
>> can use when PUTing content as well as for GETing content.
>>
>> Paul.
>>
>> [1] https://jsr311.dev.java.net/nonav/javadoc/javax/ws/rs/core/
>> CacheControl.html
>> [2] https://jsr311.dev.java.net/nonav/javadoc/javax/ws/rs/core/
>> Response.Builder.html#cacheControl(javax.ws.rs.core.CacheControl)
>> [3] https://jsr311.dev.java.net/nonav/javadoc/javax/ws/rs/core/
>> PreconditionEvaluator.html
>>
>>> Paul.
>>>
>>> [1] http://roy.gbiv.com/talks/200709_fielding_rest.pdf
>>> [2] http://www.mnot.net/cache_docs/
>>>
>>>> Thanks.
>>>>
>>>> Peter
>>>>
>>>> -------------------------------------------------------------------
>>>> --
>>>> To unsubscribe, e-mail: dev-unsubscribe_at_jersey.dev.java.net
>>>> For additional commands, e-mail: dev-help_at_jersey.dev.java.net
>>>>
>>>
>>> --------------------------------------------------------------------
>>> -
>>> To unsubscribe, e-mail: dev-unsubscribe_at_jersey.dev.java.net
>>> For additional commands, e-mail: dev-help_at_jersey.dev.java.net
>>>
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: dev-help_at_jersey.dev.java.net
>

---
Marc Hadley <marc.hadley at sun.com>
CTO Office, Sun Microsystems.