Skip to content

Extend caching for collections #23221

Closed
Closed
@neiser

Description

@neiser

I'd like to use the Spring Caching abstraction in a way that I can also ask for a bunch of items via a list of provided IDs, and then put the result into the cache, as if I had asked for each item one by one.

As an example, consider the following snippet:

    @Cacheable("myCache")
    public String findById(String id) {
        // ... access DB backend and return item
    }

    @CollectionCacheable("myCache") // let's suppose this exists and does the magic :D
    public Map<String, String> findByIds(Collection<String> ids) {
        // ... access DB backend, return map of id to item
    }

Then usage would be:

// suppose the following call has happened before the examples below
findById("key1")

// example1: uses "key1" from cache, never calls findByIds
findByIds(Arrays.asList("key1")) 

// example2: calls findByIds(["key2"]) and uses value for "key1" from cache,
//           puts value for "key2" into cache
findByIds(Arrays.asList("key1", "key2"))

// example3: calls findByIds(["key3", "key4"]) as there's nothing in the cache
//           puts value for "key3" and for "key4" separately into cache
findByIds(Arrays.asList("key3", "key4")) 

I've implemented this functionality in a proof-of-concept Spring Boot application here: https://github.com/neiser/spring-collection-cacheable The main implementation can be found in CollectionCacheInterceptor#handleCollectionCacheable

The PoC lacks the following:

  1. Modifying the BeanFactoryCacheOperationSourceAdvisor to account for my extra CollectionCacheableCacheAnnotationParser and CollectionCacheInterceptor only worked via a BeanFactoryPostProcessor
  2. No consisderation of sync (might be possible, but is harder to implement)
  3. The CacheAspectSupport (which I extended in CollectionCacheInterceptor) has only some methods protected, which required me to copy some of the code from CacheAspectSupport in CollectionCacheInterceptor

Still, the tests in MyRepositoryIntTest show that the PoC works 👍

My questions to you folks are:

  1. Do you have a better idea how to "modify" the BeanFactoryCacheOperationSourceAdvisor in order to support my custom @CollectionCacheable?
  2. Do you think the annotation @CollectionCacheable could be officially integrated in Spring's caching layer (of course with some more polishing)? I've seen some discussions on Stackoverflow and in particular in Insert all elements of a returned list into a Cache [SPR-15213] #19777 but they lack the "partial" invocation feature as in example 2 above (they proposes to use the Cache/CacheManager interfaces to achieve the desired functionality).
  3. If you don't want to integrate something like @CollectionCacheable: The CacheAspectSupport class is hard to extend for my PoC. The same holds for CollectionCacheableCacheAnnotationParser, which is extending SpringCacheAnnotationParser. Would you mind to make this easier for my use case?

I'm happy to contribute a PR once I know what your opinion on this feature is. I can also polish the PoC further following your recommendations. I appreciate any feedback!

Metadata

Metadata

Assignees

No one assigned

    Labels

    in: coreIssues in core modules (aop, beans, core, context, expression)status: declinedA suggestion or change that we don't feel we should currently apply

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions