Hi Mark,
> We think that support for preconditions is important and the
> HttpRequestContext contains a few evaluatePreconditions methods that
> offer such support. Jerome raised the question of whether we could
> use annotations instead of these methods using something like the
> following:
>
> @UriTemplate("someuri")
> public class SomeResource {
>
> ...
>
> @LastModified
> Date getLastModified() {
> ...
> }
>
> @Tag
> EntityTag getEntityTag() {
> ...
> }
> }
>
> We did consider this approach for while but decided against it for
> the following reasons:
>
> - A strong entity tag can depend on the media type of the returned
> representation (a brute force approach is to hash the bytes of the
> returned representation). If a class has two methods that return
> different media types then you either need multiple variants of the
> above @Tag method or some way of indicating which method is going to
> be called and what the returned mediaType will be.
Well this could be solved by an *optional* annotation parameter:
@Tag(mediaType="application/foo")
String getEntityTag1() {
...
}
@Tag(mediaType="application/bar")
String getEntityTag2() {
...
}
Also, I'm not sure there is a strong need to have a custom EntityTag class
in our case. I used a String above and it should be enough. IMHO, the
definition of entity tag will be something rather rare at the JSR level. But
it should definitely be possible.
> - Often you'll need to obtain the same data to compute an entity tag
> and last modified value as you'll need to service the request
> (should
> the preconditions be met). You don't want to have to fetch the same
> data multiple times so you'd want some way to cache it between the
> getEntityTag/getLastModified/http method. However its not
> clear which
> of the methods will actually be called since the preconditions might
> not be met so then you end up with data lifecycle issues. We
> considered thread-local approaches to caching data but that has
> implications on the container for thread management.
Hmm, I don't understand why we should take this into account. Isn't this an
internal issue for the POJOs that we are annotating? They could also
implement late data loading mechanisms if necessary. The first method
invoked (getLastMofidied/getEntityTag/...) would check whether the internal
data has been already initialized.
> The current design avoids these issues. The developer writes their
> http methods as normal and just has to add a call to one of the
> evaluatePreconditions methods where its appropriate. If
> evaluatePreconditions returns null then the preconditions were met
> and the method continues as normal. A non-null return value
> indicates
> that the preconditions weren't met and supplies an appropriate
> Response that the method can use.
>
> On the downside this approach does dictate that the method have a
> Response return type which is unfortunate. We considered use of an
> exception but rejected it since this isn't really an exceptional
> circumstance.
I'm not convinced that such a mechanism is necessary at all. Maybe I missed
an important use case, but in the Restlet API, the application only
describes the metadata of the representations (variants) and the engine
internally check if the preconditions are met, like if the last modification
date has changed since the last retrieval to automatically return the
expected HTTP 304 status.
Best regards,
Jerome