I am using spring boot, and it's very easy to integrate spring cache with other cache component.
By caching data, we can use @Cachable
annotation, but still we need configure and add cacheName to the cacheManager
, without this step, we will get an exception while accessing the method:
java.lang.IllegalArgumentException: Cannot find cache named 'xxxx' for Builder
My question is, is that able to disable the cache instead of raising the error if we not configure the cacheName
? I raised this because spring cache provide a configuration spring.cache.cacheNames
in CacheProperties
.
Not sure if the condition
attribute in @Cachable
works for this.
Any idea is appreciate!! Thanks in advance!
It really depends on your "caching provider" and the implementation of the CacheManager interface, in particular. Since Spring's Cache Abstraction is just that, an "abstraction" it allows you to plugin different providers and backend data stores to support the caches required by your application (i.e. as determined by Spring's caching annotations, or alternatively, the JSR-107-JCache annotations; see here).
For instance, if you were to use the Spring Framework's provided ConcurrentMapCacheManager
implementation (not recommended for production except for really simple UCs), then if you choose to not declare your caches at configuration/initialization time (using the default, no-arg constructor) then the "Caches
" are lazily created. However, if you do declare your "Caches
" at configuration/initialization time (using the constructor accepting cache name arguments), then if your application uses a cache (e.g. @Cacheable("NonExistingCache")
) not explicitly declared, then Exception would be thrown because the getCache(name:String):Cache
method would return null
and the CacheInterceptor
initialization logic would throw an IllegalArgumentException
for no Cache
available for the caching operation (follow from the CacheIntercepter
down, here, here, here, here and then here).
There is no way to disable this initialization check (i.e. throw Exception) for non-existing caches, currently. The best you can do is, like the ConcurrentMapCacheManager
implementation, lazily create Caches
. However, this heavily depends on your caching provider implementation. Obviously, some cache providers are more sophisticated than others and creating a Cache
on the fly (i.e. lazily) is perhaps more expensive and costly, so is not supported by the caching provider, or not recommended.
Still, you could work around this limitation by wrapping any CacheManager
implementation (of your choice), and delegate to the underlying implementation for "existing" Caches
and "safely" handle "non-existing" Caches
by treating it as a Cache miss simply by providing some simple wrapper implementations of the core Spring CacheManager
and Cache
interfaces.
Here is an example integration test class that demonstrates your current problem. Note the test/assertions for non-existing Caches
.
Then, here is an example integration test class that demonstrates how to effectively disable caching for non-existing Caches
(not provided by the caching provider). Once again, note the test/assertions for safely accessing non-existing Caches
.
This is made possible by the wrapper delegate for CacheManager
(which wraps and delegates to an existing caching provider, which in this case is just the ConcurrentMapCacheManager
again (see here), but would work for any caching provider supported by Spring Cache Abstraction) along with the NoOpNamedCache
implementation of the Spring Cache
interface. This no-op Cache
instance could be a Singleton and reused for all non-existing Caches
if you did not care about the name. But, it would give you a degree of visibility into which "named" Caches
are not configured with an actual Cache
since this most likely will have an impact on your services (i.e. service methods without caching enabled because the "named" cache does not exist).
Anyway, this may not be one you exactly want, and I would even caution you to take special care if you pushed this to production since (I'd argue) it really ought to fail fast for missing Caches
, but this does achieve what you want.
Clearly, it is configurable and you could make it conditional based on cache name or other criteria, in that, if your really don't care or don't want caching on certain service methods in certain contexts, then it is up to you and this approach is flexible and completely give you that choice, if needed.
Hope this gives you some ideas.