I'm trying to somehow 'debug' my application that use the spring boot cache annotations and for that I would like to know how to find the class that actually implements the interface Cacheable, CacheConfig, etc.
My idea is to confirm that the cache is being populated, emptied etc.
Thanks a lot for your help,
#Cacheable is used to demarcate methods that are cacheable - that is, methods for whom the result is stored into the cache so on subsequent invocations (with the same arguments), the value in the cache is returned without having to actually execute the method. In its simplest form, the annotation declaration requires the name of the cache associated with the annotated method:
#Cacheable("books")
public Book findBook(ISBN isbn) {...}
In the snippet above, the method findBook is associated with the cache named books. Each time the method is called, the cache is checked to see whether the invocation has been already executed and does not have to be repeated. While in most cases, only one cache is declared, the annotation allows multiple names to be specified so that more than one cache are being used. In this case, each of the caches will be checked before executing the method - if at least one cache is hit, then the associated value will be returned.
For more information read the following;
https://docs.spring.io/spring/docs/current/spring-framework-reference/integration.html#cache
Spring used ConcurrentHashMap as the default cache implementation.
public class ConcurrentMapCache extends AbstractValueAdaptingCache
If, on the other hand, you need different cache, then Spring also comes with a built in ehCache wrapper. The good news is that swapping between Spring's caching implementations is easy. In theory it’s all a matter of configuration.
Related
Our applications using Spring Cache and need to know if response was returned from cache OR it was actually calculated. We are looking to add a flag in result HashMap that will indicate it. However whatever is returned by method, it is cached so not sure if we can do it in calculate method implementation.
Is there any way to know if calculate method was executed OR return value coming from cache when calling calculate method?
Code we are using for calculate method -
#Cacheable(
cacheNames = "request",
key = "#cacheMapKey",
unless = "#result['ErrorMessage'] != null")
public Map<String, Object> calculate(Map<String, Object> cacheMapKey, Map<String, Object> message) {
//method implementation
return result;
}
With a little extra work, it is rather simple to add a bit of state to your #Cacheable component service methods.
I use this technique when I am answering SO questions like this to show that the value came from the cache vs. the service method by actually computing the value. For example.
You will notice this #Cacheable, #Service class extends an abstract base class (CacheableService) to help manage the "cacheable" state. That way, multiple #Cacheable, #Service classes can utilize this functionality if need be.
The CacheableService class contains methods to query the state of the cache operation, like isCacheMiss() and isCacheHit(). Inside the #Cacheable methods, when invoked due to a "cache miss", is where you would set this bit, by calling setCacheMiss(). Again, the setCacheMiss() method is called like so, inside your #Cacheable service method.
However, a few words of caution!
First, while the abstract CacheableService class manages the state of the cacheMiss bit with a Thread-safe class (i.e. AtomicBoolean), the CacheableService class itself is not Thread-safe when used in a highly concurrent environment when you have multiple #Cacheable service methods setting the cacheMiss bit.
That is, if you have a component class with multiple #Cacheable service methods all setting the cacheMiss bit using setCacheMiss() in a multi-Threaded environment (which is especially true in a Web application) then it is possible to read stale state of cacheMiss when querying the bit. Meaning, the cacheMiss bit could be true or false depending on the state of the cache, the operation called and the interleaving of Threads. Therefore, more work is needed in this case, so be careful if you are relying on the state of the cacheMiss bit for critical decisions.
Second, this approach, using an abstract CacheableService class, does not work for Spring Data (CRUD) Repositories based on an interface. As others have mentioned in the comments, you could encapsulate this caching logic in an AOP Advice and intercept the appropriate calls, in this case. Personally, I prefer that caching, security, transactions, etc, all be managed in the Service layer of the application rather than the Data Access layer.
Finally, there are undoubtedly other limitations you might run into, as the example code I have provided above was never meant for production, only demonstration purposes. I leave it to you as an exercise to figure out how to mold these bits for your needs.
I am wondering if there is a built in way to know wheather or not an object is returned frome SpringBoot cache. I am using SpringBoot 2.2.2 and Caffeine 2.8.0. I am creating a Caffeine bean as follows:
#Bean
public Caffeine caffeineConfig() {
return Caffeine.newBuilder().maximumSize(1000).expireAfterWrite(4, TimeUnit.HOURS);
}
I noticed that the builder has a removalListener method. What I need is something like objectServedFromCacheListener. In other words, I would like to get notified when an object is served or returned from the cache. Given that such a method does not exist, how can I know when an object is returned from the cache? I can use service method invocation time, expecting that a real invocation would take over a few seconds, and if the method returns within less than a second it would mean that the object was returned from a cache. But this seems awkward.
I have an internal profiling mechanism, based on which I can determine if the service method was called. But I was expecting there to be a built in way. Is there?
When adding #Cacheable annotation on a method performing a simple Java code, on application execution, breakpoint inside the method is triggered. Does this mean that the result was not cached?
Configuration used:
spring.cache.type=redis
spring.redis.host=localhost
spring.redis.port=[port]
spring.cache.redis.time-to-live=[some value]
Note that the #Cacheable is working fine in the same project when put before a database method
Yes, this means that the result was not cached.
In this case, if any of the caches contains the required result, the result is returned and the method is not invoked.
Source
In order to make use of a cache, the method must be invoked with the same parameters again. However, there are limitations, as this answer points out.
To make it work, we need to call the method annotated with #Cacheable from a different Java class. Otherwise it doesnt work.
I understand that for caching annotations like #Cacheable, #CachePut to work, they should be used in Spring Component class. But, I have a class that is not a Spring component or service, but I need to implement caching on one of the methods in that class.
#CachePut(cacheNames = {"NAME_OF_CACHE"})
public Object addToCache(String cacheKey) {
// Some computation here
return response;
}
I have a roadblock for converting this class to a component. Objects of this class will be initialized during runtime. Is there any way to implement this functionality?
You can manage the caching manually:
1- when you enter the function, check if the cache has the record you want and return it if yes.
2- in the end of the function insert to the cache before you return the result.
Note: you need to have an instance of your cache inside this class which is doable but not preferable.
On the other hand, if you have a problem in converting it to component because it needs to be instantiated in the runtime. Spring provides this capability, you just need to check the scope option.
You can choose the prototype scope for your purpose.
Trying to collect and understand the main points of #Transactional annotation and crossed one point. So, the main things that we need to keep in mind when using Transactional annotation are:
Transactional annotation can be applied only to public methods [according to Does Spring #Transactional attribute work on a private method?
Transactional annotation should be applied to the concrete classes instead of interfaces [according to Where should I put #Transactional annotation: at an interface definition or at an implementing class?
Transactional annotation should be applied on the Service level [according to Spring #Transactional Annotation Best Practice
If you want to exclude some public method from being annotated with Transactional when whole class is annotated you can use some propagation strategies [according to Transactional annotation on whole class + excluding a single method
Unfortunately I didn't find the answer to the question: Where it is better to put Transactional annotation - to the class or method? We can consider different situations, but mostly i am interested in the one when we have several methods which must have this annotation and some which don't.
Plus, maybe you would like to add some points to this list, that would be really great.
Here is a list of pros and (implicitly) cons I can think of.
Pro Method Level:
Easy to read: You look at a method and can tell that it is transactional without having to look at the class, its implemented interfaces or super-classes.
Explicit: The annotation clearly tells you that the method is meant to be transactional. It is not just transactional because all methods in the class are transactional.
Less unintended merging of (otherwise) independent transactions: If you call multiple transactional methods from a method that is (implicitly) transactional, then the outer transaction defines the whole transaction (unless the propagation settings are like REQUIRES_NEW or so). While this is in many cases no problem, I have seen projects getting into serious trouble due to this in the long run. Especially when it comes to pessimistic locking, it is crucial to keep transactions as independent and small as possible, so transactions need only few locks and the locks are released as soon as possible.
Pro Class Level:
Less repetitive: If you put the annotation on the class level, you do not have to annotate each and every transactional method. Some people argue that putting the annotation on each transactional method is against the DRY principle. However, IMHO, if this is against the DRY principle, then Java's private/protected/public modifiers are, too.
In my opinion it is better to mark each method with #Transactional annotation separately (to indicate that this method is updating something) instead of marking whole class. This will produce more code and can be redundant in some cases but imagin that you have for example 10 methods in your service. Nine of those methods are updating something and one is only reading. Your code is using ORM (for example Hibernate) and you have some objects managed by Hibernate in your method. During adding new logic you accidentaly changed one field in object managed by Hibernate. In this case hibernate will fire update sql insturction in method which should only read. It may produce bug which is hard to find.