0

Spring provides a caching abstraction package spring-boot-starter-cache which basically provides method level annotations to cache data with @Cacheable, @Cacheput and other annotations. I feel there are limitations to this: Caching a collection of POJO against a property (for example: Person.getId() as the key from List<Person> as a return type). And the other limitation is searching. How do I query and search data in the cache provider?

I'm assuming I'd need to use CacheManager, CacheResolver and KeyGenerator along with RedisCacheManager to cache a collection of objects and also to lookup caches. So far the documentation hasn't been helpful at all. And most of the articles don't even touch up on these items. Can someone please explain how to use these or direct me towards some documentation.

user2354302
  • 1,833
  • 5
  • 23
  • 35

1 Answers1

0

The core Spring Framework's Cache Abstraction is much more than a collection of annotations for caching, and specifically, Look-Aside, or Cache-Aside, caching as it's commonly referred. The Cache-Aside pattern is the pattern of caching on which Spring's Cache Abstraction is based.

Spring's Cache Abstraction is a general purpose caching framework (and facade) with an API allowing users to plugin different "caching provider" implementations (e.g. Redis, or Apache Geode using the following bits). For all intents and purposes, it is a proper Service Provider Interface (SPI) with implementations adhering to the interfaces defined by the SPI.

The 2 main interfaces in Spring's Cache Abstraction include the CacheManager and Cache.

These are the primary interfaces and APIs that must be implemented when adding support for a new caching provider that can be used to apply caching to Spring managed application services (components, or beans declared in the Spring container). Under-the-hood, Spring's Cache Abstraction is implemented with Spring AOP.

You can either use the APIs from the CacheManager and Cache interfaces directly in your Spring managed application components (beans), or you can more commonly use the caching annotations (e.g. @Cacheable), which are less invasive, and easier to disable, if applicable (e.g. simply remove the @EnableCaching annotation, or in Spring Boot's case, set the spring.cache.type property to none; see here).

The Cache interface (Javadoc) only provides basic and essential data access operations (e.g. querying) that are relevant for caching. It does not provide "low-level" data access operations that are possibly provided by the underlying caching provider (e.g. Redis).

This is primarily due to the fact that not all caching providers are equal. Some caching providers far exceed others in terms of functionality and capabilities, functionality and capabilities that fall outside of the "general concern of caching". In fact, things like querying or distributed compute, replication, eviction/expiration policies (hence this), consistency guarantees, etc, all vary from 1 caching provider to the next. The caching provider is often chosen based on your application use case and requirements.

However, Spring does not prevent you from getting access to the low-level functionality if you need it, even from the Cache Abstraction.

For instance, the Cache.getNativeCache() method returns the underlying implementation of the Cache interface for your caching provider implementation. In Spring for Apache Geode, that is a cache Region. In Spring for Redis, that is a HASH, I believe (?).

Regarding the "limitations", as you say, for example, "Caching a collection of POJO...", this is not entirely true.

Indeed Spring's Cache Abstraction is intentionally and deliberately designed for general purpose caching, which involves "lookup", not querying or handling complex object hierarchies, or even arrays/collections of objects.

While Spring does not handle these type of concerns out of the box, it does not mean they are not possible. Spring is designed to the Open/Closed principle, being "closed" for modification, but "open" to extension.

It is possible to extend Spring's Cache Abstraction to, for example, cache the individual elements in an array or Collection (e.g. List) returned by a @Cacheable service method.

See my answer (2nd, or bottom one) to this StackOverflow question. Specifically, see this SO post.

The thing is, while Spring may not have an immediate answer out-of-the-box, there is usually always an answer, but might involve a bit of work (code).

If you understand the underlying design principles, then you can begin to plugin and customize all aspects of the caching behavior as needed, such as how Caches are resolved (from a provider), key generation, or conditional caching. Spring provides "default" behavior (for example), but nearly every aspect can be customized in some way.

Still, somethings will be very provider specific (like "Expiration") and so you are not completely void from having to understand your underlying provider. No technology can completely shield from having to understand the underlying infrastructure, for example not even JPA for databases, especially when you need to create indexes.

Hope this makes sense.

John Blum
  • 7,381
  • 1
  • 20
  • 30