Clarification on self populating cache

2,182 views
Skip to first unread message

Mohit

unread,
Sep 4, 2011, 8:10:22 PM9/4/11
to Ehcache Spring Annotations
Hi

I am not very clear about self populating cache, neither i could find
a good article on self populating cache. If you can point me to a good
article that will be a great help. I want to validate my understanding
of selfPopulatingCache and its usage with respect to Ehcache Spring
Annotation project. Here is my understanding

1. Whenever we annotate any method with selfPopulating flag set to
true, CacheEntryFactory is automatically created and registered for
the method. Whenever any call to cache is made based on key, cache
knows how to get the result based on cache entry factory if the result
is not available in cache. In case more than one thread are asking for
result based on same key then only one thread goes ahead and gets the
data based on logic mentioned in cache entry factory and puts the
result in cache, rest of the threads wait till the main thread
completes the job and gets the results from cache itself.

2. There is no auto cache populating, If an element in cache expires
then steps mentioned in #1 are executed again only when next caller
asks for the result from cache based on key of the element that was
expired. It is not like that even no one is accessing the application
and an element is expired and it gets populated again automatically
based on key of object being expired and based on logic in cache entry
factory.

3. No one ever gets the stale data, If an element is expired it is
never returned to the caller.


Question:
What does self-populating-cache-scope means? (Please take an example
if possible).

Thanks
Mohit

Eric Dalquist

unread,
Sep 4, 2011, 8:42:50 PM9/4/11
to ehcache-sprin...@googlegroups.com
So the self-populating feature is mostly just using the SelfPopulatingCache construct that Ehcache provides. What the annotations library does is have some special support for automatically creating a CacheEntryFactory that essentially wraps the annotated method and passes along the original arguments to the method (a ThreadLocal is used for this) to get the value the CacheEntryFactory returns.

As you describe the biggest benefit to this is that there will only ever be one call made to the method for a key until the entry expires. I often use it for shared resources that take a long time to return, for example a DAO that gets weather data from a remote feed. In that example there is no point to have N concurrent users all making the same 8 second HTTP request on a miss, it is better to have 1 thread make the request and the other N-1 threads just wait and use the data retrieved by the first thread.

As for scope, the SelfPopulatingCache class is a decorator that wraps an Ehcache instance. If you set the scope to shared (the default) all @Cacheable annotations that refer to cache X with selfPopulating set to true will use the same SelfPopulatingCache instance which means they all share the same locks and only one of the methods can be invoked at a time. If you set the scope to method a SelfPopulatingCache instance is created for each method so the locking is scoped to each method. I hope that helps, if not I can see about providing some pseudo-code examples.

We did add a refreshing construct in trunk. Take a look at the refreshInterval on the @Cacheable annotation in the javadocs below. You also need to specify the scheduler and executor attributes on the <ehcache:annotation-driven> element which are used to do the background processing to refresh cached elements.

https://ehcache-spring-annotations.ci.cloudbees.com/job/ehcache-spring-annotations_trunk-site/ws/core/target/site/apidocs/index.html
http://code.google.com/p/ehcache-spring-annotations/source/browse/trunk/core/src/main/resources/com/googlecode/ehcache/annotations/ehcache-spring-1.2.xsd

I'm still not wholly comfortable with the feature. The entire Object[] of arguments is stored in the cache element meaning you need to be very careful of the following:
-That your key arguments are immutable (if they are changed by reference the key is never recomputed and your cached value essentially gets "lost" in the cache)
-That your key arguments are not going to cause memory issues by sticking around "forever", where forever is the duration of the cache timeout.
-That there is NO Thread specific context data used by the annotated method or any method that it calls. Things like the Thread ContextClassLoader and ThreadLocals cannot be copied by the annotations library and made available in the refresh thread so they either will have no value or the incorrect value.

Abhijit

unread,
Apr 12, 2012, 1:18:37 PM4/12/12
to ehcache-sprin...@googlegroups.com
Hi Eric, 

I have to integrate spring and ehcache, and trying to implement it with blockingCache pattern 

Code:
<ehcache:annotation-driven/>
there is one option for self-populating-cache-scope for shared (default) and method.

There is also the annotation @Cacheable with selfPopulating flag 

As per my understanding of your comments when shared is used only one instance is created and the same used everytime the same cache name is used so if I use the selfPopulating flag as true for one method, all the threads trying to access other methods annotated with @Cacheable with selfPopulating flag set to true will go on hold which I dont want

Code:
<ehcache:annotation-driven/>
when self-populating-cache-scope = method on other hand creates separate instances for all methods annotated with @Cacheable with selfPopulating flag set to true so it doesn't create a problem. does it also create a new instance for methods which isnt annotated without selfPopulating flag

Also in this case(scope=method) when I try to remove a element using @TriggerRemove and giving the cache name used in @Cacheable will it search in each of those separate instances to find the value? Isnt this an overhead?  

Regards,
Abhijit

Eric Dalquist

unread,
Apr 12, 2012, 2:00:49 PM4/12/12
to ehcache-sprin...@googlegroups.com
In all cases there is one underlying Ehcache instance. What happens when you set selfPopulating=true is a SelfPopulatingCache wrapper is created.

If cache-scope=shared then all annotations using that named cache will use the same SelfPopulatingCache wrapper
If cache-scope=method then one wrapper is created per method

Note in both cases the SelfPopulatingCache is a wrapper, there is still only one actual cache backing the wrapper(s)


As for blocking, If you read the docs for SelfPopulatingCache and BlockingCache you'll notice that ehcache does a compromise between cache level locking and per-key locking via key striping. http://ehcache.org/apidocs/net/sf/ehcache/constructs/blocking/BlockingCache.html


-Eric
Reply all
Reply to author
Forward
0 new messages