Closed spring-projects-issues closed 4 years ago
Oliver Drotbohm commented
Would like to attach an implemented version but seems I don't have permission to do so.
Arjen Poutsma commented
After reading through the Caching chapter in HTTP: The Definitive Guide (highly recommended, btw), this seems a bit more complex than I initially thought. If we want to do caching the right way, then we need to adhere to Cache-Control, Pragma, and Expiry headers, etc.
I'm rescheduling this feature for 3.1.
Arjen Poutsma commented
Attaching Oliver's original EtagCachingRestTemplate and the alternative CachingHttpRequestFactory, sent to me via email.
Marc Weinberger commented
Are there any plans to provide an extension point for cache providers like ehcache? In an distributed RESTful service environment a solid caching feature for RestTemplate would be great.
Arjen Poutsma commented
@Marc
, you can certainly use the high-level cache abstraction for that, see #11967.
Marc Weinberger commented
Thanks Arjen,
Arjen Poutsma commented
Postponing till after 3.1.
Michel Zanini commented
This will be good to be included in Android Rest Template also because ETag support is very useful on a mobile environment.
Oliver Drotbohm commented
After a recent team discussion we decided to slightly shift the scope of this ticket. Caching is not the right word for what we're trying to achieve here. The core idea is to use the headers sent by the server in response to an original request in subsequent requests to the very same resource. Thus it's rather using HTTP means to optimize the request (using If-None-Match
, If-Modified-Since
) depending on what the server indicates to understand.
Brian Clozel commented
I've given this some thoughts after our discussion and found several problems with that approach.
So with that approach, we'd like to remain at the request/response level and let the framework generate conditional requests for us. Something (very imperfect) like this:
String requestUrl = "http://example.org/users/12"
ResponseEntity<User> cachedResponse = cache.get(requestUrl, User.class);
if(cachedResponse == null) {
ResponseEntity<User> response = restTemplate.getForEntity(requestUrl, User.class);
cache.put(requestUrl, response);
}
else {
ConditionalRequest<User> cRequest = cachedResponse.conditional(restTemplate);
User user;
if(cRequest.checkNotModified()) { // issue a conditional GET request and returns true if 304
user = cRequest.getCachedResponse().getBody();
}
else {
user = cRequest.getResponse().getBody();
cache.put("http://example.org/users/12", cRequest.getResponse());
}
}
This API can be improved in many ways, but I think that leaving the abstraction at that level means we'd need to:
This approach generates conditional requests (with proper Etag
or If-
headers), but leave to the user the following problems:
As soon as we're trying to tackle one of those issues, we're beginning to implement a client http cache.
Many frameworks/libraries went down that path with more or less complete or elegant implementations. And I'm wondering if there would be interest in this for Spring Framework given that:
@Cacheable
annotations for their own use case (like this oneJakub Jirutka implemented a RequestInterceptor for this - see his project. Some parts can be improved, like conditional requests support and cache keys generation (currently the cache key is the URL itself and does not take into account HTTP headers such as Vary, or encoding...). But it's still in a good shape IMO.
I've sketched something based on Jakub's work and I'm trying to find ways to come up with clean interfaces that would allow custom strategies for caching, conditional requests, etc. But I'm still struggling with the 3 points listed above.
Actually Jakub Jirutka, what do you think about those points? Can you share your experience and tell us why you created this project in the first place and how it's being used?
In the meantime, RestTemplate
has been put in maintenance mode, so we don't intend to invest more there.
Oliver Drotbohm opened SPR-5821 and commented
The main goal is to create a
CachingClientHttpRequestInterceptor
which provides the following:org.springframework.cache.Cache
ConcurrentCacheMap
This could be used like this:
Affects: 3.0 M3
Attachments:
Issue Links:
12152 Introduce interceptors for RestTemplate ("depends on")
16413 Server-side HTTP caching improvements
11967 Provide high-level cache API in Spring container
10 votes, 15 watchers