Spring Cache to Disable Cache by cacheName configuration - spring

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.

Related

Create cache from object type through annotations

So,
I'm trying to convert our existing caching (ehcache) to ignite cache, and migrating to spring annotations. I'm running into some difficulty making the annotations work the same as our existing caches though - our existing caches are created automagically whenever we cache something of a new class, and the new cache has the same name as the object's class.
All the current cache logic (along with most of the normal CRUD operation logic) is in an abstract class that's extended for all our persistent objects. In researching the spring annotations, though, it seems like I need to define the cache name on the method - which obviously doesn't work for the abstract class, unless I want all our objects to be in the same cache (possible but definitely not ideal). Ideally I'd specify the cache name as "#this.class.toString", but SPEL isn't allowed in the cache name, like it is in the key.
It seems like the only way to resolve the cache dynamically is by creating your own cache resolver, but for some reason IgniteCache doesn't extend springframework Cache, but javax Cache, and the cache resolver has to return the former. So I'm not even clear how Ignite cache works with spring annotations at all?
This seems like a pretty straightforward use case to me, so it seems weird that spring annotations force me to provide an explicit name on the method, when I'd assume most applications of any significant size are abstracting their persistence methods, and I feel like I must have missed some crucial documentation, but I sure can't find it. Is there a way to specify the name of the cache on the concrete implementation, but keep the caching annotation on the abstract methods?
Thanks!
Your question is quite dense and it's not very clear what you're trying to do. What is "your existing caching" for a start? You need some way to flag the places where you actually cache things I guess. I assume you already understood you need to put a cache annotation there.
As for automatically creating the cache, I wouldn't switch to a different caching system and trying to implement that. Try to migrate first to the cache annotations with your existing cache infrastructure and then migrate to ignite.
Let's pretend you do both still. You are right CacheResolver is the way to go and it can adapt to either a regular org.springframework.cache.Cache or a javax.cache.Cache. Once you have a setup that works, I'd do the following:
In your CacheResolver implementation, inject the cache manager that has been configured
Based on the method call, figure out the cache name to use (get the return type of the method, extract the FQN)
Check if the cache manager has such cache. If it does, return that. If it doesn't create a new cache and add it and then return that
If you're using JCacheCacheManager, you can invoke addCache to create a new cache and then wrap the result in JCacheCache to comply with the signature of CacheResolver.
Last note: automatically creating the cache based on the FQN seems a bit fragile to me, especially if you have sub-classes. You need a bit of control on the caches you create and the settings you apply to them (expiration, size, etc).

SW-Architecture - Caching between service- and persistence layer

I'm developing a file system which encapsulates access to an Amazon S3 bucket using the fuse library and jnr-fuse (https://github.com/SerCeMan/jnr-fuse) as a java binding.
I have a first version working and am currently doing some code-cleanup and refactoring work, trying to get everything into a proper multi-layered architecture.
So far I have roughly the following:
Frontend: This is the actual implementation of the FuseFileSystem interface from jnr-fuse. It has some dependencies to jnr (native) types and the methods are the java equivalents of fuse's c-functions.
Service Layer: One interface that has "non-native-dependent" versions of all the file-system methods from the frontend layer, but no dependencies to jnr or fuse whatsoever. The idea is that this could be used in other contexts as well (e.g. as the core component of an implementation of the java.nio.FileSystem-API for S3 or any other scenario where someone would need an API making S3 accessible in a "filesystem-ish" fashion but not want to do that via fuse and therefore not want all the jnr dependencies)
Where I'm currently struggling is the persistence layer: As all communication with S3 is actually done via http, I'm doing some fair amount of caching to reduce traffic and increase performance.
The question is where that caching would best fit..
Obviously the actual DAOs should not be polluted with any kind of caching/locking logic - they should only handle the actual access to the data (i.e. doing the http calls against S3).
On the other hand, also the service layer shouldn't really be concerned with caching (in case the persistence layer and with it the caching requirements change), so I was thinking of doing one of the following:
Use a "doubled" persistence layer: Each DAO is implemented twice: One version that holds a cache and serves data out of it's cache. If an object is not in the cache, we delegate to the second DAO which actually fetches the object (which is then added to the cache)
Introduce a separate "cache" layer with slightly different interfaces than the actual persistence layer that handles all caching requirements and delegates to the persistence layer as necessary.
Version 1 would be the cleaner one from the service-layer point of view - there wouldn't be any difference between using a cache and not using it because all calls to the persistence layer would go against the same interface. On the other hand it would also transfer all the logic concerning the state or "lifecycle" of a file (open -> read/write -> close) to the persistence layer.
Version 2 would manage the lifecycle of the file inside the "cache" layer, which I think would make the whole thing easier to understand for anyone new to the code. On the other hand it also assumes that there will always be a cache layer (which is probably true).
Are there any other pros and cons to the above approaches from a design point of view or is there any pattern out there which addresses this kind of problem?
Right now I'd rather go with option 2 but it'd be really interesting to hear some opinions.
Why are you opposed to caching in the DAO? This has always been the perfect place for me to cache. It is a data access concern, and thus goes into the data access layer. A couple of times I've used various AOP implementations for convenience, but 90% of the time, i'm implementing caching logic inside the DAO.
The cache itself does not live in the DAO, it is usually it's own interface, so I can swap between implementations (in-memory, on-disk, etc).
I have also had some luck when using Apache HTTP client's own built-in caching. It allows you to respect HTTP cache semantics, or override it with custom logic.

Advantage of using ehcahce over a static HashMap

I have always used the java singleton class for my basic caching needs.
Now the project is using ehcache and without looking deeply into source code, I am not able to figure out what was wrong with the singleton pattern.
i.e What are the benefits of using the ehcahce framework except that the caching can be done by using xml configuration and annotation without writing the boilerplate code (i.e a static HashMap)
It depends on what you need from your caching mechanism. Ehcache provides a lot of cool features, which require a lot of well designed code to do it manually:
LRU, LFU and FIFO cache eviction policies
Flexible configuration
Persistence
Replication
many more ...
I would recommend you go through them at http://ehcache.org/about/features and decide do you really need something in your project.
The most important one:
The ability to overflow to disk - this is something you don't have in normal HashMap and writing something like that is far from trivial. EhCache can function as simple to configure key-value database.
Even if you don't use overflow to disk, there's a large boilerplate to write with your own implementation. If loading the whole database would be possible, that using memory database with persistence on write and restoring on startup would be the solution. But memory is limited and you have to remove the elements from memory. But which one, based on what? Also, you must assert cache elements are not too old. Older elements should be replaced. If you need to remove elements from cache, you should start from the outdated ones. But should you do it when user requests something? It will slow down the request. Or start your own thread?
With EhCache you have the library in which all those issues are addressed and tested.
Also there is a clustered closed source version of ehcache, which allows you to have a distributed cache. That might be one reason you might want to consider using ehcache.

ibatis / mybatis caching within a restful webservice

I am using mybatis within a Jax-RS (Jersey) restful web app. So automatically, I dont have a session or state management.
Question is how can I use the caching features of mybatis ?
Caching in MyBatis is very straight forward. Per the documentation (pg 42 of the user manual http://mybatis.googlecode.com/svn/trunk/doc/en/MyBatis-3-User-Guide.pdf)
By default, there is no caching enabled, except for local session caching, which improves performance and is required to resolve circular dependencies. To enable a second level of caching, you simply need to add one line to your SQL Mapping file:
MyBatis 3 - User Guide
6 June 2011 43
<cache/>
Literally that’s it.
The common pitfalls I had while doing this:
On the mapper you add the cache element to; if you have dependent entities, make sure to explicitly flush the cache when required. Even though flushing is already done for you on insert, update, delete for the elements in the mappings you have set the cache element, sometimes you have to flush a cache due to updates/deletes/etc defined in different xml mappings.
Basically, when you're thinking about your caching, you should ask yourself, "When this entity is changed, do I want it to flush a cache for an entity in a different mapping?" If the answer is yes, use cache-ref element as opposed to just cache.
Ex from page 45 of the doc:
<cache-ref namespace=”com.someone.application.data.SomeMapper”/>

Is there a provider agnostic way of getting up to date cache statistics in Spring framework?

Spring provides a useful feature of Cache Abstraction
But what I could not find is a provider agnostic way to get live cache statistics. Essentially I just want to show a list of all the cache names and their corresponding keys with the count of hits, misses, and sizes (in kb) either on a web page or via JMX. I know Ehcache does provide this feature and if I use ehcache API inside the code I can get it (have already used it in the past). But I believe using Ehcache API inside the code takes away the whole notion of the Spring framework's cache abstraction.
The only common, provider-agnostic thing you have is CacheManager interface, which provides the following method:
Collection<String> getCacheNames()
It returns a collection of the caches known by the cache manager.

Resources