Automatic expiry of objects from Hashmap - caching

I have a static hashmap which I am using to cache objects in it. The objects are of different types including lists and hashmaps.
I want to invalidate the objects from the cache after certain time interval. I could add a timestamp to my objects and invalidate them manually. But, I don't know if there is any way I could find the timestamp of when a list was added to the hashmap.
Any comments or suggestions?

Have all the objects which you store in your Hashmap implement a single Expirable interface:
public interface Expirable {
public Date getExpiryDate();
}
Once done you'll easily be able to iterate through each element in your Hashmap and remove those which have expired.

The Guava interface com.google.common.cache.Cache can be accessed as a map by calling Cache.asMap().
Refer to CacheBuilder for documentation, specifically the expireAfterWrite() method.

Related

#Cacheable() not returning proper cache

I am well aware that there are multiple questions on this topic, but I just can't get the sense of it. The problem seems to be that #CachePut does not add the new value to the #Cacheable list.
After debugging the problem I found out that the problem seems to be in the key.
Here is the code snippet
#CacheConfig(cacheNames = "documents")
interface DocumentRepository {
#CachePut(key = "#a0.id")
Document save(Document document);
#Cacheable()
List<Document> findAll();
}
So when I invoke the save method, the key being used for caching is incrementing integer, or 1,2,3...
But when I try to get all documents, the cache uses SimpleKey[] as key. If I try to use the same key for #Cacheable, I get SpelEvaluationException, property 'id' cannot be found on null.
So what I am left with at the end is functional cache (the data is saved in the cache), but somehow I am not able to retrieve it.
The underlying cache implementation is EhCache.
I really don't understand what you are expecting here.
It looks like you expect your findAll method to return the full content of the cache named documents. I don't think there is anything in the documentation that can let you conclude that this feature exists (it does not). It is also very fragile. If we were implementing that, findAll would return different results based on the state of the cache. If someone would configure this cache to have a max size of 100 for instance. Or If the cache isn't warm-up on startup.
You can't expect a cache abstraction (or even a cache library) to maintain a synchronized view of "a list of objects". What findAll does is returning the entry that corresponds to a key with no argument (new SimpleKey by default).

cachemanager.net - How to get List of objects from redis cache based on key passed?

How do I get a List of objects from redis cache based on the key passed?
I am exploring cachemanager.net for redis cache. I have gone through the examples. But I could not find any example related to getting the List of objects based on the key passed.
var lst =cache.Get("Key_1");
It is returning only one object.
But I would like it like this. I have stored 1000 objects in cache with key name like Key_1, Key_2, Key_3..... Key_1000. I want to get list of 1000 objects if I pass Key_* as Key.
CacheManager does not provide any functionality to search keys or get many keys via wildcard. That's simply not how caches work.
As Karthikeyan pointed out, in Redis you could use the keys operator, but that's not a good solution and should only be used for debugging manually. Other cache systems don't even have something like that, therefore CacheManager also cannot provide that feature. Hope that makes sense ;)
With CacheManager, you can either store all your objects in one cache key and cache the list. That might have some limitations if you use redis because serialization might be become an issue.
Or, you store each object separately and retrieve them in a loop. The redis client will optimize certain things, also, in CacheManager, if you have 2 layers of caching, the performance will get better over time.
You can use redis hash instead. And you can use hgetall command to retrieve all the values in that hash.
http://redis.io/commands#hash
Or if you want to use a normal key Value pair you have to write a lua script to achieve it.
local keys = redis.call('keys','key_*')
return redis.call('mget',keys)
Keys is not advisable in production as it is blocking.
You can use scan command instead of keys to get all the keys matching that pattern and then follow the same procedure to achieve the same.

Spring/EhCache removing specific keys from the cache

#Cacheable(cacheName = "cacheOne")
public Map<String, Object> getSomeData(List<String> taglist,String queryString) {
I am using ehcache with Spring as shown in the code above. I can clear all the keys in cacheOne by doing this :
cacheManager.getCache("cacheOne").removeAll();
But what if I need to remove only those keys from this cache where taglist contains a particular tag? For e.g. I want to remove all the entries in cacheOne where there taglist contains a tag cricket?
I am afraid what you are asking will be on your shoulders.
What you are requesting, in addition to the caching you already perform, is a mapping between tags (cricket in your example) and the keys that contain these tags.
In order to store this mapping, you probably need to devise your own KeyGenerator that will keep track of this mapping in parallel of creating the cache key.
This mapping could even be smart if only a subset of tags are concerned by this purge need.
By default Spring will not keep track of that information for you, so you will not have a configuration based way of doing it.
The other option - not recommended - is to brute force by iterating over all the keys. And it should be pretty clear why this is a bad idea as soon as your dataset grows.

How to bind Maps of Maps, or some other way to structure the data

I am not even sure how to go about asking this, but I will try to give it a shot.
I have an existing application that I support that consists of a dynamically generated form of a bunch of values. The form is broken into a matrix of rows and columns, and the JSP uses this information to construct the required form:inputs. To build the form I have some Java classes like such (mostly pseudo code just so you get an idea as to what I am doing):
class Form {
List<FormParts> parts;
}
class FormParts {
List<FormRow> rows;
List<FormHeader> headers;
}
class FormRow {
String name;
}
class FormHeader {
String name;
}
I use these classes to dynamically build the form in the JSP by looping through the FormParts, then using the FormRows and FormHeaders to build a table of form:inputs, using a counter to index the resulting answers List described here in the FormResponse:
class FormResponse {
List<FormAnswer> answers;
}
class FormAnswer {
int rowNumber;
int headerNumber;
String value;
}
The problem I am having is the List<FormAnswer> answers. Because it's a List I have to store all the Answers, even the empty ones (nulls), in order to be able to provide the ability to reload the FormResponses from the DB. This is creating a HUGE amount of junk rows in my table, and making the application slow. When I first wrote this about 4 months ago, however, I remember I struggled for some time trying to figure out how to make Spring MVC bind to a Map of Maps, which would be a MUCH better way to implement this since I could simply skip the answers I don't need. I remember the problem was that, internally in Spring MVC, those Lists and Maps become LazyList and LazyMap.
Does anyone have another possible solution to this?
Check my answer on dynamic forms with Spring here at Auto populating Set .
The key is to use Map<Integer, YourObject> instead of lists. With that you can have gaps in your indexes.
Using Map of Maps is not possible, because the generics will be erased. The map always need to be property of object. So your example should be OK.
Concept of LazyList / LazyMap is long dead. Spring is capable of manipulating any list and map type. If the Map property is null, an instance of LinkedHashMap is created by default.
Other possibility is to do your binding and validation manually and just send JSON via the wire (i.e. submit your form as JSON in <input type="hidden"> or directly via AJAX).

java customize a hashmap values

I am working on using a real time application in java, I have a data structure that looks like this.
HashMap<Integer, Object> myMap;
now this works really well for storing the data that I need but it kills me on getting data out. The underlying problems that I run into is that if i call
Collection<Object> myObjects = myMap.values();
Iterator<object> it = myObjects.iterator();
while(it.hasNext(){ object o = it.next(); }
I declare the iterator and collection as variable in my class, and assign them each iteration, but iterating over the collection is very slow. This is a real time application so need to iterate at least 25x per second.
Looking at the profiler I see that there is a new instance of the iterator being created every update.
I was thinking of two ways of possibly changing the hashmap to possibly fix my problems.
1. cache the iterator somehow although i'm not sure if that's possible.
2. possibly changing the return type of hashmap.values() to return a list instead of a collection
3. use a different data structure but I don't know what I could use.
If this is still open use Google Guava collections. They have things like multiMap for the structures you are defining. Ok, these might not be an exact replacement, but close:
From the website here: https://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained
Every experienced Java programmer has, at one point or another, implemented a Map> or Map>, and dealt with the awkwardness of that structure. For example, Map> is a typical way to represent an unlabeled directed graph. Guava's Multimap framework makes it easy to handle a mapping from keys to multiple values. A Multimap is a general way to associate keys with arbitrarily many values.

Resources