How to store element permanently in echcache - ehcache

I am using ehcahce for caching. how do i store elements permanently in ehcache.
CacheManager cacheManager = CacheManager.getInstance();
cacheManager.addCache("test");
cache = cacheManager.getCache("test");

Related

Add Cache in a class

I have a impl class where I have 2 update methods , method1 is updating complete row in DB whereas method2 is updating only one column in DB of that table.
Now I need to use #Caceable and #CacheEvict here , How can I use in this condition ?
From Spring 3.1 introduces a new feature to allow methods to be cached and evicted thus allowing resource heavy methods to be avoided where possible. Caching is enabled via the new #Cacheable and #CacheEvict annotations.
One example of caching would be, for example, database activity. We can apply the #Cacheable annotation to a find operation and then apply the #CacheEvict to an update / delete operation. In this sense, caching would work much like a second level cache in Hibernate or JPA.
To enable caching on a find method, the method needs to be annotated with the #Cacheable annotation identifying which cache to use. Spring allows multiple caches to be defined each of which can be backed by a different caching abstraction.
#Cacheable("items") //#Cacheable(value = "items", key = "#itemId")
public Item find(long itemId) {
Item item = entityManager.find(Item.class, itemId);
return item;
}
When it is time to invoke the find method, Spring checks in the specified cache to see if the results of the operation have already been cached and if the results can be therefore be returned from cache instead of invoking the method. Spring uses the method arguments as the key, so in this case the itemId parameter.
To evict an entry from the cache when an object is updated in the database, the #CacheEvict annotation can be used. Again, this annotation takes a parameter identifying which cache to use.
#CacheEvict(value = "items", key = "#item.id")
public void updateItem(Item item) {
entityManager.merge(item);
}
EDIT:
#CacheEvict
Used for Cache-removal /cache-cleanup operation. #CacheEvict annotation indicates that a method (or all methods on a class) triggers a cache evict operation, removing specific [or all] items from cache. Various attributes provides complete control to enforce the required behavior for cache-eviction.
for example,
#CacheEvict(value = "products", key = "#product.name")
public void refreshProduct(Product product) {
//This method will remove only this specific product from 'products' cache.
}
#CacheEvict(value = "products", allEntries = true)
public void refreshAllProducts() {
//This method will remove all 'products' from cache, say as a result of flush-all API.
}

How to evict Cache based on Cache Name passed

I am calling fetchCatchAndClear method where I am passing List and it consists of cache names. Can someone help me how to iterate over the list and clear the cache based on the Cache Name coming from List of String. Also if the list is empty I should clear all the caches present.
A rather simple approach which sticks to the org.springframework.cache.CacheManager could be the following:
List<String> cacheNames = List.of("aCache", "anotherCache"); // the list you are passing in
CacheManager cacheManager = new SimpleCacheManager(); // any cache manager you are injecting from anywhere
// a simple iteration, exception handling omitted for readability reasons
cacheNames.forEach(cacheName -> cacheManager.getCache(cacheName).clear());
Evicting all caches is also that simple, except that you have to query the relevant cache names from the very same cache manager:
CacheManager cacheManager = new SimpleCacheManager();
Collection<String> cacheNames = cacheManager.getCacheNames();
cacheNames.forEach(cacheName -> cacheManager.getCache(cacheName).clear());
If you just want to evict a single cache entry you could either do it programmatically like:
cacheManager.getCache(cacheName).evict(cacheKey); or annotation-based like
#CacheEvict(value = "yourCacheName", key = "#cacheKey")
public void evictSingleCacheValue(String cacheKey) {
}
#CacheEvict(value = "yourCacheName", allEntries = true)
public void evictAllCacheValues() {
}

Configuration for specific Caffeine Caches in Spring

We need to implement several methods that have different caching times. Each method is annotated with #Cacheable and our current solution includes multiple CacheManager that are set in a CachingConfigurerSupport.
public class CachingConfiguration extends CachingConfigurerSupport {
#Override
#Bean
public CacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
cacheManager.setCaffeine(Caffeine.newBuilder().expireAfterWrite(1, TimeUnit.DAYS));
return cacheManager;
}
#Bean
public CacheManager anotherCache() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
cacheManager.setCaffeine(Caffeine.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES));
return cacheManager;
}
}
The #Cacheable annotation then included the cacheManager:
#Cacheable(cacheNames = "someCache", cacheManager = "anotherCache")
Basically that's fine but is also errorprune if you forget the cacheManager parameter etc.
So I currently try to find a better solution but as far as I can see, there is currently no general accepted way to go.
Imho the main advantage of the CaffeineCacheManager compared to e.g. SimpleCacheManager is the possibility to define a base configuration and then initialize additional caches lazily. But wouldn't it be great if you are able to set additional caches which are never reinitialized?
Those caches must be used preferentially and created in the CachingConfigurerSupport.
Maybe I'm missing something, but shouldn't this solve the problem that has already been discussed in several threads in different forms?
Recently I decided to turn my initial PR into a separate tiny project.
To start using it just add the latest dependency from Maven Central:
<dependency>
<groupId>io.github.stepio.coffee-boots</groupId>
<artifactId>coffee-boots</artifactId>
<version>2.0.0</version>
</dependency>
Format of properties is the following:
coffee-boots.cache.spec.myCache=maximumSize=100000,expireAfterWrite=1m
If no specific configuration is defined, CacheManager defaults to Spring's behavior.
Simple way without any thrid-party lib:
spring.cache.type=caffeine
# default spec (optional)
spring.cache.caffeine.spec=maximumSize=250,expireAfterWrite=15m
# specific specs (also optional)
caffeine.specs.places=maximumSize=1000,expireAfterWrite=1h
Register custom caches:
applicationContext.registerBean { context ->
CacheManagerCustomizer<CaffeineCacheManager> { cacheManager ->
for (spec in Binder.get(context.environment).bindOrCreate("caffeine.specs", HashMap::class.java)) {
cacheManager.registerCustomCache(spec.key.toString(), Caffeine.from(spec.value.toString()).build())
}
}
}

EhCache Memory limit

In my code I am using EhCache to store an object. Code is below
#Resource(name = "ehCacheManager")
private CacheManager manager;
private Ehcache cache;
public void testCache(){
cache = manager.getCache("ehSubjects");
for loop to read subjects data{ //This loops runs 15051 times
final Element element = new Element(subject.subjectId(), subject);
cache.put(element);
}
}
System.out.println("Cache Size:"+cache.getSize()); //15000
The issue is there are 15051 subjects objects but when after the loop I try to print the cache size it always gives me 15000.
So is there a limit on the amount of objects we can keep in EhCache?
The issue was with the ehcache.xml defined by the other team mate. He has given the maxitemsincache value as 15000 due to which cahce was ignoring other items.

Ehcache Cache Server + BlockingCache ?

Is it possible to use Ehcache Cache Server and have it be configured with blockingCache ? I cant seem to find how to configure this in the ehcache.xml file... only programatically.
To use BlockingCache as the default decorator for your cache via ehcache.xml, first you should implement your own CacheDecoratorFactory, say it's DefaultCacheDecoratorFactory:
public class DefaultCacheDecoratorFactory extends CacheDecoratorFactory {
#Override
public Ehcache createDecoratedEhcache(Ehcache cache, Properties properties) {
return new BlockingCache(cache);
}
#Override
public Ehcache createDefaultDecoratedEhcache(Ehcache cache, Properties properties) {
return new BlockingCache(cache);
}
}
then configure it as part of your cache definition, like this:
<cache name="CACHE_NAME" more values here.../>
<cacheDecoratorFactory class="whatsoever.DefaultCacheDecoratorFactory"/>
</cache>
And using cacheManager.getEhCache() to access the cache other than cacheManager.getCache(), because it only returns null for your decorated cache.
You can declare decorated caches programmatically, but also in configuration, see:
http://ehcache.org/documentation/apis/cache-decorators#by-configuration
You'd need to add a net.sf.ehcache.constructs.CacheDecoratorFactory implementation that does what you need. I guess in you're case it could do some pattern matching against the Ehcache instance passed to the net.sf.ehcache.constructs.CacheDecoratorFactory#createDecoratedEhcache and return either null, or the cache instance decorated by the BlockingCache.
Word of caution though, is to make sure that on misses, you always put back (even null) into the cache, otherwise the write lock for that key/segment won't be unlocked.

Resources