10

I'm using EHCache 3.5.2 and having trouble getting all cache keys and cache entries.

I am using the CacheManager to create a cache. I'm then populating it with some data. I'd then like to retrieve all entries in the cache.

Some sample code:

Cache<String, Foo> cache = cacheManager.createCache("fooCache",
     CacheConfigurationBuilder.newCacheConfigurationBuilder(String.class, Foo.class,
         ResourcePoolsBuilder.heap(20)).build());

cache.putAll(repository.findAll().stream().collect(toMap(Foo::getId, foo -> foo)));

List<Foo> foos = cache.???
List<String> keys = cache.???

Is this possible with v3.5? It seems it was possible in older versions of EHCache.

thanks

robjwilkins
  • 5,462
  • 5
  • 43
  • 59

3 Answers3

8

Why not something like this?

Map<String, Foo> foos = StreamSupport.stream(cache.spliterator(), false)
  .collect(Collectors.toMap(Cache.Entry::getKey, Cache.Entry::getValue));

or

List<Cache.Entry<String, Foo>> foos = StreamSupport.stream(cache.spliterator(), false)
  .collect(Collectors.toList());

or (old style)

List<Cache.Entry<String, Foo>> foos = new ArrayList<>();
for(Cache.Entry<String, Foo> entry : cache) {
  foos.add(entry);
}
Henri
  • 5,551
  • 1
  • 22
  • 29
  • thanks for the reply. I'm surprised there isn't an easy way to do this and I think I prefer my solution as it seems simpler, but I'll up vote your answer anyway – robjwilkins May 17 '18 at 11:04
  • Thanks. It is more related to the JDK. The Cache is iterable but not a Collection. So forEach is not available. But my solution is much more efficient and standard actually. Collecting all the keys and then getting them will be memory and CPU expensive. You can also use a good old `for(:)` if needed. I will update the answer accordingly. – Henri May 18 '18 at 17:17
8

By design, this is not a simple API call in Ehcache. Because of the tiering model it supports, realising all keys or values on heap could cause the JVM to run out of memory.

As shown by the other answers, there are ways to achieve this.

But it is considered a caching anti-pattern to have to get the whole content of the cache at once.

Louis Jacomet
  • 13,661
  • 2
  • 34
  • 43
  • I have a configuration in database, it's a table with 5 fields and 400 records. I would like to load it first in the class (from ehCache) and then use. Is it still bad pattern? – Line Aug 25 '20 at 13:28
4

I have found a way to do this, but it smells a bit:

Set<String> keys = new HashSet<>();
cache.forEach(entry -> keys.add(entry.getKey()));

List<Foo> foos = cache.getAll(keys).values().stream().collect(toList())
robjwilkins
  • 5,462
  • 5
  • 43
  • 59