Ehcache Cache Server + BlockingCache ? - ehcache

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.

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.
}

Spring Boot Cache Bulk and Access Individually

Accessing the DB repeatedly for individual entities is much slower than doing a bulk select. How do I cache a the result of a bulk select into a cache, and later access it individually?
For example, I have a Employee entity:
public class Employee {
private Integer id;
}
And I have repository that can access it either with bulk select, or individually by id:
public class EmployeeRepository {
public Map<Integer, Employee> retrieveByEmployeeIds(List<Integer> ids) {
// impl
}
public Employee retrieveByEmployeeId(Integer id) {
// impl
}
}
How do I implement it so that when retrieveByEmployeeId(Integer id) is called it will check the same cache as retrieveByEmployeeIds(List<Integer> ids), and if it doesn't exist it'll make a call to the DB, and also storing that cache with the id again?
I have answered similar questions before, for example see (Spring Cache with collection of items/entities).
Essentially, you must implement a custom CacheManager and Cache, the 2 primary interfaces that form the basis of Spring's Cache Abstraction, as described here. It may even extend or delegate to an existing caching provider, but you must "decorate" the existing functionality.
The link I referred to above also contains examples.
Hope this helps give you ideas on how to handle your particular UC.

How to cache REST API response in java

I am building an app in java.I hit api more than 15000 times in loop and get the response ( response is static only )
Example
**
username in for loop
GET api.someapi/username
processing
end loop
**
It is taking hours to complete all the calls. Suggest me any way (any cache technology) to reduce the call time.
P.S :
1) i am hitting api from java rest client(Spring resttemplate)
2) that api i am hitting is the public one, not developed by me
3) gonna deploy in heroku
Try using Springs Cache Abstraction, docs.spring.io/spring/docs/current/spring-framework-reference/html/cache.html.
You can use this abstraction in the method which has the restTemplate call.
Any method calls response can be cached using this abstraction, with the method parameters as the keys and the return type as the response.
#Cacheable("username")
public UserResponse getUser(String username){
// Code to call your rest api
}
This creates a Spring AOP advice around the method. Every time the method is called it checks if the data is available in the cache for this key(username), if yes then returns the response from the Cache and not calls the actual method. If the data is not available in the Cache then it calls the actual method and caches the data in the cache, so next time when the same method is called with same key the data can be picked from Cache.
This cache abstraction can be backed by simple JVM caches like Guava or more sophisticated cache implementations like EHCache, Redis, HazelCast as well.
One very important note to that answer: If you ever plan to update those (cached) values, don't forget to use #CacheEvict on save() and delete() in the repositories. Else you will have problems fetching the new record when it is updated.
I have implemented my solution (with EhCache) this way (in the repository):
CurrencyRepository.java:
// define a cacheable statement
#Cacheable("currencyByIdentifier")
public Currency findOneByIdentifier(String identifier);
CacheConfiguration.java: // Define that cache in EhCache Configuration
#Bean
public JCacheManagerCustomizer cacheManagerCustomizer() {
return cm -> {
cm.createCache("currencyByIdentifier", jcacheConfiguration);
cm.createCache("sourceSystemByIdentifier", jcacheConfiguration);
};
}
CurrencyRepository.java:
// evict on save and delete by overriding the default method
#Override
#CacheEvict("currencyByIdentifier")
<S extends Currency> S save(S currency);
#Override
#CacheEvict("currencyByIdentifier")
void delete(Currency currency);
I hope that helps :)

Spring Constraint Validation Context - Database Request Caching

I've written a custom Validation Annotation and a ConstraintValidator implementation, which uses a Spring Service (and executes a Database Query):
public class MyValidator implements ConstraintValidator<MyValidationAnnotation, String> {
private final MyService service;
public MyValidator(MyService service) {
this.service = service;
}
#Override
public void initialize(MyValidationAnnotation constraintAnnotation) {}
#Override
public boolean isValid(String value, ConstraintValidatorContext context) {
return service.exists(value);
}
}
It's used like this:
public class MyEntity {
#Valid
List<Foo> list;
}
public class Foo {
#MyValidationAnnotation
String id;
}
This works quite nice, but service.exists(value) is getting called for every item within the list, which is correct, but could/should be optimized.
Question:
When validating an instance of MyEntity, I'd like to cache the results of the service.exists(value) calls.
I don't want to use a static HashMap<String, Boolean>, because this would cache the results for the entire application lifetime.
Is it possible to access some kind of Constraint Validation Context, which only exists while this particular validation is running, so I can put there the cached results?
Or do you have some other solution?
Thanks in advance!
You can use Spring's cache support. There might be other parts in the application which needs caching and this can be reused. And the setup is very simple too. And it will keep your code neat and readable.
You can cache your service calls. You need to put annotation on your service methods and a little bit of configuration.
And for cache provider you can use Ehcache. You have many options like setting ttl and max number of elements that can be cached and eviction policy etc etc if needed.
Or you can implement your own cache provider if your needs are simple. And if it is web request, In this cache you may find ThreadLocal to be useful. you can do all caching for this running thread using threadlocal. When the request is processed you can clear the threadlocal cache.

Spring caching / spring repository, evict multiple keys

I have two methods to fetch an entity with two different parameters. I also have a save method that uses one of those parameters. How can I evict the entity from the cache under both fetch keys? e.g. see below:
#Cacheable
public User getByUsername(String username);
#Cacheable
public User getByEmail(String email);
#CacheEvict(key="#entity.username")
User save(User entity);
In the above, a call to getByEmail will return stale date.
There are several options, of course, but as usual, Spring has your back.
The easiest and most simple approach is to leverage Spring's #Caching annotation on your save method, like so...
#Caching(evict = {
#CacheEvict(cacheNames = "Users", key="#user.name"),
#CacheEvict(cacheNames = "Users", key="#user.email")
})
User save(User user);
For your reference, I created an example test class demonstrating this working here.
You will notice I imitated your example above using Spring's Cache Abstraction annotations on my UserRepository. In this case, my repo is backed by Pivotal GemFire, but any data store will work. I use a ConcurrentMap as my caching provider, using Spring's ConcurrentMapCacheManager, but of course, any caching provider will do.
My test case proceeds to save a new User, ensuring that the user is stored by not yet cached. The test then proceeds to exercise the query methods (findByName, findByEmail) ensuring that the user entity is cached appropriately in each case. I then remove the entity from the underlying data store and ensure that the entity is still cached. And finally, the moment of truth, I modify the entity, re-save the entity, asserting that the entity is stored by that all entries have been "evicted" from the cache.
You could also try, as another optimization, to combine the #CachePut annotation with the 2 #CacheEvict annotations in this case, which could restore the cache based on the new, updated entity, something like...
#Caching(
evict = {
#CacheEvict(cacheNames = "Users", key="#a0.name", beforeInvocation = true),
#CacheEvict(cacheNames = "Users", key="#a0.email", beforeInvocation = true)
},
put = {
#CachePut(cacheNames = "Users", key="#result.name"),
#CachePut(cacheNames = "Users", key="#result.email")
}
)
User save(User user);
NOTE: notice the user of the beforeInvocation attribute on the #CacheEvict annotations along with the #CachePuts
However, you may prefer that the entity be lazily added to the cache based on need.
Although, you would presume the entity is being frequently accessed/used since the save method on your repo was just called, and therefore rely on your underlying data store (such as GemFire) to set additional eviction (based on overflow)/expiration (based on LRU) settings, thereby better managing your system resources (e.g. memory) while still maintaining optimal application performance.
Food for thought.
Hope this helps.

Resources