RESTEasy Server-Side Caching API Ideas

Version 3

    A Server-Side Caching Proposal for RESTEasy

    This document is a proposal/ideas for caching responses in the RESTEasy framework. This document is a work in progress and no code currently exists to support this functionality. This document on details ideas on how a server-side caching framework and will take into consideration things like ETags or Cache-Control directives. This document also does not detail any ideas for caching in the RESTEasy client API.

    Goals

    A non-goal of a service-side cache is to make such a cache a replacement for tools like Squid or a CDN. In fact, such a cache would be complimentary to such tools. A server-side caching API for RESTEasy must make it easier for the developer to specify Cache-Control headers and ETag values in order to make integration with we caches easier. Eventually, a web cache will eventually have to revalidate the entity with RESTEasy and this is where the server-side cache comes into the picture.

     

    In situations where representations are dynamically generated (i.e. JPA entities annotated with JAXB annotations, etc.), the representation must be rendered before the response is complete. This usually means a hit to a database and an invocation on a MessageBodyWriter. If the entity has not changed within max-age value of the Cache-Control header, then there's no reason to have RESTEasy re-read the data from the database and re-render the response representation and header values.

     

    Additionally, this server-side cache should also be plug into the RESTEasy life cycle. That is provide read-through caching on GET requests for a given URI. On PUT, POST, and DELETE, the cache entry should be removed. This will require that the next GET request populates the cache entry, but ensures that the data is not stale.

     

    General Features:
    • Cache the response representation and headers of GET requests (duh!)
    • Provide an easier means of populating the Cache-Control and ETage headers
    • The cache should store the representation and not necessarily the raw underlying data. That is, it would cache the rendered JSON response rather than the original File or POJO. This would the overhead of have having to invoke the MessageBodyWriter.
    • A cache key could be URI + media type + created + modified (is more info needed?)
    • Potentially implement as a read-through cache for GET requests. POST, PUT, or DELETE operations purge the cache for the URI. A resource class could be annotated with a @ServerCache annotation to indicate that the responses from this resource should cached by RESTEasy.
    • Implement a pluggable SPI to plugin different cache providers as different applications will have different caching requirements
    • Implement an injectable CacheContent that allows access to the cache. The application would then have the ability to interact with the cache directly and make determinations of when items are added and removed from the cache
    • Implement a CacheStatistics class that can provide statistics on the cache (similar to Hibernate)
    • Implement some JMX management features for the cache
    Configuration
    • The caching directives should be configurable on a per-URI basis and/or media-type. For example, cache all XML representations but not Image representations
    • A user should be able to declare the desired cache provider
    • Cache regions and expiry rules should be delegated to the underlying cache provider.
    Issues
    • Since the cache will be caching the representation of the response body, memory requirements could be steep. Should the cached response be compressed in the cache?
    • There's a thorny issue with URIs that return a collection of elements. With single entity URIs such as /orders/12345, caching is pretty straight forward. However, a URI such as /order could return 100's or 1000's of elements depending how an application is designed. The issue is that a single request could hit memory limits very quickly. It could be that we don't allow caching for return types if Collection or array, but that gets thorny. It maybe that server-side caching is not automagic for collection types?
    • The caching feature should implemented via some type of RESTEasy Interceptors